{fmt} adalah pustaka pemformatan sumber terbuka yang menyediakan alternatif cepat dan aman untuk C stdio dan C++ iostreams.
Jika Anda menyukai proyek ini, mohon pertimbangkan untuk menyumbang ke salah satu dana yang membantu korban perang di Ukraina: https://www.stopputin.net/.
Dokumentasi
Lembar Curang
T&J: ajukan pertanyaan tentang StackOverflow dengan tag fmt.
Coba {fmt} di Compiler Explorer.
API format sederhana dengan argumen posisi untuk pelokalan
Implementasi C++20 std::format dan C++23 std::print
Sintaks string format mirip dengan format Python
Pemformat floating-point IEEE 754 yang cepat dengan jaminan pembulatan, kependekan, dan bolak-balik yang benar menggunakan algoritma Dragonbox
Dukungan Unicode portabel
Implementasi printf yang aman termasuk ekstensi POSIX untuk argumen posisi
Ekstensibilitas: dukungan untuk tipe yang ditentukan pengguna
Kinerja tinggi: lebih cepat dari implementasi perpustakaan standar umum (s)printf
, iostreams, to_string
dan to_chars
, lihat Tes kecepatan dan Mengonversi seratus juta bilangan bulat menjadi string per detik
Ukuran kode kecil baik dari segi kode sumber dengan konfigurasi minimum hanya terdiri dari tiga file, core.h
, format.h
dan format-inl.h
, serta kode yang dikompilasi; lihat Waktu kompilasi dan kode mengasapi
Keandalan: perpustakaan memiliki serangkaian pengujian yang ekstensif dan terus-menerus tidak jelas
Keamanan: perpustakaan sepenuhnya aman untuk mengetik, kesalahan dalam format string dapat dilaporkan pada waktu kompilasi, manajemen memori otomatis mencegah kesalahan buffer overflow
Kemudahan penggunaan: basis kode mandiri yang kecil, tidak ada ketergantungan eksternal, lisensi MIT yang permisif
Portabilitas dengan keluaran yang konsisten di seluruh platform dan dukungan untuk kompiler lama
Bersihkan basis kode bebas peringatan bahkan pada tingkat peringatan tinggi seperti -Wall -Wextra -pedantic
Independensi lokal secara default
Konfigurasi opsional header-saja diaktifkan dengan makro FMT_HEADER_ONLY
Lihat dokumentasi untuk lebih jelasnya.
Cetak ke stdout (jalankan)
#include <fmt/core.h>int main() { fmt::print("Halo, dunia!n"); }
Format string (jalankan)
std::string s = fmt::format("Jawabannya adalah {}.", 42);// s == "Jawabannya adalah 42."
Format string menggunakan argumen posisi (jalankan)
std::string s = fmt::format("Saya lebih suka menjadi {1} daripada {0}.", "benar", "bahagia");// s == "Saya lebih suka bahagia daripada benar ."
Cetak tanggal dan waktu (jalankan)
#termasuk <fmt/chrono.h>int main() { otomatis sekarang = std::chrono::system_clock::now(); fmt::print("Tanggal dan waktu: {}n", sekarang); fmt::print("Waktu: {:%H:%M}n", sekarang); }
Keluaran:
Date and time: 2023-12-26 19:10:31.557195597 Time: 19:10
Cetak wadah (jalankan)
#include <vector>#include <fmt/ranges.h>int main() { std::vektor<int> v = {1, 2, 3}; fmt::print("{}n",v); }
Keluaran:
[1, 2, 3]
Periksa string format pada waktu kompilasi
std::string s = fmt::format("{:d}", "Saya bukan angka");
Ini memberikan kesalahan waktu kompilasi di C++20 karena d
adalah penentu format yang tidak valid untuk sebuah string.
Tulis file dari satu thread
#termasuk <fmt/os.h>int main() { keluar otomatis = fmt::output_file("guide.txt"); out.print("Jangan {}", "Panik"); }
Ini bisa 5 hingga 9 kali lebih cepat daripada fprintf.
Cetak dengan warna dan gaya teks
#include <fmt/color.h>int main() { fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "Halo, {}!n", "dunia" ); fmt::print(fg(fmt::warna::floral_white) | bg(fmt::warna::slate_gray) | fmt::penekanan::garis bawah, "Olá, {}!n", "Mundo"); fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic, "你好{}!n", "世界"); }
Output pada terminal modern dengan dukungan Unicode:
Perpustakaan | Metode | Waktu Jalankan, s |
---|---|---|
libc | printf | 0,91 |
libc++ | std::ostream | 2.49 |
{fmt} 9.1 | fmt::cetak | 0,74 |
Tingkatkan Format 1.80 | peningkatan::format | 6.26 |
Format Kebodohan | kebodohan::format | 1.87 |
{fmt} adalah metode benchmark tercepat, ~20% lebih cepat dibandingkan printf
.
Hasil di atas dihasilkan dengan membangun tinyformat_test.cpp
di macOS 12.6.1 dengan clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT
, dan mengambil yang terbaik dari tiga proses. Dalam pengujian, string format "%0.10f:%04d:%+g:%s:%p:%c:%%n"
atau yang setara diisi 2.000.000 kali dengan output dikirim ke /dev/null
; untuk lebih jelasnya lihat sumbernya.
{fmt} hingga 20-30x lebih cepat daripada std::ostringstream
dan sprintf
pada IEEE754 float
dan format double
(dtoa-benchmark) dan lebih cepat daripada konversi ganda dan ryu:
Skrip bloat-test.py dari tes format-benchmark waktu kompilasi dan kode bloat untuk proyek-proyek nontrivial. Ini menghasilkan 100 unit terjemahan dan menggunakan printf()
atau alternatifnya masing-masing lima kali untuk mensimulasikan proyek berukuran sedang. Ukuran eksekusi dan waktu kompilasi yang dihasilkan (Apple clang versi 15.0.0 (clang-1500.1.0.2.5), macOS Sonoma, best of three) ditampilkan dalam tabel berikut.
Pembuatan yang dioptimalkan (-O3)
Metode | Waktu Kompilasi, s | Ukuran yang dapat dieksekusi, KiB | Ukuran yang dilucuti, KiB |
---|---|---|---|
printf | 1.6 | 54 | 50 |
IOSstream | 25.9 | 98 | 84 |
fmt 83652df | 4.8 | 54 | 50 |
format kecil | 29.1 | 161 | 136 |
Tingkatkan Format | 55.0 | 530 | 317 |
{fmt} cepat untuk dikompilasi dan sebanding dengan printf
dalam hal ukuran biner per panggilan (dalam kesalahan pembulatan pada sistem ini).
Bangunan yang tidak dioptimalkan
Metode | Waktu Kompilasi, s | Ukuran yang dapat dieksekusi, KiB | Ukuran yang dilucuti, KiB |
---|---|---|---|
printf | 1.4 | 54 | 50 |
IOSstream | 23.4 | 92 | 68 |
{fmt} 83652df | 4.4 | 89 | 85 |
format kecil | 24.5 | 204 | 161 |
Tingkatkan Format | 36.4 | 831 | 462 |
libc
, lib(std)c++
, dan libfmt
semuanya ditautkan sebagai pustaka bersama untuk membandingkan overhead fungsi pemformatan saja. Boost Format adalah pustaka khusus header sehingga tidak menyediakan opsi tautan apa pun.
Silakan merujuk ke Membangun perpustakaan untuk instruksi tentang cara membangun perpustakaan dan menjalankan pengujian unit.
Benchmark berada di repositori terpisah, format-benchmark, jadi untuk menjalankan benchmark, Anda harus mengkloning repositori ini terlebih dahulu dan membuat Makefile dengan CMake:
$ git clone --recursive https://github.com/fmtlib/format-benchmark.git $ cd format-benchmark $ cmake .
Kemudian Anda dapat menjalankan tes kecepatan:
$ make speed-test
atau tes mengasapi:
$ make bloat-test
clang-tidy v18 menyediakan pemeriksaan modernisasi-penggunaan-std-print yang mampu mengubah kemunculan printf
dan fprintf
menjadi fmt::print
jika dikonfigurasi untuk melakukannya. (Secara default diubah menjadi std::print
.)
0 AD: game strategi real-time lintas platform, sumber terbuka, dan gratis
AMPL/MP: perpustakaan sumber terbuka untuk pemrograman matematika
FoundationDB Apple: penyimpanan nilai kunci transaksional yang bersumber terbuka, terdistribusi
Aseprite: editor sprite animasi & alat seni piksel
AvioBook: rangkaian operasi pesawat yang komprehensif
Blizzard Battle.net: platform game online
Celestia: visualisasi ruang 3D secara real-time
Ceph: sistem penyimpanan terdistribusi yang skalabel
ccache: cache kompiler
ClickHouse: sistem manajemen basis data analitis
ContextVision: perangkat lunak pencitraan medis
Kontur: emulator terminal modern
CUAUV: kendaraan bawah air otonom Universitas Cornell
Drake: kotak peralatan perencanaan, pengendalian, dan analisis untuk sistem dinamis nonlinier (MIT)
Utusan: Proksi C++ L7 dan bus komunikasi (Lyft)
FiveM: kerangka modifikasi untuk GTA V
fmtlog: pustaka logging gaya fmtlib yang berkinerja baik dengan latensi dalam nanodetik
Kebodohan: perpustakaan sumber terbuka Facebook
GemRB: implementasi sumber terbuka portabel dari Mesin Infinity Bioware
Grand Mountain Adventure: permainan ski & seluncur salju dunia terbuka yang indah
HarpyWar/pvpgn: Jaringan Permainan Pemain vs Pemain dengan penyesuaian
KBEngine: mesin server MMOG sumber terbuka
Keypirinha: peluncur semantik untuk Windows
Kodi (sebelumnya xbmc): perangkat lunak home theater
Knuth: node penuh Bitcoin berkinerja tinggi
libunicode: perpustakaan Unicode C++17 modern
MariaDB: sistem manajemen basis data relasional
Microsoft Verona: meneliti bahasa pemrograman untuk kepemilikan bersamaan
MongoDB: database dokumen terdistribusi
MongoDB Smasher: alat kecil untuk menghasilkan kumpulan data acak
OpenSpace: kerangka astrovisualisasi sumber terbuka
PenUltima Online (POL): server MMO, kompatibel dengan sebagian besar klien Ultima Online
PyTorch: perpustakaan pembelajaran mesin sumber terbuka
quasardb: database asosiatif terdistribusi, berkinerja tinggi
Quill: pustaka logging latensi rendah asinkron
QKW: menggeneralisasi aliasing untuk menyederhanakan navigasi, dan menjalankan urutan perintah terminal multi-baris yang kompleks
redis-cerberus: proksi klaster Redis
redpanda: pengganti Kafka® 10x lebih cepat untuk sistem penting yang ditulis dalam C++
rpclib: server C++ msgpack-RPC modern dan perpustakaan klien
Salesforce Analytics Cloud: perangkat lunak intelijen bisnis
Scylla: penyimpanan data NoSQL yang kompatibel dengan Cassandra yang dapat menangani 1 juta transaksi per detik pada satu server
Seastar: kerangka kerja C++ sumber terbuka yang canggih untuk aplikasi server berkinerja tinggi pada perangkat keras modern
spdlog: pustaka logging C++ super cepat
Stellar: platform keuangan
Sentuh Bedah: simulator bedah
TrinityCore: kerangka MMORPG sumber terbuka
? kerangka pengguna: kerangka kerja asinkron sumber terbuka dengan serangkaian abstraksi dan driver basis data yang kaya
Terminal Windows: terminal Windows baru
Lagi...
Jika Anda mengetahui proyek lain yang menggunakan perpustakaan ini, beri tahu saya melalui email atau dengan mengirimkan masalah.
Jadi mengapa perpustakaan pemformatan lain lagi?
Ada banyak metode untuk melakukan tugas ini, dari metode standar seperti rangkaian fungsi printf dan iostreams hingga pustaka Boost Format dan FastFormat. Alasan membuat perpustakaan baru adalah setiap solusi yang saya temukan memiliki masalah serius atau tidak menyediakan semua fitur yang saya perlukan.
Hal yang baik tentang printf
adalah ia cukup cepat dan tersedia sebagai bagian dari perpustakaan standar C. Kelemahan utamanya adalah tidak mendukung tipe yang ditentukan pengguna. printf
juga memiliki masalah keamanan meskipun agak dikurangi dengan __attribute__ ((format (printf, ...)) di GCC. Ada ekstensi POSIX yang menambahkan argumen posisi yang diperlukan untuk i18n ke printf
tetapi ini bukan bagian dari C99 dan mungkin tidak tersedia di beberapa platform.
Masalah utama dengan iostreams paling baik diilustrasikan dengan sebuah contoh:
std::cout << std::setprecision(2) << std::tetap << 1.23456 << "n";
yang banyak mengetik dibandingkan dengan printf:
printf("%.2fn",1.23456);
Matthew Wilson, penulis FastFormat, menyebut ini "neraka chevron". iostreams tidak mendukung argumen posisi berdasarkan desain.
Bagian baiknya adalah iostreams mendukung tipe yang ditentukan pengguna dan aman meskipun penanganan kesalahannya sulit.
Ini adalah perpustakaan yang sangat kuat yang mendukung string format seperti printf
dan argumen posisi. Kelemahan utamanya adalah kinerja. Menurut berbagai tolok ukur, ini jauh lebih lambat dibandingkan metode lain yang dibahas di sini. Boost Format juga memiliki waktu pembuatan yang berlebihan dan masalah pengasapan kode yang parah (lihat Tolok Ukur).
Ini adalah perpustakaan menarik yang cepat, aman, dan memiliki argumen posisi. Namun, ia memiliki keterbatasan yang signifikan, mengutip penulisnya:
Tiga fitur yang tidak ada harapan untuk diakomodasi dalam desain saat ini adalah:
Angka nol di depan (atau padding non-spasi lainnya)
Pengkodean oktal/heksadesimal
Spesifikasi lebar/penyelarasan runtime
Ini juga cukup besar dan memiliki ketergantungan yang besar pada STLSoft, yang mungkin terlalu membatasi untuk digunakan dalam beberapa proyek.
Ini bukan perpustakaan pemformatan tetapi saya memutuskan untuk memasukkannya di sini untuk kelengkapan. Sebagai iostreams, ia mengalami masalah pencampuran teks kata demi kata dengan argumen. Pustakanya cukup cepat, tetapi lebih lambat dalam pemformatan bilangan bulat dibandingkan fmt::format_to
dengan kompilasi format string pada patokan Karma sendiri, lihat Mengonversi seratus juta bilangan bulat menjadi string per detik.
{fmt} didistribusikan di bawah lisensi MIT.
Bagian Sintaks Format String dalam dokumentasi didasarkan pada bagian dari dokumentasi modul string Python. Oleh karena itu, dokumentasi didistribusikan di bawah lisensi Python Software Foundation yang tersedia di doc/python-license.txt. Ini hanya berlaku jika Anda mendistribusikan dokumentasi {fmt}.
Perpustakaan {fmt} dikelola oleh Victor Zverovich (vitaut) dengan kontribusi dari banyak orang lainnya. Lihat Kontributor dan Rilis untuk beberapa nama. Beri tahu kami jika kontribusi Anda tidak dicantumkan atau disebutkan secara salah dan kami akan memperbaikinya.
Untuk melaporkan masalah keamanan, harap ungkapkan di penasihat keamanan.
Proyek ini dikelola oleh tim sukarelawan dengan upaya yang wajar. Oleh karena itu, mohon beri kami waktu setidaknya 90 hari untuk memperbaiki masalah ini sebelum dipublikasikan kepada publik.