Я должен использовать printf в своем коде C++?

Приложения Spring-boot используют spring-boot-starter-web в зависимостях POM.xml. Эта конкретная зависимость загружает Джексон-тип данных быстрее xmls, который инициализируется при использовании @springbootapplication.

67
задан MD XF 25 February 2017 в 04:11
поделиться

14 ответов

Мои ученики, которые сначала изучают cin и cout, а затем узнают printf позже, в подавляющем большинстве своем предпочитают printf (или более обычно fprintf). Я сам нашел модель printf достаточно читабельной, что я портировал её на другие языки программирования. Так же как и Оливье Дэнви , который даже сделал ее тип-безопасной.

Если у вас есть компилятор, способный проверять вызовы типа в printf, то я не вижу причин не использовать fprintf и друзей на Си++.

Disclaimer: Я ужасный программист на Си++.

.
68
ответ дан 24 November 2019 в 14:26
поделиться

(См. fmt домашняя страница библиотеки )

В C++ 20, библиотека fmt стандартизирована для части форматирования:

std::format("({},{})\n", x, y) // returns a std::string

можно избежать динамического выделения наверху при помощи format_to:

std::format_to(/* output iterator */, "({},{})\n", x, y);

Это нужно считать каноническим способом отформатировать, потому что он комбинирует преимущества потоков:

  • Безопасность : библиотека полностью безопасна с точки зрения типов. Автоматическое управление памятью предотвращает переполнение буфера. Об ошибках в строках формата сообщают с помощью исключений или во время компиляции.

  • Расширяемость : перегрузка operator<< легка, тогда как расширение printf... не так легко.

и тот из printf:

  • Простота для использования : % синтаксис поддерживается, а не подробные манипуляторы. {} синтаксис также представлен для устранения спецификаторов.

  • Производительность : измерение показало, что fmt библиотека является до сих пор самым быстрым выходным методом в C++. Быстрее, чем printf и потоки.

0
ответ дан 24 November 2019 в 14:26
поделиться

потоки предпочтительны в cpp, так как они придерживаются объектно-ориентированной парадигмы cpp,

printf, с другой стороны, является скорее функциональным подходом.

единственная причина не использовать printf в cpp-коде, о которой я могу думать, не является объектно-ориентированной.

это скорее личный выбор.

-1
ответ дан 24 November 2019 в 14:26
поделиться

Я часто "отступаю" к использованию printf(), но чаще snprintf() для более легкого форматирования вывода. При программировании на Си++ я использую эту обертку, которую я написал некоторое время назад, вызвав ее так (чтобы использовать ваш пример, как описано выше): cout << format("(%d,%d)\n", x, y);

Вот заголовок (stdiomm.h):

#pragma once

#include <cstdarg>
#include <string>

template <typename T>
std::basic_string<T> format(T const *format, ...);

template <typename T>
std::basic_string<T> vformat(T const *format, va_list args);

И источник (stdiomm.cpp):

#include "stdiomm.h"
#include <boost/scoped_array.hpp>
#include <cstdio>

template <>
std::wstring vformat(wchar_t const *format, va_list arguments)
{
#if defined(_WIN32)
    int required(_vscwprintf(format, arguments));
    assert(required >= 0);
    boost::scoped_array<wchar_t> buffer(new wchar_t[required + 1]);
    int written(vswprintf(buffer.get(), required + 1, format, arguments));
    assert(written == required);
    return std::wstring(buffer.get(), written);
#else
#   error "No implementation yet"
#endif
}

template <>
std::string vformat(char const *format, va_list arguments)
{
#if defined(_WIN32)
    int required(_vscprintf(format, arguments));
    assert(required >= 0);
    boost::scoped_array<char> buffer(new char[required + 1]);
    int written(vsnprintf(buffer.get(), required + 1, format, arguments));
    assert(written == required);
    return std::string(buffer.get(), written);
#else
    char *buffer;
    int printed = vasprintf(&buffer, format, arguments);
    assert(printed != -1);
    std::string retval(buffer, printed);
    free(buffer);
    return retval;      
#endif
}

template <typename T>
std::basic_string<T> format(T const *format, ...)
{
    va_list ap;
    va_start(ap, format);
    std::basic_string<T> retval(vformat(format, ap));
    va_end(ap);
    return retval;
}

template std::wstring format(wchar_t const *format, ...);
template std::string format(char const *format, ...);

Обновление

После прочтения некоторых других ответов, мне, возможно, придется переключиться на boost::format() myself!

