Поток - это объект операционной системы. Ну там завернутый в какую-то обертку языка и стандартной библиотеки. Он работает с байтами. Для распознавания кодировок и конверсии байтов в стринги должны применяться кодеки. Парсинг текста это вообще достаточно нетривиальная операция. CSV, XML, YAML или Json можно прочитать библиотекой, для прочих кейсов в общем случае ANTLR или Flex/Bison. Говорят что boost::spirit вполне годен, но я не любитель сложных шаблонов. То есть чтобы прочитать сложный файл нужно собрать композицию из объектов Parser(Lexer(Codec(raw_input_stream))). Это нормальное техническое решение, напоминающее конвейер по принципу работы. Ну или цепочку "сопрограмм", как их называет Дональд Кнут.Как раз этот функционал к потоку вообще не относится.
Потомок std::ofstream, не работает манипулятор
Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain
-
- Сообщения: 1228
- Зарегистрирован: 26 фев 2004, 13:24
- Откуда: Pietari, Venäjä
- Контактная информация:
2B OR NOT(2B) = FF
Он не работает с байтами. Это объект. И работает он со значениями без отрыва от интерпретации байтов. Именно поэтому не надо отдельно заботиться о переводе числа из внутреннего представления в строковое, за это отвечает поток. Если внутреннее представление какого то типа совпадает с форматом файла, или экранного буфера, тогда именно для него высокоуровневый потоковый вывод есть вывод сырых байтов. В остальных случаях нет. Поток вывода берёт на себя кодирование в целевой формат, а поток вывода - раскодирование из имеющегося формата. Иначе это не поток ввода-вывода, не путайте с протоколом TCP, где термин "поток" имеет иное значение и означает лишь прозрачность границ пакета.
Это при парсинге связного текста, при вводе отдельных значений известных типов в ожидаемом порядке парсинг берёт на себя поток, а при выводе задача парсинга вообще не стоит.То есть чтобы прочитать сложный файл нужно собрать композицию из объектов Parser(Lexer(Codec(raw_input_stream)))
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
-
- Сообщения: 1228
- Зарегистрирован: 26 фев 2004, 13:24
- Откуда: Pietari, Venäjä
- Контактная информация:
Один класс должен делать одно дело и делать его хорошо. Кроме того, он должен иметь минимальный интерфейс. Сложный функционал должен быть вынесен наружу. Должно быть легко строить произвольные композиции из разных объектов для того чтобы справляться с комбинаторным ростом сложности проекта. iostream же делает две или три вещи, скрывая детали под капотом. Т.е. он скрывает в себе кодек, лексер и даже пытается делать парсинг через перегрузки операторов << и >> для сложных типов. Интерфейс у него сложный, громоздкий и начисто лишен всякого изящества. Расширять его сложно. Попробуй вот ostream обернуть тем же lzw кодированием - там черт ногу сломает. Лично я не сунусь туда никогда. Хотя для FILE* это сделать тривиально, засунуть там несколько коллбэков в Си-структуру. Многие реализации это позволяют.Сионист писал(а):Он не работает с байтами. Это объект. И работает он со значениями без отрыва от интерпретации байтов. Именно поэтому не надо отдельно заботиться о переводе числа из внутреннего представления в строковое, за это отвечает поток.
Стоит задача форматирования.а при выводе задача парсинга вообще не стоит.
2B OR NOT(2B) = FF
Эйси. Тогда на него нельзя сверху навешать ни какой класс. В итоге программу в целом ООП не упростит, а усложнит. Интерфейс класса должен быть оптимален и вытекать из назначения, а минимальный - это к протоколам первого уровня.Один класс должен делать одно дело и делать его хорошо. Кроме того, он должен иметь минимальный интерфейс.
Для отдельных значений она столь же проста, не путайте свалку записей с осмысленным связным текстом, абстракция потока ввода-вывода лишь на один уровень выше функций ReadFile и WriteFile и ни какой сложный парсинг на этом уровне не предусмотрен, как и сложное форматирование.Стоит задача форматирования.
Для сокращения комбинаторной проекта в целом надо сокращать количество связей и участвующих в них сущностей, а не упрощать составляющие проекта. А по-Вашему простейшим языком программирования является язык ассемблера. На самом же деле он уступает в сложности лишь программированию в опкодах.Должно быть легко строить произвольные композиции из разных объектов для того чтобы справляться с комбинаторным ростом сложности проекта.
Как минимум четыре. Но разве это один класс?iostream же делает две или три вещи, скрывая детали под капотом.
Куда уж проще.Интерфейс у него сложный, громоздкий и начисто лишен всякого изящества.
Правильно. Потому что этого не надо делать.Попробуй вот ostream обернуть тем же lzw кодированием - там черт ногу сломает. Лично я не сунусь туда никогда.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
-
- Сообщения: 1228
- Зарегистрирован: 26 фев 2004, 13:24
- Откуда: Pietari, Venäjä
- Контактная информация:
Сионист писал(а):Эйси. Тогда на него нельзя сверху навешать ни какой класс. В итоге программу в целом ООП не упростит, а усложнит. Интерфейс класса должен быть оптимален и вытекать из назначения, а минимальный - это к протоколам первого уровня.
Что такое "Навешивать сверху"? Я знаю отношения наследования, агрегирования и использования.
Этот тред создал ты, я не я. У меня-то никаких проблем с iostream нет, я использую только два метода - read и write. Использовал бы Win32, POSIX или C stdio, но общий знаменатель для всех библиотек с которыми я в данный момент работаю это iostream.Куда уж проще.Интерфейс у него сложный, громоздкий и начисто лишен всякого изящества.
Ну вообще-то в рамках общепринятой современной парадигмы принято считать что для этого нужно предпочитать слабые зависимости сильным. В частности, по возможности применять использование вместо агрегирования и агрегирование вместо наследования. Парсер, лексер, кодек, враппер вокруг сисколла в одном флаконе это перпендикулярный подход общепринятой современной парадигме.Для сокращения комбинаторной проекта в целом надо сокращать количество связей и участвующих в них сущностей, а не упрощать составляющие проекта.
Хорошие абстракции упрощают а не усложняют работу. Проблема только в том что в iostream абстракции плохие.А по-Вашему простейшим языком программирования является язык ассемблера.
А если мне нужно поток байт сжимать на лету? lzw - потоковый алгоритм, он может это делать. Зачем вообще все это ООП нужно тогда?Правильно. Потому что этого не надо делать.Попробуй вот ostream обернуть тем же lzw кодированием - там черт ногу сломает. Лично я не сунусь туда никогда.
2B OR NOT(2B) = FF
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Скажу прямо, пробовал хреново. Какой же ты программист, если не можешь найти в папке компилятора место, где расположен системный хедер и открыть его? Хорошо, я подскажу тебе, в MinGW стандартные С++ хедеры действительно упрятаны в нелогичное место, например у меня они лежат вот тут:Сионист писал(а):Не открывается.
Но их нестандартное расположение не отменяет необходимость наличия у программиста (да что там, даже у обычного пользователя) умения производить поиск файлов на жёстком диске.\MinGW\lib\gcc\mingw32\4.8.1\include\c++\
И так, теперь мы открываем файл ostream и смотрим, как объявлен оператор вывода для сишных строк:
Код: Выделить всё
template<typename _CharT, typename _Traits>
inline basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __out, const _CharT* __s)
Для std::string ищем оператор в хедере, где объявлен сам класс std::string. Там он тоже внешний.
Думаю, продолжать не стоит.
А теперь вернёмся к нашей изначальной проблеме. Как заставить работать указанный код? Достаточно сделать твои операторы внешними. И всех делов-то.
Код: Выделить всё
#include <iostream>
#include <fstream>
class TMyStream : public std::ofstream { };
TMyStream& operator << (TMyStream& os, const char* String)
{
(std::ofstream&)os << "Specific narrow string operator: " << String;
return os;
}
TMyStream& operator << (TMyStream& os, const wchar_t* String)
{
(std::ofstream&)os << "Specific wide string operator: " << String;
return os;
}
int main()
{
TMyStream stream;
stream.open("D:\\Temp\\temp.txt");
stream << "Test" << std::endl;
stream << L"Test" << std::endl;
return 0;
}
Как видишь, манипуляторы прекрасно работают и никакие костыли с оператором, принимающим указатель на функцию, не нужны.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ну это собирательная обзывалка для всего перечисленного. Разумеется не официальная и термином не являющаяся.Absurd писал(а):Что такое "Навешивать сверху"? Я знаю отношения наследования, агрегирования и использования.
Вы можете лучше нажать правую кнопку и выбрать из всплывающего меню пункт open #include <fsream>? Однако!Romeo писал(а):Скажу прямо, пробовал хреново.
Пока потомок пуст, и у меня всё работает вообще без перегрузки. Но при наличии в потомке хотябы одного оператора пришлось выкручиваться. И функцияRomeo писал(а):Как видишь, манипуляторы прекрасно работают и никакие костыли с оператором, принимающим указатель на функцию, не нужны.
Код: Выделить всё
TMyStream& endl << (TMyStream &Stream)
{
*((std: :o fstream*)(&Stream))<<std::endl;
return Stream;
}
Код: Выделить всё
TMyStream f;
...
f<<endl;
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Нет, мы можем лучше сделать поиск по имени файла на жёстком диске. И я об этом выше написал - просто ты это проигнорировал или, как обычно, не прочёл. То, что среда не нашла файл и не открыла - это детсадовская отмазка, Сионист. Вот такое вот однако.Сионист писал(а): Вы можете лучше нажать правую кнопку и выбрать из всплывающего меню пункт open #include <fsream>? Однако!
Я же тебе говорю, что операторы нужно вынести. А ты мне всё равно тылдычишь, что при наличии хоть одного оператора ничего не работает. Конечно не работает, так как у локальных операторов приоритет при подборе вызова выше, чем у глобальных. Ещё раз тебе говорю, сделай все операторы внешними, как я указал в примере, и будет тебе счастье.Сионист писал(а): Пока потомок пуст, и у меня всё работает вообще без перегрузки. Но при наличии в потомке хотябы одного оператора пришлось выкручиваться. И функция вызываться отказалась.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Так с вынесенными вообще приходится возвращать ссылку на std:
stream и принимать его же, иначе оператор << не принимает цепную форму.

Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.