{fmt}는 C stdio 및 C++ iostream에 대한 빠르고 안전한 대안을 제공하는 오픈 소스 형식 라이브러리입니다.
이 프로젝트가 마음에 드신다면 우크라이나 전쟁 피해자를 돕는 기금 중 하나인 https://www.stopputin.net/에 기부해 보시기 바랍니다.
선적 서류 비치
치트 시트
Q&A: fmt 태그를 사용하여 StackOverflow에 질문하세요.
컴파일러 탐색기에서 {fmt}를 사용해 보세요.
현지화를 위한 위치 인수가 있는 간단한 형식 API
C++20 std::format 및 C++23 std::print 구현
Python의 형식과 유사한 형식 문자열 구문
Dragonbox 알고리즘을 사용하여 올바른 반올림, 단축 및 왕복을 보장하는 빠른 IEEE 754 부동 소수점 포맷터
휴대용 유니코드 지원
위치 인수에 대한 POSIX 확장을 포함한 안전한 printf 구현
확장성: 사용자 정의 유형 지원
고성능: (s)printf
, iostreams, to_string
및 to_chars
의 일반적인 표준 라이브러리 구현보다 빠릅니다. 속도 테스트 및 초당 수억 개의 정수를 문자열로 변환을 참조하세요.
core.h
, format.h
및 format-inl.h
3개의 파일과 컴파일된 코드로 구성된 최소 구성의 소스 코드 측면에서 코드 크기가 작습니다. 컴파일 시간 및 코드 팽창을 참조하세요.
신뢰성: 라이브러리에는 광범위한 테스트 세트가 있으며 지속적으로 퍼지됩니다.
안전성: 라이브러리는 완전히 유형이 안전하며 형식 문자열의 오류는 컴파일 타임에 보고될 수 있으며 자동 메모리 관리는 버퍼 오버플로 오류를 방지합니다.
사용 용이성: 작은 독립형 코드 기반, 외부 종속성 없음, 허용되는 MIT 라이센스
플랫폼 전반에 걸쳐 일관된 출력을 제공하고 이전 컴파일러를 지원하는 이식성
-Wall -Wextra -pedantic
과 같은 높은 경고 수준에서도 경고 없는 코드베이스를 정리합니다.
기본적으로 로케일 독립성
FMT_HEADER_ONLY
매크로를 사용하여 선택적 헤더 전용 구성 활성화
자세한 내용은 설명서를 참조하세요.
표준 출력으로 인쇄 (실행)
#include <fmt/core.h>int main() { fmt::print("Hello, world!n"); }
문자열 형식 지정 (실행)
std::string s = fmt::format("답은 {}입니다.", 42);// s == "답은 42입니다."
위치 인수를 사용하여 문자열 형식 지정 (실행)
std::string s = fmt::format("나는 {0}보다는 {1}이 더 낫습니다.", "맞습니다", "행복합니다");// 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 <벡터>#include <fmt/ranges.h>int main() { 표준::벡터<int> v = {1, 2, 3}; fmt::print("{}n", v); }
산출:
[1, 2, 3]
컴파일 타임에 형식 문자열 확인
std::string s = fmt::format("{:d}", "나는 숫자가 아닙니다");
d
문자열에 대한 잘못된 형식 지정자이기 때문에 C++20에서는 컴파일 타임 오류가 발생합니다.
단일 스레드에서 파일 쓰기
#include <fmt/os.h>int main() { auto out = fmt::output_file("guide.txt"); out.print("{}하지 마세요", "패닉"); }
이는 fprintf보다 5~9배 더 빠를 수 있습니다.
색상 및 텍스트 스타일로 인쇄
#include <fmt/color.h>int main() { fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "안녕하세요, {}!n", "world" ); fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) | fmt::emphasis::underline, "Olá, {}!n", "Mundo"); fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic, "你好{}!n", "world"); }
유니코드를 지원하는 최신 터미널에서 출력:
도서관 | 방법 | 런타임, 초 |
---|---|---|
libc | printf | 0.91 |
libc++ | 표준::ostream | 2.49 |
{fmt} 9.1 | fmt::인쇄 | 0.74 |
부스트 형식 1.80 | 부스트::형식 | 6.26 |
어리석은 형식 | 어리석음::형식 | 1.87 |
{fmt}는 벤치마크된 방법 중 가장 빠르며 printf
보다 ~20% 빠릅니다.
위 결과는 clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT
사용하여 macOS 12.6.1에서 tinyformat_test.cpp
빌드하고 세 가지 실행 중 최선을 다하여 생성되었습니다. 테스트에서 형식 문자열 "%0.10f:%04d:%+g:%s:%p:%c:%%n"
또는 이에 상응하는 내용은 /dev/null
로 전송된 출력으로 2,000,000번 채워집니다. 자세한 내용은 소스를 참조하세요.
{fmt}는 IEEE754 float
및 double
형식(dtoa-benchmark)에서 std::ostringstream
및 sprintf
보다 최대 20-30배 빠르며 이중 변환 및 ryu보다 빠릅니다.
format-benchmark의 bloat-test.py 스크립트는 중요하지 않은 프로젝트의 컴파일 시간과 코드 팽창을 테스트합니다. 100개의 번역 단위를 생성하고 printf()
또는 그 대안을 각각 5번 사용하여 중간 규모 프로젝트를 시뮬레이션합니다. 결과 실행 파일 크기 및 컴파일 시간(Apple clang 버전 15.0.0(clang-1500.1.0.2.5), macOS Sonoma, 세 가지 중 최고)은 다음 표에 나와 있습니다.
최적화된 빌드(-O3)
방법 | 컴파일 시간, 초 | 실행 가능 크기, KiB | 제거된 크기, KiB |
---|---|---|---|
printf | 1.6 | 54 | 50 |
IOStream | 25.9 | 98 | 84 |
fmt 83652df | 4.8 | 54 | 50 |
작은 형식 | 29.1 | 161 | 136 |
부스트 형식 | 55.0 | 530 | 317 |
{fmt}는 컴파일 속도가 빠르고 호출당 바이너리 크기 측면에서 printf
와 비슷합니다(이 시스템에서는 반올림 오류 내에서).
최적화되지 않은 빌드
방법 | 컴파일 시간, 초 | 실행 가능 크기, KiB | 제거된 크기, KiB |
---|---|---|---|
printf | 1.4 | 54 | 50 |
IOStream | 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에 있으므로 벤치마크를 실행하려면 먼저 이 저장소를 복제하고 CMake를 사용하여 Makefile을 생성해야 합니다.
$ git clone --recursive https://github.com/fmtlib/format-benchmark.git $ cd format-benchmark $ cmake .
그런 다음 속도 테스트를 실행할 수 있습니다.
$ make speed-test
또는 팽창 테스트:
$ make bloat-test
clang-tidy v18은 그렇게 구성한 경우 printf
및 fprintf
발생을 fmt::print
로 변환할 수 있는 modernize-use-std-print 검사를 제공합니다. (기본적으로 std::print
로 변환됩니다.)
0 AD: 무료 오픈 소스 크로스 플랫폼 실시간 전략 게임
AMPL/MP: 수학 프로그래밍을 위한 오픈 소스 라이브러리
Apple의 FoundationDB: 오픈 소스, 분산, 트랜잭션 키-값 저장소
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: Bioware Infinity Engine의 휴대용 오픈 소스 구현
그랜드 마운틴 어드벤처(Grand Mountain Adventure): 아름다운 오픈 월드 스키 및 스노보드 게임
HarpyWar/pvpgn: 변경된 플레이어 대 플레이어 게임 네트워크
KBEngine: 오픈 소스 MMOG 서버 엔진
Keypirinha: Windows용 시맨틱 런처
Kodi(이전 xbmc): 홈 시어터 소프트웨어
Knuth: 고성능 비트코인 풀노드
libunicode: 최신 C++17 유니코드 라이브러리
MariaDB: 관계형 데이터베이스 관리 시스템
Microsoft Verona: 동시 소유권을 위한 연구 프로그래밍 언어
MongoDB: 분산 문서 데이터베이스
MongoDB Smasher: 무작위 데이터 세트를 생성하는 작은 도구
OpenSpace: 오픈 소스 천체 시각화 프레임워크
PenUltima Online(POL): 대부분의 Ultima Online 클라이언트와 호환되는 MMO 서버
PyTorch: 오픈 소스 기계 학습 라이브러리
quasardb: 분산된 고성능 연관 데이터베이스
Quill: 지연 시간이 짧은 비동기 로깅 라이브러리
QKW: 앨리어싱을 일반화하여 탐색을 단순화하고 복잡한 여러 줄 터미널 명령 시퀀스를 실행합니다.
redis-cerberus: Redis 클러스터 프록시
redpanda: C++로 작성된 미션 크리티컬 시스템을 위한 10배 빠른 Kafka® 대체품
rpclib: 최신 C++ msgpack-RPC 서버 및 클라이언트 라이브러리
Salesforce Analytics Cloud: 비즈니스 인텔리전스 소프트웨어
Scylla: 단일 서버에서 초당 100만 건의 트랜잭션을 처리할 수 있는 Cassandra 호환 NoSQL 데이터 저장소
Seastar: 최신 하드웨어의 고성능 서버 애플리케이션을 위한 고급 오픈 소스 C++ 프레임워크
spdlog: 초고속 C++ 로깅 라이브러리
스텔라: 금융 플랫폼
터치 수술: 수술 시뮬레이터
TrinityCore: 오픈 소스 MMORPG 프레임워크
? userver 프레임워크: 풍부한 추상화 및 데이터베이스 드라이버 세트를 갖춘 오픈 소스 비동기 프레임워크
Windows 터미널: 새로운 Windows 터미널
더...
이 라이브러리를 사용하는 다른 프로젝트에 대해 알고 계시다면 이메일이나 문제 제출을 통해 알려주시기 바랍니다.
그렇다면 왜 또 다른 서식 라이브러리가 있습니까?
이 작업을 수행하는 데는 printf 함수 및 iostreams 계열과 같은 표준 방법부터 Boost Format 및 FastFormat 라이브러리에 이르기까지 다양한 방법이 있습니다. 새 라이브러리를 만드는 이유는 내가 찾은 모든 기존 솔루션에 심각한 문제가 있거나 필요한 모든 기능을 제공하지 않았기 때문입니다.
printf
의 좋은 점은 C 표준 라이브러리의 일부로서 매우 빠르고 쉽게 사용할 수 있다는 것입니다. 가장 큰 단점은 사용자 정의 유형을 지원하지 않는다는 것입니다. printf
에도 GCC의 __attribute__ ((format (printf, ...))를 사용하면 다소 완화되기는 하지만 안전 문제가 있습니다. i18n에 필요한 위치 인수를 printf
에 추가하는 POSIX 확장이 있지만 C99의 일부가 아니며 일부 플랫폼에서는 사용할 수 없습니다.
iostreams의 주요 문제는 다음 예를 통해 가장 잘 설명됩니다.
std::cout << std::setprecision(2) << std::fixed << 1.23456 << "n";
printf에 비해 입력량이 많습니다.
printf("%.2fn", 1.23456);
FastFormat의 저자인 Matthew Wilson은 이것을 "쉐브론 지옥"이라고 불렀습니다. iostream은 설계상 위치 인수를 지원하지 않습니다.
좋은 점은 iostream이 사용자 정의 유형을 지원하고 오류 처리가 어색하더라도 안전하다는 것입니다.
이것은 printf
와 유사한 형식 문자열과 위치 인수를 모두 지원하는 매우 강력한 라이브러리입니다. 주요 단점은 성능입니다. 다양한 벤치마크에 따르면 여기에서 고려한 다른 방법보다 훨씬 느립니다. Boost Format에는 또한 과도한 빌드 시간과 심각한 코드 팽창 문제가 있습니다(벤치마크 참조).
이것은 빠르고 안전하며 위치 인수가 있는 흥미로운 라이브러리입니다. 그러나 저자는 다음과 같이 언급하면서 상당한 제한 사항을 가지고 있습니다.
현재 디자인에 수용될 가능성이 없는 세 가지 기능은 다음과 같습니다.
선행 0(또는 기타 공백이 아닌 패딩)
8진수/16진수 인코딩
런타임 너비/정렬 사양
또한 STLSoft에 대한 의존도가 상당히 크고 일부 프로젝트에서 사용하기에는 너무 제한적일 수 있습니다.
이것은 형식화 라이브러리는 아니지만 완전성을 위해 여기에 포함하기로 결정했습니다. iostreams로서 이는 축어적 텍스트와 인수를 혼합하는 문제로 어려움을 겪습니다. 라이브러리는 꽤 빠르지만 정수 형식에서는 Karma의 자체 벤치마크에서 형식 문자열 컴파일을 사용하는 fmt::format_to
보다 느립니다. 초당 수억 개의 정수를 문자열로 변환을 참조하세요.
{fmt}는 MIT 라이센스에 따라 배포됩니다.
문서의 형식 문자열 구문 섹션은 Python 문자열 모듈 문서의 항목을 기반으로 합니다. 이러한 이유로 문서는 doc/python-license.txt에서 제공되는 Python Software Foundation 라이선스에 따라 배포됩니다. {fmt}의 문서를 배포하는 경우에만 적용됩니다.
{fmt} 라이브러리는 다른 많은 사람들의 기여를 받아 Victor Zverovich(vitaut)가 관리합니다. 일부 이름은 기여자 및 릴리스를 참조하세요. 귀하의 기여가 목록에 없거나 잘못 언급된 경우 알려주시면 바로잡도록 하겠습니다.
보안 문제를 보고하려면 보안 권고에 공개하세요.
이 프로젝트는 합리적인 노력을 바탕으로 자원 봉사 팀에 의해 유지 관리됩니다. 따라서 공개되기 전에 수정 작업을 수행할 수 있도록 최소 90 일의 시간을 주십시오.