std::format (C++20) ile Modern String Formatlama
Bir restoranda sipariş verdiğini düşün. Garson sana "Ne istersiniz?" diye soruyor, sen de "Bir adet 150 gramlık orta pişmiş bonfile, yanında patates püresi, içecek olarak sade su" diyorsun. Garson bunu kısa bir notla yazdı: "1x bonfile(150g, med), patates, su". İşte string formatlama tam bu — verileri alıp belirli bir şablona göre okunabilir metne dönüştürmek. C++ bu işi yıllarca printf ve iostream ile yaptı — ikisi de farklı şekillerde sorunluydu. C++20 ile gelen std::format, Python'un f-string'lerine benzer modern, güvenli ve esnek bir çözüm sunuyor.
Eski Yöntemlerin Sorunları
printf: Güçlü Ama Tehlikeli
C'den miras kalan printf, format string'i ile veri tiplerini elle eşleştirmeni gerektirir. Eşleştirme yanlışsa derleyici (çoğu zaman) uyarmaz ve tanımsız davranış oluşur.
#include <cstdio>
#include <string>
void printfSorunlari() {
int yas = 25;
const char* isim = "Ali";
// Doğru kullanım
printf("Isim: %s, Yas: %d\n", isim, yas);
// TEHLIKE 1: Yanlış format specifier — UB
printf("Yas: %s\n", yas); // %s ama int verdik — çökebilir!
// TEHLIKE 2: Argüman sayısı uyumsuz
printf("Isim: %s, Yas: %d, Sehir: %s\n", isim, yas);
// 3 placeholder var, 2 argüman — çöp değer veya çökme
// TEHLIKE 3: std::string doğrudan çalışmaz
std::string sehir = "Istanbul";
printf("Sehir: %s\n", sehir); // YANLIS: UB
printf("Sehir: %s\n", sehir.c_str()); // Dogru ama zahmetli
}printf'in en büyük sorunu tip güvenliği olmamasıdır. Format string %d deyip double verirsen, derleyici bunu hata olarak görmez. Sonuç: çöp çıktı veya çökme.
iostream: Güvenli Ama Zahmetli
iostream tip güvenlidir ama karmaşık formatlama yapmak çok uzun ve okunaksız kod üretir.
#include <iostream>
#include <iomanip>
#include <string>
void iostreamSorunlari() {
double fiyat = 1234.5678;
int adet = 42;
std::string urun = "Laptop";
// Basit çıktı — idare eder
std::cout << urun << ": " << adet << " adet" << std::endl;
// Formatlı çıktı — kabus başlıyor
std::cout << std::left << std::setw(15) << urun
<< std::right << std::setw(5) << adet << " adet, "
<< std::fixed << std::setprecision(2)
<< fiyat << " TL" << std::endl;
// Hex formatlama
std::cout << "Hex: " << std::hex << std::showbase
<< std::uppercase << 255 << std::endl;
// Dikkat: state kalıcıdır!
std::cout << 42 << std::endl; // Hala hex modunda: "0X2A"
// Resetlemek gerekiyor
std::cout << std::dec << std::noshowbase
<< std::nouppercase;
}İki büyük sorunu var. Birincisi: setw, setprecision, setfill gibi manipülatörlerle formatlama kodu, asıl veriyi gölgede bırakır. Neyin yazdırıldığını anlamak için kodu üç kez okuman gerekir. İkincisi: std::hex, std::fixed gibi bazı manipülatörler stream state'ini kalıcı olarak değiştirir. Resetlemeyi unutursan sonraki çıktılar bozulur.
std::to_string + Concatenation
#include <string>
#include <iostream>
void toStringProblemleri() {
std::string isim = "Ali";
int yas = 25;
double maas = 15750.5;
// Her şeyi string'e çevirip birleştir
std::string mesaj = "Isim: " + isim + ", Yas: "
+ std::to_string(yas) + ", Maas: "
+ std::to_string(maas) + " TL";
std::cout << mesaj << std::endl;
// Çıktı: Isim: Ali, Yas: 25, Maas: 15750.500000 TL
// Sorunlar:
// 1. Hassasiyet kontrolü yok (15750.500000)
// 2. Hex, oct formatlama yok
// 3. Genişlik/hizalama yok
// 4. Çok fazla + operatörü — okunabilirlik düşük
// 5. Her + geçici string oluşturabilir (performans)
}std::to_string basit dönüşümler için işe yarar ama format kontrolü yoktur. Ondalık hassasiyet, hizalama, dolgu gibi şeyler imkansızdır.
std::format Temelleri
İlk Adımlar
std::format, Python'un str.format() ve Rust'un format! makrosundan ilham alır. <format> başlık dosyasından gelir.
#include <format>
#include <iostream>
#include <string>
int main() {
std::string isim = "Ali";
int yas = 25;
double maas = 15750.5;
// Temel kullanım — {} yer tutucu (placeholder)
std::string mesaj = std::format("Isim: {}, Yas: {}, Maas: {:.2f} TL",
isim, yas, maas);
std::cout << mesaj << std::endl;
// Çıktı: Isim: Ali, Yas: 25, Maas: 15750.50 TL
// Indeksli argümanlar — sırayı değiştir
std::string ters = std::format("{1} yasinda {0}", isim, yas);
std::cout << ters << std::endl;
// Çıktı: 25 yasinda Ali
// Aynı argümanı birden fazla kullan
std::string tekrar = std::format("{0} {0} {0}", "hey");
std::cout << tekrar << std::endl;
// Çıktı: hey hey hey
return 0;
}Syntax basit: {} otomatik sıralı, {0}, {1} indeksli. İkisini karıştıramazsın — ya hepsi otomatik ya hepsi indeksli.
Derleme
# GCC 13+ ile
g++ -std=c++20 main.cpp -o main
# Clang 17+ ile
clang++ -std=c++20 main.cpp -o main⚠️ Dikkat: std::format desteği derleyici sürümüne bağlıdır. GCC 13+, Clang 17+, MSVC 19.29+ (VS 2019 16.10+) tam destek sunar. Eski derleyicilerde fmt kütüphanesini kullanabilirsin (dersin sonunda anlatılıyor).
Format Specifiers: Tam Kontrol
Genel Syntax
Format specifier {} içinde : sonrasına yazılır:
{[argüman_indeksi]:[dolgu][hizalama][işaret][#][0][genişlik][.hassasiyet][tip]}Karmaşık görünüyor ama parça parça öğrenince basit.
Genişlik ve Hizalama
#include <format>
#include <iostream>
int main() {
// Genişlik: minimum karakter sayısı
std::cout << std::format("[{:10}]", "Ali") << std::endl;
// Çıktı: [Ali ] — sağda boşluk (string varsayılan: sola hizalı)
std::cout << std::format("[{:10}]", 42) << std::endl;
// Çıktı: [ 42] — solda boşluk (sayı varsayılan: sağa hizalı)
// Hizalama: < sola, > sağa, ^ ortaya
std::cout << std::format("[{:<10}]", 42) << std::endl;
// Çıktı: [42 ]
std::cout << std::format("[{:>10}]", "Ali") << std::endl;
// Çıktı: [ Ali]
std::cout << std::format("[{:^10}]", "orta") << std::endl;
// Çıktı: [ orta ]
// Dolgu karakteri: hizalamadan önce
std::cout << std::format("[{:*^10}]", "orta") << std::endl;
// Çıktı: [***orta***]
std::cout << std::format("[{:.<10}]", "Ali") << std::endl;
// Çıktı: [Ali.......]
std::cout << std::format("[{:0>8}]", 42) << std::endl;
// Çıktı: [00000042]
return 0;
}Dolgu karakteri herhangi bir karakter olabilir — *, ., -, 0 veya başka bir şey. Hizalama ile birlikte kullanılır.
Hassasiyet (Precision)
#include <format>
#include <iostream>
int main() {
double pi = 3.14159265358979;
// Ondalık hassasiyet
std::cout << std::format("{:.2f}", pi) << std::endl; // 3.14
std::cout << std::format("{:.4f}", pi) << std::endl; // 3.1416
std::cout << std::format("{:.0f}", pi) << std::endl; // 3
// Bilimsel gösterim
std::cout << std::format("{:.3e}", pi) << std::endl; // 3.142e+00
std::cout << std::format("{:.3E}", pi) << std::endl; // 3.142E+00
// Genel (general) — gereksiz sıfırları atar
std::cout << std::format("{:.4g}", pi) << std::endl; // 3.142
std::cout << std::format("{:.4g}", 1000.0) << std::endl; // 1000
std::cout << std::format("{:.4g}", 100000.0) << std::endl; // 1e+05
// String'lerde hassasiyet — karakter sınırı
std::cout << std::format("{:.5}", "Merhaba Dunya") << std::endl;
// Çıktı: Merha (ilk 5 karakter)
// Genişlik + hassasiyet birlikte
std::cout << std::format("[{:10.2f}]", pi) << std::endl;
// Çıktı: [ 3.14]
return 0;
}İşaret ve Sıfır Dolgu
#include <format>
#include <iostream>
int main() {
int pozitif = 42;
int negatif = -42;
// Varsayılan: sadece negatif işaret
std::cout << std::format("{}", pozitif) << std::endl; // 42
std::cout << std::format("{}", negatif) << std::endl; // -42
// + : her zaman işaret göster
std::cout << std::format("{:+}", pozitif) << std::endl; // +42
std::cout << std::format("{:+}", negatif) << std::endl; // -42
// boşluk: pozitifin önüne boşluk
std::cout << std::format("{: }", pozitif) << std::endl; // 42
std::cout << std::format("{: }", negatif) << std::endl; // -42
// 0 ile sıfır dolgu (genişlikle birlikte)
std::cout << std::format("{:05}", pozitif) << std::endl; // 00042
std::cout << std::format("{:05}", negatif) << std::endl; // -0042
return 0;
}İşaret seçeneği tablo çıktılarında hizalama için çok kullanışlıdır. Pozitif ve negatif sayılar alt alta güzel dizilir.
Sayı Formatlama: Hex, Oct, Binary
Tamsayı Formatları
#include <format>
#include <iostream>
int main() {
int sayi = 255;
// Ondalık (varsayılan)
std::cout << std::format("Decimal: {}", sayi) << std::endl;
// Çıktı: Decimal: 255
// Onaltılık (hexadecimal)
std::cout << std::format("Hex: {:x}", sayi) << std::endl;
// Çıktı: Hex: ff
std::cout << std::format("Hex (ust):{:X}", sayi) << std::endl;
// Çıktı: Hex (ust):FF
// Sekizlik (octal)
std::cout << std::format("Octal: {:o}", sayi) << std::endl;
// Çıktı: Octal: 377
// İkilik (binary)
std::cout << std::format("Binary: {:b}", sayi) << std::endl;
// Çıktı: Binary: 11111111
// # ile prefix göster
std::cout << std::format("Hex: {:#x}", sayi) << std::endl;
// Çıktı: Hex: 0xff
std::cout << std::format("Octal: {:#o}", sayi) << std::endl;
// Çıktı: Octal: 0377
std::cout << std::format("Binary: {:#b}", sayi) << std::endl;
// Çıktı: Binary: 0b11111111
// Hex + sıfır dolgu + genişlik — bellek adresi gibi
std::cout << std::format("Addr: {:#010x}", sayi) << std::endl;
// Çıktı: Addr: 0x000000ff
return 0;
}Karakter ve Bool Formatlama
#include <format>
#include <iostream>
int main() {
char c = 'A';
bool aktif = true;
// Karakter
std::cout << std::format("Karakter: {}", c) << std::endl; // A
std::cout << std::format("ASCII: {:d}", c) << std::endl; // 65
// Bool
std::cout << std::format("Bool: {}", aktif) << std::endl; // true
std::cout << std::format("Sayi: {:d}", aktif) << std::endl; // 1
return 0;
}Tip Güvenliği: Derleme Zamanı Kontrol
printf vs std::format
std::format'ın en büyük avantajı derleme zamanı tip kontrolüdür. Yanlış format string'i derleme hatası verir — runtime sürprizi olmaz.
#include <format>
#include <string>
void tipGuvenligi() {
int yas = 25;
std::string isim = "Ali";
// printf: derlenir ama runtime'da UB
// printf("%s\n", yas); // %s ama int — çökme!
// printf("%d\n", isim); // %d ama string — çöp!
// std::format: DERLEME HATASI
// auto s1 = std::format("{:s}", yas); // int'i string olarak formatlayamazsın
// auto s2 = std::format("{:d}", isim); // string'i sayı olarak formatlayamazsın
// Argüman sayısı uyumsuzluğu da derleme hatası
// auto s3 = std::format("{} {} {}", yas); // 3 placeholder, 1 argüman
// Doğru kullanımlar
auto s4 = std::format("{}", yas); // 25
auto s5 = std::format("{}", isim); // Ali
auto s6 = std::format("{} {}", isim, yas); // Ali 25
}Bu kontrol C++20'de consteval ve std::basic_format_string altyapısı sayesinde mümkün oluyor. Format string'i derleme zamanında parse edilir ve argüman tipleriyle uyumu kontrol edilir.
Runtime Format String
Bazen format string'ini runtime'da belirlemen gerekir (örneğin bir konfigürasyon dosyasından okunan şablon). C++26'da std::runtime_format geliyor, ama şimdilik bu mümkün değil — format string'i derleme zamanı sabiti olmalı.
#include <format>
#include <string>
void runtimeFormat() {
// Bu çalışır: derleme zamanı string literal
auto s1 = std::format("Sayi: {}", 42);
// Bu CALISMAZ: runtime string
// std::string fmt_str = "Sayi: {}";
// auto s2 = std::format(fmt_str, 42); // Derleme hatası
// C++26 ile gelecek:
// auto s2 = std::format(std::runtime_format(fmt_str), 42);
// Şimdilik alternatif: fmt kütüphanesi
// auto s2 = fmt::format(fmt::runtime(fmt_str), 42);
}Custom Type İçin Formatter
std::formatter Specialization
Kendi tiplerini std::format ile kullanabilmek için std::formatter template'ini özelleştirmen gerekir.
#include <format>
#include <iostream>
#include <string>
struct Nokta {
double x;
double y;
};
// std::formatter özelleştirmesi
template <>
struct std::formatter<Nokta> {
// Format string'ini parse et
constexpr auto parse(std::format_parse_context& ctx) {
return ctx.begin(); // Ek format specifier yok
}
// Formatla ve yaz
auto format(const Nokta& n, std::format_context& ctx) const {
return std::format_to(ctx.out(), "({:.2f}, {:.2f})", n.x, n.y);
}
};
int main() {
Nokta p{3.14159, 2.71828};
std::cout << std::format("Nokta: {}", p) << std::endl;
// Çıktı: Nokta: (3.14, 2.72)
std::cout << std::format("A={}, B={}", Nokta{0, 0}, Nokta{1, 1}) << std::endl;
// Çıktı: A=(0.00, 0.00), B=(1.00, 1.00)
return 0;
}Format Specifier Destekleyen Formatter
Daha gelişmiş bir formatter, kullanıcının format specifier yazmasına izin verir:
#include <format>
#include <iostream>
#include <string>
struct Renk {
uint8_t r, g, b;
};
template <>
struct std::formatter<Renk> {
char sunum = 'd'; // 'd' = decimal, 'h' = hex
constexpr auto parse(std::format_parse_context& ctx) {
auto it = ctx.begin();
if (it != ctx.end() && (*it == 'd' || *it == 'h')) {
sunum = *it;
++it;
}
return it;
}
auto format(const Renk& r, std::format_context& ctx) const {
if (sunum == 'h') {
return std::format_to(ctx.out(), "#{:02X}{:02X}{:02X}",
r.r, r.g, r.b);
}
return std::format_to(ctx.out(), "rgb({}, {}, {})",
r.r, r.g, r.b);
}
};
int main() {
Renk kirmizi{255, 0, 0};
Renk mavi{0, 128, 255};
// Varsayılan: decimal
std::cout << std::format("Renk: {}", kirmizi) << std::endl;
// Çıktı: Renk: rgb(255, 0, 0)
// 'h' specifier: hex
std::cout << std::format("Renk: {:h}", kirmizi) << std::endl;
// Çıktı: Renk: #FF0000
std::cout << std::format("Gokyuzu: {:h}", mavi) << std::endl;
// Çıktı: Gokyuzu: #0080FF
return 0;
}parse metodu format string'indeki specifier'ları okur, format metodu o bilgiye göre çıktı üretir. Bu mekanizma sayesinde kendi tiplerini std::format ekosistemine tamamen entegre edebilirsin.
std::print (C++23)
format + output Birleşik
C++23 ile gelen std::print ve std::println, std::format ile std::cout'u birleştirir. Artık std::cout << std::format(...) yazmana gerek yok.
#include <print>
#include <string>
#include <vector>
int main() {
std::string isim = "Ali";
int yas = 25;
// C++23: std::print — satır sonu yok
std::print("Isim: {}, Yas: {}", isim, yas);
// C++23: std::println — otomatik satır sonu
std::println("Isim: {}, Yas: {}", isim, yas);
// stderr'e yazdır
std::print(stderr, "Hata: dosya bulunamadi: {}", "config.txt");
// Tablo çıktısı
std::println("{:<15} {:>5} {:>10}", "Urun", "Adet", "Fiyat");
std::println("{:-<15} {:->5} {:->10}", "", "", "");
std::println("{:<15} {:>5} {:>10.2f}", "Laptop", 3, 25999.99);
std::println("{:<15} {:>5} {:>10.2f}", "Mouse", 50, 149.90);
std::println("{:<15} {:>5} {:>10.2f}", "Klavye", 25, 399.00);
return 0;
}Çıktı:
Urun Adet Fiyat
--------------- ----- ----------
Laptop 3 25999.99
Mouse 50 149.90
Klavye 25 399.00std::println inanılmaz temiz ve okunabilir kod üretir. std::cout ve << operatörünün karmaşasından tamamen kurtulursun.
💡 İpucu: std::print ve std::println GCC 14+, Clang 18+, MSVC 19.37+ ile desteklenir. Derleyicin desteklemiyorsa fmt::print aynı işlevi sunar.
Pratik Örnekler
Tablo Çıktısı
#include <format>
#include <iostream>
#include <string>
#include <vector>
struct Ogrenci {
std::string isim;
int numara;
double ortalama;
};
void tabloYazdir(const std::vector<Ogrenci>& ogrenciler) {
// Başlık
std::cout << std::format("{:<20} {:>8} {:>10}\n",
"Isim", "Numara", "Ortalama");
// Ayırıcı çizgi
std::cout << std::format("{:-<20} {:->8} {:->10}\n", "", "", "");
// Veriler
for (const auto& o : ogrenciler) {
std::cout << std::format("{:<20} {:>8} {:>10.2f}\n",
o.isim, o.numara, o.ortalama);
}
// Toplam
double toplam = 0;
for (const auto& o : ogrenciler) toplam += o.ortalama;
double genel = toplam / static_cast<double>(ogrenciler.size());
std::cout << std::format("{:-<20} {:->8} {:->10}\n", "", "", "");
std::cout << std::format("{:<20} {:>8} {:>10.2f}\n",
"GENEL ORTALAMA", "", genel);
}
int main() {
std::vector<Ogrenci> sinif = {
{"Ali Yilmaz", 1001, 3.45},
{"Ayse Kaya", 1002, 3.78},
{"Mehmet Demir", 1003, 2.90},
{"Zeynep Celik", 1004, 3.92},
};
tabloYazdir(sinif);
return 0;
}Çıktı:
Isim Numara Ortalama
-------------------- -------- ----------
Ali Yilmaz 1001 3.45
Ayse Kaya 1002 3.78
Mehmet Demir 1003 2.90
Zeynep Celik 1004 3.92
-------------------- -------- ----------
GENEL ORTALAMA 3.51Hex Dump
#include <format>
#include <iostream>
#include <string>
#include <vector>
#include <cstdint>
#include <cctype>
void hexDump(const std::vector<uint8_t>& data) {
for (size_t i = 0; i < data.size(); i += 16) {
// Adres
std::cout << std::format("{:08x}: ", i);
// Hex değerler
for (size_t j = 0; j < 16; ++j) {
if (i + j < data.size()) {
std::cout << std::format("{:02x} ", data[i + j]);
} else {
std::cout << " ";
}
if (j == 7) std::cout << " "; // Orta boşluk
}
// ASCII gösterim
std::cout << " |";
for (size_t j = 0; j < 16 && i + j < data.size(); ++j) {
char c = static_cast<char>(data[i + j]);
std::cout << (std::isprint(c) ? c : '.');
}
std::cout << "|\n";
}
}
int main() {
std::string mesaj = "Hello, std::format! Bu bir hex dump ornegi.";
std::vector<uint8_t> data(mesaj.begin(), mesaj.end());
hexDump(data);
return 0;
}Çıktı:
00000000: 48 65 6c 6c 6f 2c 20 73 74 64 3a 3a 66 6f 72 6d |Hello, std::form|
00000010: 61 74 21 20 42 75 20 62 69 72 20 68 65 78 20 64 |at! Bu bir hex d|
00000020: 75 6d 70 20 6f 72 6e 65 67 69 2e |ump ornegi.|Bu tür bir çıktıyı printf ile yazmak mümkün, iostream ile çok uzun — std::format ikisinin arasında temiz bir denge kuruyor.
std::format vs printf vs iostream
| Özellik | printf | iostream | std::format |
|---|---|---|---|
| Tip güvenliği | ❌ Yok | ✅ Var | ✅ Var (derleme zamanı) |
| Format string | "%d %s" | Manipülatörler | "{} {}" |
| Okunabilirlik | Orta | Düşük | ✅ Yüksek |
| Genişletilebilirlik | ❌ Zor | operator<< | std::formatter |
| State sorunu | Yok | ⚠️ Kalıcı state | Yok |
| Performans | ✅ Hızlı | Yavaş | ✅ Hızlı |
| Locale desteği | Kısıtlı | Var | {:L} ile |
| C++ standardı | C | C++98 | C++20 |
| Derleme zamanı kontrol | Kısıtlı | Yok | ✅ Tam |
| std::string döndürme | ❌ | std::ostringstream | ✅ Doğrudan |
Tavsiye: Yeni C++20 projelerinde std::format (veya C++23 std::println) kullan. Legacy kodda printf kabul edilebilir. iostream'i formatlama için kullanmaktan kaçın — sadece basit çıktılar için yeterli.
fmt Kütüphanesi
std::format'ın İlham Kaynağı
std::format, Victor Zverovich'in {fmt} kütüphanesinden doğmuştur. C++20 öncesi projelerde veya derleyicin std::format desteklemiyorsa fmt kullanabilirsin.
Kurulum:
# vcpkg ile
vcpkg install fmt
# Conan ile
conan install fmt/10.2.1
# CMake FetchContent ileCMake entegrasyonu:
include(FetchContent)
FetchContent_Declare(
fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 10.2.1
)
FetchContent_MakeAvailable(fmt)
add_executable(main main.cpp)
target_link_libraries(main fmt::fmt)Kullanım:
#include <fmt/core.h>
#include <fmt/color.h>
#include <fmt/ranges.h>
#include <vector>
int main() {
// Temel — std::format ile aynı syntax
fmt::print("Merhaba, {}!\n", "Dunya");
// Renkli çıktı (std::format'ta yok!)
fmt::print(fg(fmt::color::green), "Basarili!\n");
fmt::print(fg(fmt::color::red) | fmt::emphasis::bold, "HATA!\n");
// Range formatlama (std::format'ta yok!)
std::vector<int> v = {1, 2, 3, 4, 5};
fmt::print("Vektor: {}\n", v);
// Çıktı: Vektor: [1, 2, 3, 4, 5]
// Runtime format string (C++26'da gelecek)
std::string fmt_str = "Sayi: {}";
fmt::print(fmt::runtime(fmt_str), 42);
return 0;
}fmt, std::format'ın sahip olmadığı ekstra özellikler sunar: renkli çıktı, range formatlama, runtime format string'ler. Birçok büyük proje (Spdlog, Folly, Catch2) fmt'yi kullanır. std::format'a geçiş yapmak istersen sadece #include ve namespace'i değiştirmen yeterli — API aynı.
std::format_to ve Bellek Yönetimi
Buffer'a Yazma
std::format her çağrıda yeni bir std::string oluşturur. Performans kritik durumlarda std::format_to ile mevcut bir buffer'a yazabilirsin.
#include <format>
#include <iostream>
#include <string>
#include <vector>
int main() {
// format_to: mevcut container'a yaz
std::string buffer;
buffer.reserve(256); // Önceden yer ayır
std::format_to(std::back_inserter(buffer),
"Isim: {}, ", "Ali");
std::format_to(std::back_inserter(buffer),
"Yas: {}, ", 25);
std::format_to(std::back_inserter(buffer),
"Puan: {:.1f}", 95.5);
std::cout << buffer << std::endl;
// Çıktı: Isim: Ali, Yas: 25, Puan: 95.5
// format_to_n: maksimum karakter sayısıyla sınırla
char kucuk_buf[20];
auto result = std::format_to_n(kucuk_buf, sizeof(kucuk_buf) - 1,
"Merhaba, {}!", "Dunya");
*result.out = '\0'; // Null terminate
std::cout << kucuk_buf << std::endl;
// Çıktı: Merhaba, Dunya!
// formatted_size: kaç karakter gerektiğini hesapla (yazmadan)
auto boyut = std::formatted_size("Sayi: {:010.3f}", 3.14);
std::cout << "Gereken boyut: " << boyut << std::endl;
return 0;
}std::format_to döngü içinde çok sayıda formatlama yaparken gereksiz bellek tahsisini önler. Log sistemleri ve seri port çıktıları gibi yerlerde fark yaratır.
Özet
printf tip güvenliği sunmaz ve format string hatalarını runtime'da sessizce geçer — yeni kodda tercih etme
std::format derleme zamanı tip kontrolü, temiz syntax ve yüksek performansla C++20'nin string formatlama standardıdır
Format specifier'lar (
{:>10.2f}) ile genişlik, hizalama, dolgu, hassasiyet ve sayı tabanı tam kontrol altındaCustom type'lar için
std::formatterspecialization yazarak kendi tiplerinistd::formatekosistemine entegre edebilirsinstd::print/println (C++23) format + output'u birleştirerek
std::cout <<ihtiyacını ortadan kaldırırDerleyicin C++20 desteklemiyorsa fmt kütüphanesi aynı API'yi sunar ve ekstra özellikler (renk, range) içerir
AI Asistan
Sorularını yanıtlamaya hazır