{fmt} — это библиотека форматирования с открытым исходным кодом, предоставляющая быструю и безопасную альтернативу потокам C stdio и C++ iostreams.
Если вам понравился этот проект, рассмотрите возможность сделать пожертвование в один из фондов помощи жертвам войны в Украине: https://www.stopputin.net/.
Документация
Шпаргалки
Вопросы и ответы: задавайте вопросы на StackOverflow с тегом fmt.
Попробуйте {fmt} в обозревателе компилятора.
API простого формата с позиционными аргументами для локализации
Реализация C++20 std::format и C++23 std::print
Синтаксис строки формата аналогичен формату Python.
Быстрый форматировщик чисел с плавающей запятой IEEE 754 с правильным округлением, краткостью и гарантиями двустороннего прохождения с использованием алгоритма Dragonbox.
Портативная поддержка Unicode
Безопасная реализация printf, включая расширение POSIX для позиционных аргументов.
Расширяемость: поддержка пользовательских типов.
Высокая производительность: быстрее, чем реализации обычных стандартных библиотек (s)printf
, iostreams, to_string
и to_chars
, см. Тесты скорости и Преобразование ста миллионов целых чисел в строки в секунду.
Небольшой размер кода как с точки зрения исходного кода с минимальной конфигурацией, состоящей всего из трех файлов core.h
, format.h
и format-inl.h
, так и скомпилированного кода; см. Время компиляции и раздувание кода.
Надежность: библиотека имеет обширный набор тестов и постоянно подвергается фаззингу.
Безопасность: библиотека полностью типобезопасна, об ошибках в строках формата можно сообщить во время компиляции, автоматическое управление памятью предотвращает ошибки переполнения буфера.
Простота использования: небольшая автономная база кода, отсутствие внешних зависимостей, разрешающая лицензия MIT.
Переносимость с единообразным выводом на разных платформах и поддержка старых компиляторов.
Чистая кодовая база без предупреждений даже на высоких уровнях предупреждений, таких как -Wall -Wextra -pedantic
Независимость от локали по умолчанию
Дополнительная конфигурация только заголовка, включенная с помощью макроса FMT_HEADER_ONLY
Более подробную информацию смотрите в документации.
Печать в стандартный вывод (запуск)
#include <fmt/core.h>int main() { fmt::print("Привет, мир!n"); }
Форматировать строку (запустить)
std::string s = fmt::format("Ответ: {}.", 42);// s == "Ответ: 42."
Форматирование строки с использованием позиционных аргументов (запуск)
std::string s = fmt::format("Я лучше буду {1}, чем {0}.", "прав", "счастлив");// s == "Я лучше буду счастлив, чем прав ."
Печать даты и времени (запуск)
#include <fmt/chrono.h>int main() { auto now = std::chrono::system_clock::now(); fmt::print("Дата и время: {}n", сейчас); fmt::print("Время: {:%H:%M}n", сейчас); }
Выход:
Date and time: 2023-12-26 19:10:31.557195597 Time: 19:10
Распечатать контейнер (запустить)
#include <vector>#include <fmt/ranges.h>int main() { std::vector<int> v = {1, 2, 3}; fmt::print("{}n", v); }
Выход:
[1, 2, 3]
Проверьте строку формата во время компиляции
std::string s = fmt::format("{:d}", "Я не число");
Это приводит к ошибке времени компиляции в C++20, поскольку d
является недопустимым спецификатором формата строки.
Запись файла из одного потока
#include <fmt/os.h>int main() { auto out = fmt::output_file("guide.txt"); out.print("Не {}", "Паника"); }
Это может быть в 5–9 раз быстрее, чем fprintf.
Печать с использованием цветов и стилей текста
#include <fmt/color.h>int main() { fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "Hello, {}!n", "world" ); fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) | fmt::emphasis::underline, "Ола, {}!n", "Mundo"); fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic, "你好{}!n", "世界"); }
Вывод на современном терминале с поддержкой Unicode:
Библиотека | Метод | Время работы, с |
---|---|---|
libc | печать | 0,91 |
библиотека libС++ | станд::ostream | 2.49 |
{ФМТ} 9.1 | fmt::print | 0,74 |
Формат повышения 1.80 | повышение::формат | 6.26 |
Формат глупости | глупость::формат | 1,87 |
{fmt} — самый быстрый из протестированных методов, он примерно на 20 % быстрее, чем printf
.
Приведенные выше результаты были получены путем сборки tinyformat_test.cpp
в macOS 12.6.1 с помощью clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT
и взятия лучшего из трех прогонов. В тесте строка формата "%0.10f:%04d:%+g:%s:%p:%c:%%n"
или ее эквивалент заполняется 2 000 000 раз, а выходные данные отправляются в /dev/null
; для получения более подробной информации обратитесь к источнику.
{fmt} работает в 20–30 раз быстрее, чем std::ostringstream
и sprintf
при IEEE754 float
и double
форматировании (dtoa-benchmark), а также быстрее, чем двойное преобразование и ryu:
Скрипт bloat-test.py из тестов format-benchmark увеличивает время компиляции и раздувает код для нетривиальных проектов. Он генерирует 100 единиц перевода и использует printf()
или его альтернативу пять раз в каждой для моделирования проекта среднего размера. Результирующий размер исполняемого файла и время компиляции (Apple clang версии 15.0.0 (clang-1500.1.0.2.5), macOS Sonoma, лучшая из трех) показаны в следующих таблицах.
Оптимизированная сборка (-O3)
Метод | Время компиляции, с | Размер исполняемого файла, КиБ | Разобранный размер, КиБ |
---|---|---|---|
печать | 1,6 | 54 | 50 |
IO-потоки | 25,9 | 98 | 84 |
fmt 83652df | 4,8 | 54 | 50 |
крошечный формат | 29.1 | 161 | 136 |
Формат повышения | 55,0 | 530 | 317 |
{fmt} быстро компилируется и сравним с printf
с точки зрения двоичного размера каждого вызова (с точностью до ошибки округления в этой системе).
Неоптимизированная сборка
Метод | Время компиляции, с | Размер исполняемого файла, КиБ | Разобранный размер, КиБ |
---|---|---|---|
печать | 1,4 | 54 | 50 |
IO-потоки | 23,4 | 92 | 68 |
{fmt} 83652df | 4.4 | 89 | 85 |
крошечный формат | 24,5 | 204 | 161 |
Формат повышения | 36,4 | 831 | 462 |
libc
, lib(std)c++
и libfmt
связаны как общие библиотеки только для сравнения накладных расходов функций форматирования. Boost Format — это библиотека только для заголовков, поэтому она не предоставляет никаких параметров связывания.
Инструкции по сборке библиотеки и запуску модульных тестов см. в разделе Создание библиотеки.
Тесты производительности находятся в отдельном репозитории format-benchmarks, поэтому для запуска тестов вам сначала необходимо клонировать этот репозиторий и сгенерировать файлы Makefile с помощью CMake:
$ git clone --recursive https://github.com/fmtlib/format-benchmark.git $ cd format-benchmark $ cmake .
Затем вы можете запустить тест скорости:
$ make speed-test
или тест на раздувание:
$ make bloat-test
clang-tidy v18 обеспечивает проверку Modernize-use-std-print, которая способна преобразовывать экземпляры printf
и fprintf
в fmt::print
если это настроено. (По умолчанию он преобразуется в std::print
.)
0 AD: бесплатная кроссплатформенная стратегическая игра в реальном времени с открытым исходным кодом.
AMPL/MP: библиотека с открытым исходным кодом для математического программирования.
FoundationDB от Apple: распределенное транзакционное хранилище ключей и значений с открытым исходным кодом.
Aseprite: редактор анимированных спрайтов и инструмент пиксельной графики
AvioBook: комплексный пакет для управления воздушными судами
Blizzard Battle.net: игровая онлайн-платформа.
Celestia: 3D-визуализация космоса в реальном времени
Ceph: масштабируемая распределенная система хранения
ccache: кеш компилятора
ClickHouse: аналитическая система управления базами данных
ContextVision: программное обеспечение для медицинской визуализации
Contour: современный эмулятор терминала
CUAUV: автономный подводный аппарат Корнеллского университета
Drake: набор инструментов для планирования, контроля и анализа нелинейных динамических систем (MIT).
Envoy: прокси-сервер C++ L7 и коммуникационная шина (Lyft)
FiveM: фреймворк модификации для GTA V
fmtlog: производительная библиотека журналирования в стиле fmtlib с задержкой в наносекундах.
Folly: библиотека Facebook с открытым исходным кодом
GemRB: портативная реализация Infinity Engine от Bioware с открытым исходным кодом.
Grand Mountain Adventure: красивая игра о лыжах и сноуборде с открытым миром
HarpyWar/pvpgn: игровая сеть «Игрок против игрока» с настройками
KBEngine: серверный движок MMOG с открытым исходным кодом.
Keypirinha: семантический лаунчер для Windows
Kodi (ранее xbmc): программное обеспечение для домашнего кинотеатра.
Кнут: высокопроизводительный полный узел Биткойна
libunicode: современная библиотека Unicode C++17.
MariaDB: система управления реляционными базами данных
Microsoft Verona: исследовательский язык программирования для одновременного владения
MongoDB: распределенная база данных документов
MongoDB Smasher: небольшой инструмент для создания рандомизированных наборов данных.
OpenSpace: платформа астровизуализации с открытым исходным кодом.
PenUltima Online (POL): сервер MMO, совместимый с большинством клиентов Ultima Online.
PyTorch: библиотека машинного обучения с открытым исходным кодом.
quasardb: распределенная высокопроизводительная ассоциативная база данных.
Quill: асинхронная библиотека журналирования с малой задержкой.
QKW: обобщение псевдонимов для упрощения навигации и выполнения сложных многострочных последовательностей команд терминала.
redis-cerberus: прокси-сервер кластера Redis
redpanda: замена Kafka® в 10 раз быстрее для критически важных систем, написанная на C++
rpclib: современный C++ сервер и клиентская библиотека msgpack-RPC.
Salesforce Analytics Cloud: программное обеспечение для бизнес-аналитики
Scylla: совместимое с Cassandra хранилище данных NoSQL, способное обрабатывать 1 миллион транзакций в секунду на одном сервере.
Seastar: передовая платформа C++ с открытым исходным кодом для высокопроизводительных серверных приложений на современном оборудовании.
spdlog: сверхбыстрая библиотека журналирования C++.
Stellar: финансовая платформа
Touch Surgery: симулятор хирургии
TrinityCore: платформа MMORPG с открытым исходным кодом.
? userver framework: асинхронная платформа с открытым исходным кодом и богатым набором абстракций и драйверов баз данных.
Терминал Windows: новый терминал Windows
Более...
Если вам известны другие проекты, использующие эту библиотеку, сообщите мне об этом по электронной почте или отправив сообщение о проблеме.
Так зачем еще одна библиотека форматирования?
Существует множество методов для выполнения этой задачи: от стандартных, таких как семейство функций printf и iostreams, до библиотек Boost Format и FastFormat. Причина создания новой библиотеки заключается в том, что каждое существующее решение, которое я нашел, либо имело серьезные проблемы, либо не предоставляло все необходимые мне функции.
Преимущество printf
в том, что он довольно быстр и легко доступен, поскольку является частью стандартной библиотеки C. Основным недостатком является то, что он не поддерживает типы, определяемые пользователем. printf
также есть проблемы с безопасностью, хотя они несколько смягчаются с помощью __attribute__ ((format (printf, ...)) в GCC. Существует расширение POSIX, которое добавляет позиционные аргументы, необходимые для i18n, в printf
, но оно не является частью C99 и может не быть доступным на некоторых платформах.
Основную проблему с iostreams лучше всего проиллюстрировать на примере:
std::cout << std::setprecision(2) << std::fixed << 1.23456 << "n";
что требует много ввода по сравнению с printf:
printf("%.2fn", 1.23456);
Мэтью Уилсон, автор FastFormat, назвал это «шевронным адом». iostreams изначально не поддерживает позиционные аргументы.
Хорошая часть заключается в том, что iostreams поддерживают определяемые пользователем типы и безопасны, хотя обработка ошибок неудобна.
Это очень мощная библиотека, которая поддерживает как строки формата printf
, так и позиционные аргументы. Главный его недостаток – производительность. Согласно различным тестам, он намного медленнее, чем другие рассмотренные здесь методы. Формат Boost также требует длительного времени сборки и серьезных проблем с раздуванием кода (см. Контрольные показатели).
Это интересная библиотека, быстрая, безопасная и имеющая позиционные аргументы. Однако он имеет существенные ограничения, цитируя его автора:
Три особенности, которые не имеют никакой надежды быть учтенными в текущем дизайне:
Ведущие нули (или любое другое дополнение, не являющееся пробелом)
Восьмеричная/шестнадцатеричная кодировка
Спецификация ширины/выравнивания во время выполнения
Он также довольно большой и сильно зависит от STLSoft, который может быть слишком ограничительным для использования в некоторых проектах.
Это не библиотека форматирования, но я решил включить ее сюда для полноты картины. Как и iostreams, он страдает от проблемы смешивания дословного текста с аргументами. Библиотека работает довольно быстро, но медленнее при форматировании целых чисел, чем fmt::format_to
с компиляцией строки формата в собственном тесте Karma, см. Преобразование ста миллионов целых чисел в строки в секунду.
{fmt} распространяется по лицензии MIT.
Раздел «Синтаксис строки формата» в документации основан на разделе документации строкового модуля Python. По этой причине документация распространяется по лицензии Python Software Foundation, доступной в doc/python-license.txt. Это применимо только в том случае, если вы распространяете документацию {fmt}.
Библиотеку {fmt} поддерживает Виктор Зверович (vitaut) при участии многих других людей. Некоторые имена см. в разделе «Участники и релизы». Сообщите нам, если ваш вклад не указан или не упомянут неправильно, и мы исправим это.
Чтобы сообщить о проблеме безопасности, сообщите об этом в разделе рекомендаций по безопасности.
Этот проект поддерживается командой волонтеров на разумной основе. Поэтому, пожалуйста, дайте нам как минимум 90 дней на работу над исправлением, прежде чем оно будет опубликовано.