.
3
ответ дан 24 November 2019 в 14:26
поделиться

Я не люблю печатать. Отсутствие типовой безопасности делает его опасным в использовании, плюс необходимость запоминать спецификаторы формата - это больно. Шаблонные операторы, которые умело делают правильные вещи, гораздо лучше. Поэтому я всегда использую потоки C++ в C++.

Разрешено, многие предпочитают printf, по другим причинам, перечисленным в другом месте.

.
3
ответ дан 24 November 2019 в 14:26
поделиться

В целом я согласен (ненавижу <<синтаксис, особенно если вам нужно сложное форматирование)

Но я должен обратить внимание на аспекты безопасности.

printf("%x",2.0f)
printf("%x %x",2)
printf("%x",2,2)

Наверное, компилятор не заметит, но может привести к краху вашего приложения.

5
ответ дан 24 November 2019 в 14:26
поделиться

Используйте printf. Не используйте потоки C++. printf дает гораздо лучший контроль (например, точность поплавка и т.д.). Код также обычно короче и более читабельный.

Google C++ style guide согласен.

Не используйте потоки, кроме тех случаев, когда требуемый лог-интерфейсом. Использовать Вместо этого есть различные "за" и "против".

Есть различные "за" и "против", чтобы используя потоки, но в данном случае, как в случае с многие другие случаи, козыри согласованности дебаты. Не используйте потоки в вашем code.

5
ответ дан 24 November 2019 в 14:26
поделиться

Никакой причины. Я думаю, что это просто какая-то странная идеология, которая подталкивает людей к использованию только библиотек Си++, несмотря на то, что старые добрые либбики Си все еще актуальны. Я парень с C++ и тоже часто использую функции C. У меня никогда не было с ними проблем.

7
ответ дан 24 November 2019 в 14:26
поделиться

Потоки - это канонический путь. Попробуйте заставить этот код работать с printf:

template <typename T>
void output(const T& pX)
{
    std::cout << pX << std::endl;
}

Удачи.

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

Это больше, чем просто удобство. Есть еще и согласованность. Во всех моих проектах у меня есть cout (и cerr и clog) тройка, которая также выводится в файл. Если вы используете printf, вы пропустите все это. Кроме того, консистенция сама по себе является хорошей вещью; смешивание cout и printf, хотя и является абсолютно корректным, является уродливым.

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

Если вы действительно хотите отформатировать, используйте Boost.Format, сохраняя при этом интерфейс потока. Согласованность форматирования и .

.
6
ответ дан 24 November 2019 в 14:26
поделиться

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

19
ответ дан 24 November 2019 в 14:26
поделиться

Я использую printf, потому что ненавижу уродливый < синтаксис.

19
ответ дан 24 November 2019 в 14:26
поделиться

Если вы когда-нибудь надеетесь на i18 в вашей программе, держитесь подальше от iostreams. Проблема в том, что может быть невозможно правильно локализовать строки, если предложение состоит из нескольких фрагментов, как это делается в iostream.

Помимо проблемы фрагментов сообщений, у вас также возникает проблема упорядочивания. Рассмотрим отчет, который печатает имя ученика и его средний балл успеваемости:

std::cout << name << " has a GPA of " << gpa << std::endl;

Когда вы переводите его на другой язык, грамматике другого языка может понадобиться, чтобы вы показали средний балл успеваемости перед именем. AFAIK, iostreams не может переупорядочить интерполированные значения.

Если вы хотите получить лучшее из обоих миров (безопасность печати и возможность i18n), используйте Boost.Format.

.
48
ответ дан 24 November 2019 в 14:26
поделиться

Используйте все, что соответствует вашим потребностям и предпочтениям. Если вам удобно использовать printf, то обязательно используйте его. Если вы счастливее с iostreams, придерживайтесь их. Смешивайте и подбирайте то, что лучше всего соответствует вашим требованиям. В конце концов, это программное обеспечение - есть лучшие и худшие способы, но редко бывает только ОДИН.

Поделитесь и наслаждайтесь.

4
ответ дан 24 November 2019 в 14:26
поделиться

Я почти всегда использую printf для временных отладочных операторов. Для более постоянного кода я предпочитаю потоки 'c', так как это The C++ Way. Хотя boost::format выглядит многообещающе и может заменить мое использование потоков (особенно для сложного форматирования вывода), наверное, ничто не заменит мне printf долгое время.

0
ответ дан 24 November 2019 в 14:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: