Printf vs. std:: cout

Возможный дубликат:
Должен ли я использовать printf в своем коде на С++?

Если я просто хочу напечатать string на экране, я могу сделать это, используя эти два способа:

printf("abc");

std::cout << "abc" << std::endl;

Дело в том, что в приведенных выше примерах есть преимущество использования printf over std::cout или, наоборот,?

Ответ 1

Хотя cout является правильным способом С++, я считаю, что некоторые люди и компании (включая Google) продолжают использовать printf в коде на С++, потому что гораздо легче сделать форматированный вывод с printf, чем с cout.

Вот интересный пример, который я нашел здесь.

Сравнить:

printf( "%-20s %-20s %5s\n" , "Name" , "Surname" , "Id" );

и

cout << setw( -20 ) << "Name" << setw( 20 ) << "Surname"  << setw( 5 ) << "Id" << endl;

Ответ 2

printf, а его ассоциированные друзья - это функции C. Они работают на С++, но не имеют безопасности типов С++ std::ostream s. Проблемы могут возникать в программах, которые используют функции printf для форматирования вывода на основе пользовательского ввода (или даже ввода из файла). Например:

int main()
{
    char[] a = {'1', '2', '3', '4'}; // a string that isn't 0-terminated
    int i = 50;
    printf("%s", a); // will continue printing characters until a 0 is found in memory
    printf("%s", i); // will attempt to print a string, but this is actually an integer
}

С++ имеет гораздо более высокую безопасность типов (и класс std::string), чтобы предотвратить такие проблемы.

Ответ 3

Собственно, для вашего конкретного примера вы должны спросить, что предпочтительнее, puts или cout. printf печатает форматированный текст, но вы просто выводите текст на консоль.

Для общего использования потоки (iostream, из которых cout являются частью) более расширяемы (вы можете распечатывать свои собственные типы с ними) и более универсальны тем, что вы можете создавать функции для печати для любого типа потока, а не только консоль (или перенаправленный вывод). Вы можете создать общее поведение потока с помощью printf, используя fprintf, которые принимают FILE * как FILE *, часто не являются реальным файлом, но это более сложно.

Потоки являются "типичными", поскольку вы перегружаетесь с типом, который вы печатаете. printf не является типичным с использованием эллипсов, поэтому вы можете получить результаты undefined, если вы введете неправильные типы параметров, которые не соответствуют строке формата, но компилятор не будет жаловаться. Вы даже можете получить поведение seg-fault/undefined (но вы можете использовать cout при неправильном использовании), если вы пропустите параметр или пропустите плохой (например, число для% s, и оно все равно относится к нему как к указателю).

printf имеет некоторые преимущества: вы можете шаблонировать строку формата, а затем повторно использовать эту строку формата для разных данных, даже если эти данные не находятся в структуре, а использование форматирования для одной переменной не "фиксирует" этот формат для используйте, поскольку вы указываете формат для каждой переменной. printf также известен как потокобезопасный, тогда как cout фактически не является.

boost объединил преимущества каждого из них в своей библиотеке boost:: format.

Ответ 4

Я сам борюсь с этим вопросом. printf, как правило, проще в использовании для форматированной печати, но средство iostreams на С++ имеет большое преимущество в том, что вы можете создавать собственные форматирования для объектов. В конечном итоге я использую оба из них в своем коде.

Проблема с использованием обоих и их смешивание состоит в том, что выходные буферы, используемые printf и cout, не совпадают, поэтому, если вы не запускаете небуферизованный или явно скрытый вывод, вы можете получить поврежденный вывод.

Мое главное возражение против С++ заключается в том, что нет быстрого форматирования вывода, аналогичного printf, поэтому нет возможности легко управлять выходом для форматирования целого числа, шестнадцатеричного и с плавающей запятой.

У Java была эта же проблема; язык заканчивал тем, что получил printf.

В Википедии есть хорошее обсуждение этой проблемы на http://en.wikipedia.org/wiki/Printf#C.2B.2B_alternatives_to_sprintf_for_numeric_conversion.

Ответ 5

printf был заимствован из C и имеет некоторые ограничения. Наиболее распространенным упомянутым ограничением printf является безопасность типов, так как он полагается на программиста, чтобы правильно сопоставить строку формата с аргументами. Второе ограничение, которое снова возникает из среды varargs, заключается в том, что вы не можете расширять поведение с помощью определенных пользователем типов. printf знает, как печатать набор типов, и что все, что вы выберете из него. Тем не менее, для некоторых вещей, для которых он может быть использован, быстрее и проще форматировать строки с printf, чем с потоками С++.

В то время как большинство современных компиляторов могут решать ограничение безопасности типа и, по крайней мере, предоставлять предупреждения (компилятор может анализировать строку формата и проверять аргументы, предоставленные в вызове), второе ограничение не может быть преодолено. Даже в первом случае есть вещи, с которыми компилятор не может реально помочь, так как проверка нулевого завершения - но опять же, такая же проблема возникает с std::cout, если вы используете его для печати того же массива.

С другой стороны, потоки (включая std::cout) могут быть расширены для обработки определенных пользователем типов с помощью перегруженного std::ostream& operator<<( std::ostream&, type const & ) для любого заданного определенного пользователем типа type. Они сами по себе безопасны по типу - если вы передаете тип, который не перегружен operator<<, компилятор будет жаловаться. С другой стороны, они являются более громоздкими для получения отформатированного вывода.

Итак, что вы должны использовать? В общем, я предпочитаю использовать потоки, так как перегрузка operator<< для моих собственных типов проста и их можно использовать равномерно со всеми типами.

Ответ 6

Эти два примера делают разные вещи. Последний добавит символ новой строки и вывернутый вывод (результат std::endl). std::cout также медленнее. Кроме того, printf и std::cout достигают того же, и вы можете выбрать то, что вы предпочитаете. В качестве предпочтения я использовал бы std::cout в коде на С++. Это более читаемо и безопаснее.

Смотрите эту статью, если вам нужно форматировать вывод с помощью std::cout.

Ответ 7

В общем, вы должны предпочесть cout, потому что он гораздо более безопасный и более общий. printf не является безопасным по типу, и он вообще не является общим. Единственная причина, по которой вы можете отдать предпочтение printf, - это скорость - из памяти, printf во много раз быстрее, чем cout.