Прочитал тут Google Code Style. Обратил внимание на пункт Streams, где говорится "Use streams only for logging" и "Do not use streams, except where required by a logging interface. Use printf-like routines instead".
Я, конечно, понимаю, что многие вещи в C++ — дело вкуса, но, на мой взгляд, не в данном случае. Почему? Ну, например, хотя бы поэтому:
Потоки C++ можно удобно использовать с классами путём перегрузки операторов
Сами потоки также представляют собой объекты и отлично вписываются в объектно-ориентированную структуру языка
Интуитивно-понятны (не надо вспоминать, что означает тот или иной спецификатор в строке форматирования)
Безопасны (хотя некоторые компиляторы и выдают ошибки / предупреждения на попытку некорректного использования функций семейства printf, это лишь исключения из правила — стандарт этого, разумеется, не обязывает)
Из минусов могу вспомнить лишь, как правило, более медленную работу по сравнению с теми же printf-like функциями (да и тут ещё посмотреть надо, как оно реализовано в той или иной библиотеке, поставляемой производителем компилятора, и задуматься об использовании, возможно, ещё более быстрых API-функций в случае написания платформо-зависимого кода), а также более короткие записи в случае использования многочисленных спецификаторов.
Здравствуйте, Аноним, Вы писали:
А>А что Вы думаете по этому поводу?
Всё так, только забыли главное упомянуть: неудобство форматирования вывода. Во всех языках имеется возможность удобного вывода в том или ином виде, от обычных printf-подобных и их расширений (ява, шарп) до here-doc & K°.
ЗЫ: ещё камень в потоки, хотя это уже не относится к stream vs printf: стандартные потоки завязаны исключительно на текстовой вывод, и средствами C++ вроде бы нельзя работать с бинарными файлами. Или неформатированный ввод/вывод может?
Здравствуйте, Аноним, Вы писали:
А>Прочитал тут Google Code Style. Обратил внимание на пункт Streams, где говорится "Use streams only for logging" и "Do not use streams, except where required by a logging interface. Use printf-like routines instead".
... А>А что Вы думаете по этому поводу?
Думаю, что у них были какие-то свои причины на это. Вообще, нет особого смысла обсуждать чьи-то конкретные стандарты кодирования, не зная причин появления тех или иных правил.
_DA>Думаю, что у них были какие-то свои причины на это. Вообще, нет особого смысла обсуждать чьи-то конкретные стандарты кодирования, не зная причин появления тех или иных правил.
Они объясняют это так:
Streams make it difficult to do functionality like pread(). Some formatting (particularly the common format string idiom %.*s) is difficult if not impossible to do efficiently using streams without using printf-like hacks. Streams do not support operator reordering (the %1s directive), which is helpful for internationalization
Но разве этого достаточно, чтобы говорить, что потоки C++ стоит использовать разве что для логов?
Здравствуйте, Аноним, Вы писали:
А>Интуитивно-понятны (не надо вспоминать, что означает тот или иной спецификатор в строке форматирования)
Эта интуитивная понятность кончается, когда хочется вписать результат форматирования в поле определенной ширины, или вывести число с определенной точностью — то, что в printf'е как раз делается просто и естественно.
Pzz>Эта интуитивная понятность кончается, когда хочется вписать результат форматирования в поле определенной ширины, или вывести число с определенной точностью — то, что в printf'е как раз делается просто и естественно.
Не совсем понял, честно говоря.
std::setw и std::setprecision менее понятны? Они ведь как раз описывают то, что собирается делать человек, а не используют одни лишь числа.
Я не хочу спорить — сразу же сказал, что это дело вкуса, просто интересно.
Здравствуйте, YourLastSong, Вы писали:
YLS>std::setw и std::setprecision менее понятны? Они ведь как раз описывают то, что собирается делать человек, а не используют одни лишь числа.
Меня такие модификаторы бесят тем, что в случае, если область существования потока несколько больше, чем текущий блок, ты никогда заранее не знаешь, в каком состоянии он находится и что ожидать на выходе.
Здравствуйте, ntp, Вы писали:
ntp>Здравствуйте, Аноним, Вы писали:
А>>А что Вы думаете по этому поводу? ntp>Всё так, только забыли главное упомянуть: неудобство форматирования вывода. Во всех языках имеется возможность удобного вывода в том или ином виде, от обычных printf-подобных и их расширений (ява, шарп) до here-doc & K°.
в чем именно неудобство? в том, что приходится "прерывать" строковые литералы конструкциями вида "..." << variable << "..." ??
вообще говоря это дело вкуса (и меня лично не напрягает, и местами даже не плохо выглядит -- все зависит от того как отформатировать исходник...).
кроме того, возможность использовать манипуляторы (в т.ч. свои собственные... или даже: в особенности собственные) может сильно упростить жизнь.
кроме того, имеется вполне себе навороченная библа boost::format. а для тех кто перешел на С++11 raw string literals + variadic templates помогут сделать более простую (lightweight) замену этой библе...
ntp>ЗЫ: ещё камень в потоки, хотя это уже не относится к stream vs printf: стандартные потоки завязаны исключительно на текстовой вывод, и средствами C++ вроде бы нельзя работать с бинарными файлами. Или неформатированный ввод/вывод может?
Здравствуйте, __kot3, Вы писали:
__>Здравствуйте, YourLastSong, Вы писали:
YLS>>std::setw и std::setprecision менее понятны? Они ведь как раз описывают то, что собирается делать человек, а не используют одни лишь числа.
__>Меня такие модификаторы бесят тем, что в случае, если область существования потока несколько больше, чем текущий блок, ты никогда заранее не знаешь, в каком состоянии он находится и что ожидать на выходе.
Здравствуйте, zaufi, Вы писали:
Z>в чем именно неудобство? в том, что приходится "прерывать" строковые литералы конструкциями вида "..." << variable << "..." ?? Z>вообще говоря это дело вкуса (и меня лично не напрягает, и местами даже не плохо выглядит -- все зависит от того как отформатировать исходник...).
Форматная строка может быть единицей локализации (или просто строковым ресурсом). Ты легко можешь заменить литерал «"Could not open file {0} in directory {1}."» на вызов «GetOpenErrorMessageFormat()». А если это у тебя куски типа «... << "Could not open file " << filename << " in directory " << directory << "."»?
Здравствуйте, Аноним, Вы писали:
А>Прочитал тут Google Code Style. Обратил внимание на пункт Streams, где говорится "Use streams only for logging" и "Do not use streams, except where required by a logging interface. Use printf-like routines instead".
Удивительно, что никто из обсуждавших пока что не обратил внимание на то, что вообще-то одно другому не противоречит. Видимо, потому, что Гугл противопоставляет эти два варианта.
Но никто не запрещает сделать что-то вроде
cerr << format("Error in %s: %s", module, errormessage) << endl;
причём реализация, если хорошо сделана, обойдётся без выделения места под строку.
Мне это кажется более разумным, чем stdio (о котором почему-то подумали все, кто тут отметился и говорил про printf-like), хотя бы потому, что в stdio нет стандартного варианта сделать не связанный с файлом поток. GNU libc знает fopencookie(); BSD системы знают funopen(); MSVC CRT вообще не предоставляет никакого аналога для этой функциональности, как и большинство проприетарных Unix-систем. C++ <iostream> позволяет делать потоки, не связанные с внешним файлом, штатными средствами, а с произвольным коллбэками — лёгкой доработкой, но без хака основ.
А>Потоки C++ можно удобно использовать с классами путём перегрузки операторов А>Сами потоки также представляют собой объекты и отлично вписываются в объектно-ориентированную структуру языка А>Интуитивно-понятны (не надо вспоминать, что означает тот или иной спецификатор в строке форматирования)
Вот-вот, Вы говорите о штатном управлении потоком, но привязали к потокам целиком. Лично мне давно проще вспомнить значение какого-нибудь %20.8f — хотя бы потому, что он универсален для C, Python, Perl и ещё кучи языков, и даже в Erlang похожий стиль (только ~ вместо % и в конце другой символ вместо f). А вот межъязыкового аналога <iostream> нет и, похоже, не будет. Зато возиться с FILE* в C++ мне кажется порочным, при наличии собственного механизма, адекватного языку и, следовательно, более удобного по сумме всех использований. В случае RAII этот FILE* придётся оборачивать спец-классом, потоки C++ такого не требуют.
Здравствуйте, netch80, Вы писали: N>Удивительно, что никто из обсуждавших пока что не обратил внимание на то, что вообще-то одно другому не противоречит. Видимо, потому, что Гугл противопоставляет эти два варианта. N>Но никто не запрещает сделать что-то вроде N>
есть стандартные вещи из С, переосмысленные в С++. они были изменены по двум причинам — (1) они стали надежнее, (2) они стали проще.
printf был переосмыслен из-за того, что при неправильном формате/пропуске параметра или, еще интереснее, изменении его типа где-то там наверху, printf начинал делать очень поганые вещи. и они совсем не стоили того, чтобы выводить что-то на экран. в С printf был введен также из-за отсутствия перегрузки ф-ий, чтобы не делать отдельно print_str, print_int и т.д. кроме printf эллипсис по сути вообще нигде не используется!
потоки решили эти проблемы безопасным, простым и расширяемым способом. если кто-то до сих пор продолжает использовать printf вместо потоков, он не понимает философии С++ и ему вообще писать на нем не следует. а тем более делать какие-то там стандарты С++ кода
Здравствуйте, __kot2, Вы писали:
__>есть стандартные вещи из С, переосмысленные в С++. они были изменены по двум причинам — (1) они стали надежнее, (2) они стали проще. __>printf был переосмыслен из-за того, что при неправильном формате/пропуске параметра или, еще интереснее, изменении его типа где-то там наверху, printf начинал делать очень поганые вещи. и они совсем не стоили того, чтобы выводить что-то на экран. в С printf был введен также из-за отсутствия перегрузки ф-ий, чтобы не делать отдельно print_str, print_int и т.д. кроме printf эллипсис по сути вообще нигде не используется!
__>потоки решили эти проблемы безопасным, простым и расширяемым способом. если кто-то до сих пор продолжает использовать printf вместо потоков, он не понимает философии С++ и ему вообще писать на нем не следует. а тем более делать какие-то там стандарты С++ кода
(намеренно не срезал квотинг. он весь показателен)
Понятно. Есть два мнения: одно Ваше, другое неправильное.
А Вы никогда не задумывались, почему потокового интерфейса в таком стиле, как в C++, больше нигде нет?
Почему ещё более "безопасный, простой и расширяемый" C#, например, использует printf-like интерфейсы (разницу между %d и {0} я тут не считаю существенной)?
Почему весь из себя объектный Python использует два стиля форматирования, один весь как в printf, другой похож на тот, что в C#, и — о ужас! — там тоже есть проблемы с возможной неадекватностью параметров формату, которые не выявляются влёгкую на компиляции? И почему, раз "проблемы решены безопасным, простым и расширяемым образом", что-то не видно штатного аналога стиля C++, хотя его сделать — раз плюнуть?
Может, Вам стоит задуматься о том, что это не весь окружающий мир шагает не в ногу, а это Вы с iostream шагаете не в ногу?
Здравствуйте, netch80, Вы писали: N>А Вы никогда не задумывались, почему потокового интерфейса в таком стиле, как в C++, больше нигде нет?
вот есть я. я не задумывался никогда почему такого, как я больше нет нигде
N>Почему ещё более "безопасный, простой и расширяемый" C#, например, использует printf-like интерфейсы (разницу между %d и {0} я тут не считаю существенной)?
вот есть бомж Вася. он собирает бутылки
N>Почему весь из себя объектный Python использует два стиля форматирования, один весь как в printf, другой похож на тот, что в C#, и — о ужас! — там тоже есть проблемы с возможной неадекватностью параметров формату, которые не
выявляются влёгкую на компиляции? И почему, раз "проблемы решены безопасным, простым и расширяемым образом", что-то не видно штатного аналога стиля C++, хотя его сделать — раз плюнуть?
вот есть баба Валя жена бомжа Васи, она тоже собирает бутылки
N>Может, Вам стоит задуматься о том, что это не весь окружающий мир шагает не в ногу, а это Вы с iostream шагаете не в ногу?
может и мне стоить бросить это программирование и идти собирать бутылки?
Здравствуйте, __kot2, Вы писали:
__>Здравствуйте, netch80, Вы писали: N>>А Вы никогда не задумывались, почему потокового интерфейса в таком стиле, как в C++, больше нигде нет? __>вот есть я. я не задумывался никогда почему такого, как я больше нет нигде
N>>Почему ещё более "безопасный, простой и расширяемый" C#, например, использует printf-like интерфейсы (разницу между %d и {0} я тут не считаю существенной)? __>вот есть бомж Вася. он собирает бутылки
Интересно бы увидеть обоснование сравнения разработчиков одного из трёх основных языков программирования современного мира с бомжом, собирающим бутылки.
Наверняка у Вас есть существенные аргументы для этого. Например, особенности процедуры собирания бутылок, или статистические характеристики урожая бутылок этого года.
N>>Может, Вам стоит задуматься о том, что это не весь окружающий мир шагает не в ногу, а это Вы с iostream шагаете не в ногу? __>может и мне стоить бросить это программирование и идти собирать бутылки?
Хм... Даже не знаю, что сказать. Попробуйте. Может, лет через 10 этого занятия сможете изобрести что-то сравнимое с C# по популярности...
Здравствуйте, netch80, Вы писали: N>А Вы никогда не задумывались, почему потокового интерфейса в таком стиле, как в C++, больше нигде нет?
а как их реализовать средствами языка в C# и в Python? уже как сделали, так сделали
Здравствуйте, netch80, Вы писали: N>Хм... Даже не знаю, что сказать. Попробуйте. Может, лет через 10 этого занятия сможете изобрести что-то сравнимое с C# по популярности...
это аргумент из серии "миллионы зоофилов не могут ошибаться"?
только не надо сейчас бычиться на меня про бутылки и зоофилов. C# хороший язык со своей нишей. но для своей аудитории. посмотрите на наименование контейнеров, например — сразу видно, что их разрабатывал человек не для, там, алгоритмов каких-то продвинутых, а для тех, кто 2 недельный курс программирования в ПТУ закончил. аналогично с перегрузкой операторов.
Я сделал с нуля два проекта на C# и еще в одном участвовал, это прекрасный язык, если вам нужно что-то с базой данных и интерфейсом быстренько сделать. но это не значит, что это идеальный язык, где все прямо так безупречно
Здравствуйте, __kot2, Вы писали:
__>посмотрите на наименование контейнеров, например — сразу видно, что их разрабатывал человек не для, там, алгоритмов каких-то продвинутых, а для тех, кто 2 недельный курс программирования в ПТУ закончил.
Lol'd :) Хуже, чем в C++, коллекции мало где называются :)
list'ом называется не абстрактный тип данных cписок, а структура данных односвязный список.
vector'ом называется не кортеж фиксированного числа элементов с операциями типа евклидова длина или скалярное произведение, а динамически расширяемый массив.
Хэш-таблица в стандарте называется unordered_map.
Здравствуйте, Qbit86, Вы писали:
Q>Lol'd Хуже, чем в C++, коллекции мало где называются
Q>list'ом называется не абстрактный тип данных cписок, а структура данных односвязный список.