Практическое различие printf и cout
Здравствуйте, дорогие обитали данного форума. Недавно у нас на 2 курсе началось программирование на C++ (так его гордо называл наш препод), но на первых парах нам выдали практику содержащую оператор printf, хотя практически везде, во множестве литературы и многочисленых хелоу-ворд проектах содержался cout. Так вот, вопрос в чем различие этих операторов?
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:
Небольшое различие между printf и cout
Заметил, что если я вывожу максимальное или минимальное значение типа char через printf, то это.
Cout в printf
Здравствуйте, может кто-нибудь помочь переделать cout в printf на 87-88 строках в данной программе.
printf > cout
Помогите переделать printf("| %3.2f | %3.1f | %7.5f |\n",a,b,y); на cout.
printf и cout
У меня возник вопрос, что луче еспользовать в C++, printf/scanf или cout/cin ? Что работает.
Любитель чаепитий
3741 / 1798 / 565
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
d1astola, Во-первых, printf — не оператор, как и cout.
Во-вторых, как легче написать,
printf("%d\n%s\n%d",x,y,z);
cout x '\n' y '\n' z endl;
?
И запомните: printf — функция, cout — поток!
5277 / 2364 / 342
Регистрация: 20.02.2013
Сообщений: 5,763
Записей в блоге: 20
d1astola, возможно, вот эта статья Вам поможет.
805 / 532 / 158
Регистрация: 27.01.2015
Сообщений: 3,017
Записей в блоге: 1
d1astola,
printf, как уже было ранее сказано, это функция. Используется она, как правило, в программах, написанных на чистом Си.
На данном форуме многие не жалуют эту функцию в С++ программах. Использование ее в коде С++ считается дурным тоном.
Другое дело — предопределенный потоковый объект (вероятно, ТС не знаком с понятием объекта) cout из библиотеки iostream.
Использование этого объекта считается уместным в программах на С++, но в чистом Си его использование невозможно по причине его отстутствия.
НО! Оба этих средства служат для вывода информации на экран.
Мешать в одном коде средства языка С++ и чистого Си может считаться извращением.
23 / 33 / 14
Регистрация: 11.06.2015
Сообщений: 384
printf — функция, cout нет. Вот и отличие.
163 / 104 / 14
Регистрация: 17.10.2012
Сообщений: 488
Ни printf, ни cout не являются операторами. printf — функция из стандартной библиотеки Си, cout — объект класса ostream из стандартной библиотеки Си++.
Объединяет их то, что оба связаны со стандартным потоком вывода (stdout, файл с дескриптором 1).
Вообще я бы отметил такое ключевое отличие — printf принимает переменное число параметров, выводя их тип на основании форматирующей строки. Такой подход мало того, что ограничен только набором стандартных типов (расширения в счет не беру), да еще и небезопасный. Плюсовые стримы используют механизм шаблонов + полиморфизм, благодаря чему обеспечивается безопасность на уровне компилятора, ну и возможность ввода\вывода собственных типов.
Изучить работу и основные форматы printf стоит хотя бы потому, что он используется в множестве других языках, рано или поздно на него можно наткнуться.
Что лучше использовать: cout / wcout или printf? [закрыт]
Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы он был сосредоточен только на одной проблеме.
Закрыт 5 лет назад .
Собственно, вопрос в заголовке. Пожалуйста, дайте подробный ответ.
Отслеживать
20.1k 6 6 золотых знаков 37 37 серебряных знаков 81 81 бронзовый знак
задан 13 июл 2018 в 16:02
Mournehowl Mournehowl
153 15 15 бронзовых знаков
Вопрос вполне идентичен вопросу: » Что лучше использовать: шуруповерт , дрель или перфоратор? ..» Каждый инструмент хорош при разных задачах и ситуаций.
13 июл 2018 в 16:21
Что удобнее, то и используйте. Как уже ответили cout безопаснее, нет необходимости указывать тип, который выводишь. С другой стороны можно быстро написать printf(«count %i with %s, or %s», i, data, foo); С cout это выглядело бы cout
13 июл 2018 в 16:24
Хотите удобно и безопасно — используйте boost::format Предыдущий пример запишется так: cout
13 июл 2018 в 19:10
На моей практике, добиться красиво отформатированного вывода (особенно при модификации программ) с printf -ом получается быстрее
13 июл 2018 в 20:31
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Как завещал нам Страуструп, лучше потоки чем printf. Ибо потоки, как минимум, типобезопасны.
Например есть код:
int i; cout
Представим, что в процессе работы пришлось сменить тип переменной (это встречается сплошь и рядом):
float i; cout
Как видно, при использовании потока ничего не поменялось. А при использовании printf пришлось править форматную строку. Если printf много в коде, то везде править форматную строку во всех printf очень утомительно и черевато ошибками.
Предположить легко. Однако, на самом деле это последствие идеи предоставления пользователям языка средств для его расширения -- т.е. конструирования собственных типов данных и операций над ними, что влечет перегрузку операций (т.е. одно и то же обозначение операций в зависимости от типов операндов дает разный результат). Хорошо это или плохо для реальной практики программирования, учитывающей качество персонала, вопрос дискуссионный
Уж не знаю насколько потоки следствие идеи перегрузки операций. Может быть это и так. В любом случае, в варианте с printf тип операнда указывается два раза. Один раз в форматной строке, а второй раз собственно имя переменной говорит компилятору какой это тип. А два раза повторять одну и ту же информацию не есть хорошо. Потому что править приходится в двух местах, а не в одном месте. Так что идея с потоками (независимо от источника ее появления, будь то перегрузка операций или просто желание избавится от форматной строки) еще позволила избавится от ненужного дублирования информации.
Кстати, перегрузить операции можно было бы и с printf. Или в потоках оставить форматную строку. Ну если все делать через одно место конечно.
Что касается квалификации персонала, то квалификация постоянно растет. Старая школа может долбать любимый printf до посинения, пока самим не надоест вылавливать ошибки форматов. Новое поколение не знает таких ужасов и весело применяет потоки.
Кстати, вывод через потоки в общем случае быстрее, чем вывод через printf. Объясняется это тем, что при выводе через потоки разбор типов происходит на этапе компиляции и в рантайме разбора типов нет, а там есть только вывод значения. В случае же с printf происходит разбор форматной строки в рантайме, то есть компилированный код передает управление интерпретатору форматной строки. А, как известно, интерпретатор работает в 100-1000 раз медленнее, чем компилированный код.
Ранние трансляторы С++ создавали потоковый вывод как надстройку над выводом printf и разницы в скорости не было (но все равно была разница в типобезопасности, так как форматные строки формировались автоматически). Современные трансляторы С++ делают потоковый вывод как надо, без использования printf. И это (теоретически) повышает быстродействие вывода.
Так что скорость вывода это еще один аргумент, который заставляет программистов выбирать потоки вместо старого подхода с printf.
Но и объем скомпилированного кода больше.
Объем скомпилированного кода при выводе в поток не больше, чем при использовании printf.
int var1=1; int var2=2; cout
В этом примере строки вывода
cout
разворачиваются в обычные вызовы подпрограмм вывода, а вовсе не в последовательные повторения кода.
скорость встроенных при компиляции (как следствие реализации templates) преобразований выше.
Скорость вывода при использовании printf меньше именно из-за того, что разбор форматной строки происходит в рантайме. В случае использования потоков нет разбора форматной строки в рантайме и также нет оверхеда из-за шаблонов потому что там вставляется не шаблон, а обычный вызов подпрограммы вывода для соответствующего типа. Это легко проверить, если посмотреть ассемблерный код простого примера, приведенного выше. Транслятор Visual Studio 2017.
; Listing generated by Microsoft (R) Optimizing Compiler Version 19.14.26433.0 TITLE C:\user\basil\rttsched\etudes\etude2\etude2\etude2\etude2.cpp .686P .XMM include listing.inc .model flat INCLUDELIB MSVCRTD PUBLIC ?__empty_global_delete@@YAXPAX@Z ; __empty_global_delete PUBLIC ?__empty_global_delete@@YAXPAXI@Z ; __empty_global_delete PUBLIC _main EXTRN __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z:PROC EXTRN __RTC_CheckEsp:PROC EXTRN __RTC_InitBase:PROC EXTRN __RTC_Shutdown:PROC EXTRN __imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A:BYTE ; COMDAT rtc$TMZ rtc$TMZ SEGMENT __RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown rtc$TMZ ENDS ; COMDAT rtc$IMZ rtc$IMZ SEGMENT __RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase rtc$IMZ ENDS ; Function compile flags: /Odtp /RTCsu /ZI ; File c:\user\basil\rttsched\etudes\etude2\etude2\etude2\etude2.cpp ; COMDAT _main _TEXT SEGMENT _var2$ = -20 ; size = 4 _var1$ = -8 ; size = 4 _main PROC ; COMDAT push ebp mov ebp, esp sub esp, 216 ; 000000d8H push ebx push esi push edi lea edi, DWORD PTR [ebp-216] mov ecx, 54 ; 00000036H mov eax, -858993460 ; ccccccccH rep stosd mov DWORD PTR _var1$[ebp], 1 mov DWORD PTR _var2$[ebp], 2 mov esi, esp mov eax, DWORD PTR _var1$[ebp] push eax mov ecx, DWORD PTR __imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A call DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z cmp esi, esp call __RTC_CheckEsp mov esi, esp mov eax, DWORD PTR _var2$[ebp] push eax mov ecx, DWORD PTR __imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A call DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z cmp esi, esp call __RTC_CheckEsp xor eax, eax pop edi pop esi pop ebx add esp, 216 ; 000000d8H cmp ebp, esp call __RTC_CheckEsp mov esp, ebp pop ebp ret 0 _main ENDP _TEXT ENDS ; Function compile flags: /Odtp /RTCsu /ZI ; File c:\user\basil\rttsched\etudes\etude2\etude2\etude2\etude2.cpp ; COMDAT ?__empty_global_delete@@YAXPAXI@Z _TEXT SEGMENT ___formal$ = 8 ; size = 4 ___formal$ = 12 ; size = 4 ?__empty_global_delete@@YAXPAXI@Z PROC ; __empty_global_delete, COMDAT push ebp mov ebp, esp sub esp, 192 ; 000000c0H push ebx push esi push edi lea edi, DWORD PTR [ebp-192] mov ecx, 48 ; 00000030H mov eax, -858993460 ; ccccccccH rep stosd pop edi pop esi pop ebx mov esp, ebp pop ebp ret 0 ?__empty_global_delete@@YAXPAXI@Z ENDP ; __empty_global_delete _TEXT ENDS ; Function compile flags: /Odtp /RTCsu /ZI ; File c:\user\basil\rttsched\etudes\etude2\etude2\etude2\etude2.cpp ; COMDAT ?__empty_global_delete@@YAXPAX@Z _TEXT SEGMENT ___formal$ = 8 ; size = 4 ?__empty_global_delete@@YAXPAX@Z PROC ; __empty_global_delete, COMDAT push ebp mov ebp, esp sub esp, 192 ; 000000c0H push ebx push esi push edi lea edi, DWORD PTR [ebp-192] mov ecx, 48 ; 00000030H mov eax, -858993460 ; ccccccccH rep stosd pop edi pop esi pop ebx mov esp, ebp pop ebp ret 0 ?__empty_global_delete@@YAXPAX@Z ENDP ; __empty_global_delete _TEXT ENDS END
Видно, что вызов
cout
разворачивается в обычный вызов подпрограммы
call DWORD PTR __imp_??6?$basic_ostream@DU$char_traits@D@std@@@std@@QAEAAV01@H@Z
и никаких шаблонов тут нет.
мы пишем программы не для компьютера, а для других программистов
Довольно спорное утверждение. Проще переписать весь код, чем править чужое. Ибо невозможно до конца понять, какие мысли (часто неверные) были у человека, когда он писал код.
Поэтому, используйте те конструкции, что вам представляются наиболее подходящими для понимания конкретного кода.
Нет, надо не только использовать то, чем владеешь, но и осваивать новые, более продвинутые инструменты вроде потоков, которые для нас придумывают разные головастые страуструпы. Если бы мы не осваивали новые инструменты, то мы бы до сих пор программировали в машинных кодах.
Чем команда printf() отличается от cout?
Раньше, когда я начинал изучать С++, я использовал команду printf(). А тут обучают команде cout. Между ним есть различия или это зависит от версии языка?
4th Feb 2020, 7:03 AM
Majid Isaev
Often have questions like this?
Learn more efficiently, for free:
Introduction to Python 7.1M learners
Introduction to Java 4.7M learners
Introduction to C 1.5M learners
Introduction to HTML 7.5M learners
Чем отличается cout от printf
Ну как сказать. Вообще это принципиально разные вещи.
cout и cin - это потоки. Конкретно cin является экземпляром класса cin, который есть специализация шаблона basic_istream:
typedef basic_istream istream; istream cin;
При это basic_istream является потомком шаблона basic_ios, а тот в свою очередь вообще является потомком класса ios_base.
Аналогично и cout - экземпляр класса ostream, являющегося специализацией шаблона basic_ostream.
А printf и scanf - это просто функции, самые что ни на есть обычные.
В силу такого различия у cin и cout есть куча более высокоуровневых возможностей по сравнению с printf и scanf, так же, как и у других потоков. Для справки,
cout
это не просто вызов функции, а вызов оператора operator Среди возможностей и преимуществ потоков - перегрузка операторов ввода/вывода, использование манипуляторов, единый интерфейс с другими потоками (файловыми, строковыми и прочими).
Если вы пишите на C++ - используйте стандартную библиотеку, т.е. потоки.