Приложения Spring-boot используют spring-boot-starter-web в зависимостях POM.xml. Эта конкретная зависимость загружает Джексон-тип данных быстрее xmls, который инициализируется при использовании @springbootapplication.
Мои ученики, которые сначала изучают cin
и cout
, а затем узнают printf
позже, в подавляющем большинстве своем предпочитают printf
(или более обычно fprintf
). Я сам нашел модель printf
достаточно читабельной, что я портировал её на другие языки программирования. Так же как и Оливье Дэнви , который даже сделал ее тип-безопасной.
Если у вас есть компилятор, способный проверять вызовы типа в printf
, то я не вижу причин не использовать fprintf
и друзей на Си++.
Disclaimer: Я ужасный программист на Си++.
.(См. 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
и потоки.
потоки предпочтительны в cpp, так как они придерживаются объектно-ориентированной парадигмы cpp,
printf, с другой стороны, является скорее функциональным подходом.
единственная причина не использовать printf в cpp-коде, о которой я могу думать, не является объектно-ориентированной.
это скорее личный выбор.
Я часто "отступаю" к использованию 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!
Я не люблю печатать. Отсутствие типовой безопасности делает его опасным в использовании, плюс необходимость запоминать спецификаторы формата - это больно. Шаблонные операторы, которые умело делают правильные вещи, гораздо лучше. Поэтому я всегда использую потоки C++ в C++.
Разрешено, многие предпочитают printf, по другим причинам, перечисленным в другом месте.
.В целом я согласен (ненавижу <<синтаксис, особенно если вам нужно сложное форматирование)
Но я должен обратить внимание на аспекты безопасности.
printf("%x",2.0f)
printf("%x %x",2)
printf("%x",2,2)
Наверное, компилятор не заметит, но может привести к краху вашего приложения.
Используйте printf. Не используйте потоки C++. printf дает гораздо лучший контроль (например, точность поплавка и т.д.). Код также обычно короче и более читабельный.
Google C++ style guide согласен.
Не используйте потоки, кроме тех случаев, когда требуемый лог-интерфейсом. Использовать Вместо этого есть различные "за" и "против".
Есть различные "за" и "против", чтобы используя потоки, но в данном случае, как в случае с многие другие случаи, козыри согласованности дебаты. Не используйте потоки в вашем code.
Никакой причины. Я думаю, что это просто какая-то странная идеология, которая подталкивает людей к использованию только библиотек Си++, несмотря на то, что старые добрые либбики Си все еще актуальны. Я парень с C++ и тоже часто использую функции C. У меня никогда не было с ними проблем.
Потоки - это канонический путь. Попробуйте заставить этот код работать с 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, сохраняя при этом интерфейс потока. Согласованность форматирования и .
.Используйте формат boost::. Вы получаете безопасность типа, поддержку std::string, printf как интерфейс, возможность использовать cout, и много других хороших вещей. Вы не вернетесь.
Я использую printf, потому что ненавижу уродливый <
Если вы когда-нибудь надеетесь на i18 в вашей программе, держитесь подальше от iostreams. Проблема в том, что может быть невозможно правильно локализовать строки, если предложение состоит из нескольких фрагментов, как это делается в iostream.
Помимо проблемы фрагментов сообщений, у вас также возникает проблема упорядочивания. Рассмотрим отчет, который печатает имя ученика и его средний балл успеваемости:
std::cout << name << " has a GPA of " << gpa << std::endl;
Когда вы переводите его на другой язык, грамматике другого языка может понадобиться, чтобы вы показали средний балл успеваемости перед именем. AFAIK, iostreams не может переупорядочить интерполированные значения.
Если вы хотите получить лучшее из обоих миров (безопасность печати и возможность i18n), используйте Boost.Format.
.Используйте все, что соответствует вашим потребностям и предпочтениям. Если вам удобно использовать printf, то обязательно используйте его. Если вы счастливее с iostreams, придерживайтесь их. Смешивайте и подбирайте то, что лучше всего соответствует вашим требованиям. В конце концов, это программное обеспечение - есть лучшие и худшие способы, но редко бывает только ОДИН.
Поделитесь и наслаждайтесь.
Я почти всегда использую printf для временных отладочных операторов. Для более постоянного кода я предпочитаю потоки 'c', так как это The C++ Way. Хотя boost::format выглядит многообещающе и может заменить мое использование потоков (особенно для сложного форматирования вывода), наверное, ничто не заменит мне printf долгое время.