(C++) When do you use std::cout vs printf?
![]()
Title, I've gotten through 13 chapters of learncpp.com and we've used cout the entire time, it hasn't even mentioned printf, but in sources I see online I see printf more commonly than cout.
![]()
The advantage of cout (and streams in general) is that you can customize them for your own type. For example, the following outputs a constant string (const char *), a non-constant string, an integer, and then another constant string using cout and printf:
After getting used to the notation, the fprintf notation is obviously superior and easier to read. It was introduced by C and the notation has been copied and reimplemented in various forms by many other programming languages since then. It has some shortcomings, however. Suppose 'word' is not a string but is a custom type. With iostreams, the convention is to overload operator<< for your own type. If you do that, then the above code that uses cout will work just fine. But that approach can never work for fprintf.
In C++20 we will have the following Python 3-like alternative, so in some time (when compiler support is good enough), you will be able to write the following C++ code instead of using the punctuation salad of << and double quotes all over the place to format and concatenate strings manually with std::cout:
printf против cout в C ++
В чем разница между printf() и cout в C ++?
задан 20 мая ’10, 06:05
16 ответы
Я удивлен, что все в этом вопросе утверждают, что std::cout намного лучше чем printf , даже если вопрос просто задавал отличия. Теперь есть разница — std::cout это C ++, и printf это C (однако вы можете использовать его в C ++, как и почти что-нибудь еще из C). Теперь я буду честен здесь; оба printf и std::cout имеют свои преимущества.
Реальные различия
растяжимость
std::cout расширяемый. Я знаю, что люди скажут это printf также является расширяемым, но такое расширение не упоминается в стандарте C (поэтому вам придется использовать нестандартные функции — но даже общие нестандартные функции не существуют), и такие расширения представляют собой одну букву (поэтому легко вступить в конфликт с уже существующий формат).
В отличие от printf , std::cout полностью зависит от перегрузки оператора, поэтому нет проблем с настраиваемыми форматами — все, что вам нужно сделать, это определить подпрограмму, принимающую std::ostream как первый аргумент и ваш тип как второй. Таким образом, нет проблем с пространством имен — пока у вас есть класс (который не ограничен одним символом), вы можете иметь рабочий std::ostream перегрузка для этого.
Однако я сомневаюсь, что многие захотят расширить ostream (честно говоря, я редко видел такие пристройки, даже если их легко сделать). Однако он здесь, если вам это нужно.
Синтаксис
Как легко заметить, оба printf и std::cout используйте другой синтаксис. printf использует стандартный синтаксис функции с использованием шаблонной строки и списков аргументов переменной длины. Фактически, printf это причина, по которой они есть в C — printf форматы слишком сложны, чтобы их можно было использовать без них. Тем не мение, std::cout использует другой API — operator << API, который возвращает себя.
Обычно это означает, что версия C будет короче, но в большинстве случаев это не имеет значения. Разница заметна, когда вы печатаете много аргументов. Если вам нужно написать что-то вроде Error 2: File not found. , если предположить, что номер ошибки и его описание является заполнителем, код будет выглядеть следующим образом. Оба примера работать одинаково (ну вроде, std::endl фактически очищает буфер).
Хотя это не кажется слишком сумасшедшим (это всего в два раза дольше), все становится еще более сумасшедшим, когда вы фактически форматируете аргументы, а не просто их печатаете. Например, печать чего-то вроде 0x0424 просто безумие. Это вызвано std::cout состояние смешивания и фактические значения. Я никогда не видел языка, где что-то вроде std::setfill будет типом (кроме C ++, конечно). printf четко разделяет аргументы и фактический тип. Я бы предпочел сохранить printf его версию (даже если она выглядит загадочно) по сравнению с iostream его версия (так как в ней слишком много шума).
Переводы
Вот где настоящее преимущество printf вранье. В printf строка формата ну . строка. Это действительно упрощает перевод по сравнению с operator << злоупотребление iostream . Предполагая, что gettext() функция переводит, и вы хотите показать Error 2: File not found. , код для получения перевода ранее показанной строки формата будет выглядеть так:
Теперь предположим, что мы переводим на «фиктивный», где номер ошибки стоит после описания. Переведенная строка будет выглядеть как %2$s oru %1$d.\n . Как это сделать на C ++? Ну я понятия не имею. Я думаю, ты можешь подделать iostream который строит printf что вы можете перейти к gettext , или что-то в этом роде, для целей перевода. Конечно, $ не является стандартом C, но он настолько распространен, что, на мой взгляд, его безопасно использовать.
Отсутствие необходимости запоминать / искать конкретный синтаксис целочисленного типа
C имеет множество целочисленных типов, как и C ++. std::cout обрабатывает все типы за вас, в то время как printf требует определенного синтаксиса в зависимости от целочисленного типа (есть нецелочисленные типы, но единственный нецелочисленный тип, который вы будете использовать на практике с printf is const char * (Строка C, может быть получена с помощью to_c метод std::string )). Например, напечатать size_t , вам нужно использовать %zd , В то время int64_t потребует использования %»PRId64″ . Таблицы доступны на http://en.cppreference.com/w/cpp/io/c/fprintf и http://en.cppreference.com/w/cpp/types/integer.
Вы не можете распечатать байт NUL, \0
Так как printf использует строки C в отличие от строк C ++, он не может печатать байт NUL без особых уловок. В некоторых случаях можно использовать %c с ‘\0’ в качестве аргумента, хотя это явно взлом.
Различия никого не волнуют
Производительность
Обновление: оказывается, что iostream настолько медленный, что обычно он медленнее, чем ваш жесткий диск (если вы перенаправляете свою программу в файл). Отключение синхронизации с stdio может помочь, если вам нужно вывести много данных. Если производительность вызывает реальную озабоченность (в отличие от записи нескольких строк в STDOUT), просто используйте printf .
Все думают, что им небезразлична производительность, но никто не пытается ее измерить. Я отвечу, что ввод-вывод в любом случае является узким местом, независимо от того, используете ли вы printf or iostream . я думаю что printf может быть быстрее от быстрого взгляда на сборку (скомпилировано с помощью clang с использованием -O3 вариант компилятора). Предполагая мой пример ошибки, printf пример делает намного меньше вызовов, чем cout пример. Это int main с printf :
Вы можете легко заметить, что две строки и 2 (число) нажимаются как printf аргументы. Вот и все; больше ничего нет. Для сравнения это iostream скомпилирован в сборку. Нет, встраивания нет; каждый operator << вызов означает еще один вызов с другим набором аргументов.
Однако, честно говоря, это ничего не значит, поскольку ввод-вывод в любом случае является узким местом. Я просто хотел показать это iostream не быстрее, потому что он «безопасен по типу». Большинство реализаций C реализуют printf форматы с использованием вычисляемого goto, поэтому printf работает настолько быстро, насколько это возможно, даже если компилятор не знает о printf (не то чтобы это не так — некоторые компиляторы могут оптимизировать printf в некоторых случаях — постоянная строка, оканчивающаяся на \n обычно оптимизирован для puts ).
наследование
Я не знаю, почему ты хочешь наследовать ostream , но мне все равно. Это возможно с FILE тоже.
Тип безопасности
Правда, списки аргументов переменной длины небезопасны, но это не имеет значения, поскольку популярные компиляторы C могут обнаруживать проблемы с printf строка формата, если вы включили предупреждения. Фактически, Clang может делать это без включения предупреждений.
C в чем разница между cout и printf
Однако я сомневаюсь, что многие люди захотят расширить ostream (честно говоря, я редко видел такие расширения, даже если их легко сделать). Тем не менее, это здесь, если вам это нужно.
Синтаксис
Хотя это не кажется слишком сумасшедшим (просто в два раза дольше), все становится более сумасшедшим, когда вы на самом деле форматируете аргументы, а не просто печатаете их. Например, печать чего-то подобного 0x0424 просто сумасшедшая. Это вызвано std::cout смешиванием состояния и фактических значений. Я никогда не видел языка, в котором что-то вроде std::setfill бы было типом (кроме C ++, конечно). printf четко разделяет аргументы и фактический тип. Я действительно предпочел бы сохранить его printf версию (даже если она выглядит несколько загадочно) по сравнению с iostream версией (поскольку она содержит слишком много шума).
Перевод
Не нужно запоминать / искать определенный синтаксис целочисленных типов
Вы не можете напечатать байт NUL, \0
Поскольку printf используются строки C, а не строки C ++, он не может печатать NUL-байт без специальных уловок. В некоторых случаях можно использовать %c с ‘\0’ качестве аргумента, хотя это явно хак.
Различия никого не волнуют
Представление
Вы можете легко заметить, что две строки и 2 (число) выдвигаются в качестве printf аргументов. Это об этом; больше ничего нет Для сравнения, это iostream скомпилировано в сборку. Нет, там нет встраивания; каждый отдельный operator вызов означает другой вызов с другим набором аргументов.
наследование
Тип безопасности
Правда, списки аргументов переменной длины не имеют никакой безопасности, но это не имеет значения, так как популярные компиляторы C могут обнаружить проблемы со printf строкой формата, если вы включите предупреждения. На самом деле, Clang может сделать это без включения предупреждений.
Повысить безопасность типов, уменьшить количество ошибок, расширить возможности и обеспечить наследуемость.
Что лучше использовать: cout / wcout или printf? [закрыт]
Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы он был сосредоточен только на одной проблеме.
Собственно, вопрос в заголовке. Пожалуйста, дайте подробный ответ.


1 ответ 1
Как завещал нам Страуструп, лучше потоки чем printf. Ибо потоки, как минимум, типобезопасны.
Представим, что в процессе работы пришлось сменить тип переменной (это встречается сплошь и рядом):
Как видно, при использовании потока ничего не поменялось. А при использовании printf пришлось править форматную строку. Если printf много в коде, то везде править форматную строку во всех printf очень утомительно и черевато ошибками.
Уж не знаю насколько потоки следствие идеи перегрузки операций. Может быть это и так. В любом случае, в варианте с printf тип операнда указывается два раза. Один раз в форматной строке, а второй раз собственно имя переменной говорит компилятору какой это тип. А два раза повторять одну и ту же информацию не есть хорошо. Потому что править приходится в двух местах, а не в одном месте. Так что идея с потоками (независимо от источника ее появления, будь то перегрузка операций или просто желание избавится от форматной строки) еще позволила избавится от ненужного дублирования информации.
Кстати, перегрузить операции можно было бы и с printf. Или в потоках оставить форматную строку. Ну если все делать через одно место конечно.
Что касается квалификации персонала, то квалификация постоянно растет. Старая школа может долбать любимый printf до посинения, пока самим не надоест вылавливать ошибки форматов. Новое поколение не знает таких ужасов и весело применяет потоки.
Кстати, вывод через потоки в общем случае быстрее, чем вывод через printf. Объясняется это тем, что при выводе через потоки разбор типов происходит на этапе компиляции и в рантайме разбора типов нет, а там есть только вывод значения. В случае же с printf происходит разбор форматной строки в рантайме, то есть компилированный код передает управление интерпретатору форматной строки. А, как известно, интерпретатор работает в 100-1000 раз медленнее, чем компилированный код.
Ранние трансляторы С++ создавали потоковый вывод как надстройку над выводом printf и разницы в скорости не было (но все равно была разница в типобезопасности, так как форматные строки формировались автоматически). Современные трансляторы С++ делают потоковый вывод как надо, без использования printf. И это (теоретически) повышает быстродействие вывода.
Так что скорость вывода это еще один аргумент, который заставляет программистов выбирать потоки вместо старого подхода с printf.
Но и объем скомпилированного кода больше.
Объем скомпилированного кода при выводе в поток не больше, чем при использовании printf.
В этом примере строки вывода
разворачиваются в обычные вызовы подпрограмм вывода, а вовсе не в последовательные повторения кода.
скорость встроенных при компиляции (как следствие реализации templates) преобразований выше.
Скорость вывода при использовании printf меньше именно из-за того, что разбор форматной строки происходит в рантайме. В случае использования потоков нет разбора форматной строки в рантайме и также нет оверхеда из-за шаблонов потому что там вставляется не шаблон, а обычный вызов подпрограммы вывода для соответствующего типа. Это легко проверить, если посмотреть ассемблерный код простого примера, приведенного выше. Транслятор Visual Studio 2017.
разворачивается в обычный вызов подпрограммы
и никаких шаблонов тут нет.
мы пишем программы не для компьютера, а для других программистов
Довольно спорное утверждение. Проще переписать весь код, чем править чужое. Ибо невозможно до конца понять, какие мысли (часто неверные) были у человека, когда он писал код.
Поэтому, используйте те конструкции, что вам представляются наиболее подходящими для понимания конкретного кода.
Нет, надо не только использовать то, чем владеешь, но и осваивать новые, более продвинутые инструменты вроде потоков, которые для нас придумывают разные головастые страуструпы. Если бы мы не осваивали новые инструменты, то мы бы до сих пор программировали в машинных кодах.
использование printf / scanf и отличия от различий и cout / cin, когда и какие использовать?
3 ответа
Обычные конкурирующие программисты сталкиваются с общей проблемой, когда ввод велик, и задача чтения такого ввода из stdin может оказаться узким местом. Такая проблема сопровождается «Предупреждение: большие данные ввода / вывода».
cin / cout быстрее, чем scanf / printf, ключевое отличие между ними.
Почему scanf быстрее, чем cin?
На высоком уровне они оба являются оболочками системного вызова theread (), просто синтаксическим сахаром. Единственное видимое отличие состоит в том, что scanf () должен явно объявить тип ввода, тогда как в cin операция перенаправления перегружена с использованием шаблонов. Это не кажется достаточной причиной для снижения производительности в 5 раз.
Оказывается, iostream использует систему буферизации stdio. Таким образом, cin тратит время на синхронизацию с буфером stdio C-библиотеки, так что вызовы обоих scanf () и cin могут чередоваться.
Хорошо, что libstdc ++ предоставляет возможность отключить синхронизацию всех стандартных потоков iostream с соответствующими им стандартными потоками C, используя
СТД :: ИОС :: sync_with_stdio ( ложь) ;
То же самое с cout и printf.
Я надеюсь, что это ответит на ваш вопрос о том, почему один из них предпочтительнее другого, и они в основном являются способом ввода данных, а внутренне cin, cout пишется с использованием библиотеки буфера c stdio.
scanf и printf не являются операторами. Это функции.
Нет заголовка в стандартной библиотеке C ++ ни в одной стандартной версии C ++. Вы можете использовать древний диалект C ++.
Грубое практическое правило: используйте std::cout и std::cin при написании C ++. Не используйте printf или scanf при написании C ++.
тогда почему он был импортирован в C ++
Насколько я понимаю, это так, что программы на C могут быть преобразованы в C ++ небольшими пошаговыми шагами. Если вы написали программу на C, которая использует стандартный ввод / вывод C, то вы можете переписать программу на C ++ без полной замены части ввода / вывода. Этот выбор дизайна, вероятно, должен был побудить существующие программы / проекты перейти от использования C к использованию C ++.
Функции C I / O являются рудиментарной функцией, которая существует для обратной совместимости с C.
Русские Блоги
Дети учатся C ++ (22): сравнение эффективности cin и scanf, cout и printf
1. Генерация тестовых данных
Сначала запишите 10 миллионов тестовых данных в data.txt
Конфигурация компьютера представляет собой процессор i7, память 16 ГБ, а время работы составляет около 5 секунд. Размер сгенерированного файла data.txt составляет 77040 КБ, что составляет около 77 МБ.
Во-вторых, сравнение эффективности cin и scanf

(2) Ускорение вращения
Следующие две строки кода могут улучшить эффективность cin и cout
Три, анализ sync_with_stdio и cin.tie
(1) ios :: sync_with_stdio ()
Значение по умолчанию для параметра sync_with_stdion равно true, что означает, что cin и scanf синхронизированы, а cout и printf синхронизированы.
Что означает синхронизация?
Например, несколько человек стоят в очереди за водой, и есть только один кран. Тогда только человек впереди может допить воду до человека сзади, в этом случае человек спереди должен закончить воду перед человеком сзади.
Соответствующая синхронизация асинхронная (асинхронная), что асинхронная?
Например, несколько человек стоят в очереди, чтобы набрать воды, и есть много кранов. Тогда человек впереди не может допить воду до человека сзади. Например, человек с номером 1 выбрал кран № 1, а человек с номером 2 немедленно выбрал кран № 2. Если скорость подачи воды из крана № 2 намного выше, чем у крана № 1, то человек получил оценку № 2 Он допьет воду до первого лица.
(Два) cin.tie (0)
Связывание здесь означает привязку. По умолчанию cin привязывается к cout. Каждый раз, когда выполняется оператор cout Также может быть написано как cin.tie()
cin.tie (0) эквивалентен cin.tie (NULL), что означает, что он не связан ни с одним выходным потоком, то есть cout по умолчанию не связан.
Если вы используете его в это время cin.tie() Компилятор сообщит об ошибке.
Следующие процедуры могут быть использованы для углубления понимания:
результат операции:
напечатано на консоли
Также генерируется файл test.out, содержимое которого
4. Сравнение эффективности между cout и printf
(1) Вывести 100 000 данных на консоль для тестирования
Видно, что эффективность работы cout выше, чем у printf, что является результатом оптимизации cin и cout компилятором G ++.
(Два) ускорить кут
Видно, что после ускорения cout работает быстрее.
V. Вывод
(1) Scanf / printf должен форматировать символы% d,% f,% c и т.п., что не так удобно, как cin / cout
(2) Cout очень неудобен при управлении выводом десятичных разрядов. Нужно сделать так
(3) Для некоторых компиляторов, которые оптимизируют cin и cout (например, G ++), эффективность работы cin / cout выше, чем scanf / printf.
Но для компиляторов, которые не были оптимизированы, эффективность scanf / printf намного выше, чем у cin / cout. Это почти всегда относится к статьям, найденным в Интернете. Это полная противоположность экспериментальным результатам в этой статье.
(4) Для неалгоритмических игр не имеет значения, используете ли вы cin / cout или scanf / printf.
(5) Но для игр с алгоритмами из-за большого объема данных это часто приводит к тайм-ауту (превышен лимит времени TLE). В настоящее время scanf / printf можно использовать равномерно или использовать plus ios::sync_with_stdio(false); cin.tie(0) Cin / соиЬ.
TopCoder & Codeforces & AtCoder Exchange QQ Группа: 648202993
Для получения дополнительной информации, пожалуйста, следуйте общедоступной учетной записи WeChat.
Интеллектуальная рекомендация
![]()
![]()
Разработчик PL / SQL удаленно входит в систему с ошибкой идентификатора соединения Oracle TNS
Мозга
Обратитесь к источнику: IBM DeveloperWorks: https://www.ibm.com/developerworks/cn/linux/l-cn-cmake/ содержание: 1. Введение в Cmake 2, обработка каталога файлов с несколькими источниками 3, найти и ис.
Settings.System.getInt, чтобы получить некоторые настройки в Setting
В пользовательских компонентахpropertiesНеправильное использование неправильноVueГрамматика модифицировать.
в чем разница между printf и cout
Какой-то код, подобный этому ниже:
Я знаю, что последовательность выполнения выполняется справа налево, в то время как почему результат оператора a равен «1,1,1», а результат оператора B равен «112».
Я использую vs2008 с режимом отладки: результат тот же: 2,1,2. с режимом выпуска: результат другой: Ответ: 1,1,1, B:1,1,2
4 ответа
В C/C++, в чем разница между использованием #define [и #ifndef #endif ] для создания значений, когда вы можете легко сделать это и с int или std::string [C++]? #ifndef MYVAL #define MYVAL(500) #endif //C++ cout
Таким образом, вы можете получить одинаковые результаты для обоих выражений. Вы можете получить разные результаты. Демоны могут вылететь из вашего носа, когда вы оцениваете любого из них. Ты просто не можешь сказать.
Тема последовательности пунктов и порядка оценки может быть довольно сложной. Я бы посоветовал вам взглянуть на этот вопрос, если вы хотите узнать больше:
с printf все аргументы вычисляются (x=1) перед вызовом printf. с помощью cout аргументы оцениваются и применяются последовательно. (по крайней мере, в том, что касается вашего компилятора)
Прочтите эту статью. Это хороший вариант.
В то время как в операторе cout берется самое последнее значение переменных, поэтому оно непосредственно влияет на текущий оператор.
Надеюсь, вы будете ясны.
В чем разница между echo и printf?
Результат утверждения А и в одинаков.
Результат / поведение несовместимы с компилятором.
Похожие вопросы:
Возможный Дубликат : printf против cout в C++ В чем разница между cout и printf?
Возможный Дубликат : Разница между спецификаторами формата %i и %d в printf Я только что проверил ссылку, она говорит, что оба они указывают на целое число со знаком. Я подумал, что должна быть.
char s[100]= ; fgets(s, sizeof(s), stdin); В контексте приведенного выше кода, в чем разница между этими тремя? printf(%s,s); printf(s); fputs(s,stdout);
В C/C++, в чем разница между использованием #define [и #ifndef #endif ] для создания значений, когда вы можете легко сделать это и с int или std::string [C++]? #ifndef MYVAL #define MYVAL(500).
В чем разница между printf() и cout в C++?
В чем разница между echo и printf?
Мне интересно, в чем разница между %D, %d и %i в функции printf, потому что все они отображают целые числа, так почему же существует 3 формата для отображения целых чисел? Должна же быть разница.
printf против производительности cout
Заключить, cout быстрее чем printf , Причина вышеприведенных наблюдений была связана с выводом на консоль. При перенаправлении вывода в файл все перевернулось с ног на голову!
Решение
У меня больше не установлено VS 2010, но я провел быстрое тестирование с VS 2013 и 2015. Я немного изменил ваш код, чтобы уменьшить дублирование, и включил временный код, давая следующее:
С выключенной оптимизацией cout показал себя немного быстрее (например, 358 мс против 460 для printf ) но измерение скорости с отключенной оптимизацией довольно бессмысленно.
С включенной оптимизацией cout выиграл с еще большим отрывом (191 мс против 365 мс для printf ).
Чтобы сохранить их смысл, я запустил их все с перенаправленным выводом в файл. Без этого, по сути, все, что вы бы измерили, — это скорость драйвера консоли, которая по сути бессмысленна и бесполезна.