Standart şablon kütüphanesinin gücü: std::sort, accumulate, max_element, count_if, std::map ve lambda ifadeleri.
C++ standart kütüphanesinin bir bölümüne STL (Standard Template Library) denir. Üç ana parçası vardır: konteynerler (vector, map gibi veri yapıları), algoritmalar (sort, find, accumulate…) ve bunları bağlayan yineleyiciler (iterator). Kendi sıralama döngünü yazmak yerine yıllardır test edilmiş, optimize edilmiş hazır araçları kullanırsın.
Yineleyici fikri
Bir konteynerin begin() metodu ilk elemanı, end() metodu ise son elemandan bir sonrayı gösteren yineleyici verir. Algoritmalar "şu aralıktaki elemanlar" üzerinde çalışır: std::sort(v.begin(), v.end()). Yineleyici, işaretçiye benzer: *it ile elemana ulaşılır.
Örnek: sensör verisi ve stok
#include <algorithm>
#include <iostream>
#include <map>
#include <numeric>
#include <string>
#include <vector>
int main() {
std::vector<double> olcum = {23.5, 19.0, 25.2, 21.7, 30.1};
std::sort(olcum.begin(), olcum.end()); // kucukten buyuge
for (double x : olcum) std::cout << x << ' ';
std::cout << '\n';
double toplam = std::accumulate(olcum.begin(), olcum.end(), 0.0);
std::cout << "Ortalama: " << toplam / olcum.size() << '\n';
auto enBuyuk = std::max_element(olcum.begin(), olcum.end());
std::cout << "En buyuk: " << *enBuyuk << '\n';
// Lambda: eslikten yuksek olanlari say
int sicak = std::count_if(olcum.begin(), olcum.end(),
[](double x) { return x > 24.0; });
std::cout << "24 C ustu: " << sicak << " adet\n";
// Lambda ile ozel siralama: buyukten kucuge
std::sort(olcum.begin(), olcum.end(),
[](double a, double b) { return a > b; });
std::cout << "En sicak: " << olcum.front() << '\n';
// std::map: anahtar -> deger
std::map<std::string, int> stok;
stok["direnc"] = 120;
stok["led"] = 300;
stok["kondansator"] = 45;
stok["direnc"] += 30;
for (const auto& [ad, adet] : stok) {
std::cout << ad << ": " << adet << '\n';
}
return 0;
}
19 21.7 23.5 25.2 30.1
Ortalama: 23.9
En buyuk: 30.1
24 C ustu: 2 adet
En sicak: 30.1
direnc: 150
kondansator: 45
led: 300
Kodu parça parça okuyalım
sort ve accumulate
std::sort varsayılan olarak küçükten büyüğe sıralar. std::accumulate başlangıç değerinden (burada 0.0) başlayarak elemanları toplar; başlık <numeric>'tur. Başlangıç değerini 0 değil 0.0 yazdık, çünkü int olarak yazılsa tüm toplama int cinsinden yapılırdı ve ondalıklar kaybolurdu.
max_element
Elemanın kendisini değil yineleyiciyi döndürür; değeri almak için *enBuyuk yazılır. min_element de vardır.
Lambda ifadeleri
Lambda, yerinde yazılan isimsiz bir fonksiyondur: [yakalama](parametreler) { gövde }. [](double x) { return x > 24.0; } ifadesi "x, 24'ten büyük mü?" sorusunu soran küçük bir fonksiyondur. Köşeli parantez, dışarıdaki değişkenleri lambda içine nasıl alacağını belirtir: [eşik] değeri kopyalar, [&eşik] referansla alır, [=] ve [&] hepsini alır. Böylece eşik değerini dışarıdan verebilirsin:
double esik = 24.0;
int adet = std::count_if(olcum.begin(), olcum.end(),
[esik](double x) { return x > esik; });
std::map
std::map anahtar-değer çiftlerini anahtara göre sıralı tutar; bu yüzden döngüde direnc, kondansator, led alfabetik sırayla çıktı. stok["led"] ile erişirsin. Dikkat: anahtar yoksa [] operatörü onu sıfır değeriyle oluşturur. Sadece kontrol etmek için stok.count("led") ya da stok.find("led") kullan. for (const auto& [ad, adet] : stok) biçimi C++17'nin yapısal bağlama (structured binding) özelliğidir ve çifti iki isme ayırır. Sıralama gerekmiyorsa std::unordered_map (başlık: <unordered_map>) ortalamada daha hızlıdır.
Neden STL?
- Doğruluk: Elle yazdığın sıralama döngüsünde hata olması çok olasıdır; STL denenmiştir.
- Hız:
std::sortortalamada n log n karmaşıklıktadır ve iyi optimize edilmiştir. - Okunabilirlik:
std::count_if(...)satırı ne yaptığını söyler; elle yazılmış döngüyü çözmek gerekir.
Hangi konteynerin ne zaman seçileceği konusunda başlangıç kuralı basit: varsayılan seçim std::vector. Anahtarla arama gerekiyorsa std::map ya da std::unordered_map. Benzersiz elemanları sıralı tutmak için std::set. Başka bir şey seçmek için ölçümle kanıtlanmış bir nedenin olmalı.
Algoritmalar aralıklara güvenir. end() yineleyicisini dereference etmek (örneğin boş vektörde max_element sonucunu kontrol etmeden * ile kullanmak) tanımsız davranıştır. Boş aralıkta max_element end() döner; önce vektörün boş olmadığını kontrol et.
Kendin dene
- Üç ölçüm vektörünün her birinin ortalamasını
accumulateile hesapla. - Ölçümlerden 20'den küçük olanları
count_ifve lambda ile say; eşiği değişkenle ver. std::map<std::string, double>ile "sensör adı -> son ölçüm" tablosu tut ve hepsini yazdır.std::findile vektörde belirli bir değer var mı kontrol et.
// Mini sınav
Bir seçeneğe tıkla; doğru mu yanlış mı, anında ve nedeniyle birlikte göreceksin.
Bitirdiğinde işaretle: ilerlemen kaydolur, +20 XP kazanırsın.
İpucu: ← → tuşlarıyla dersler arasında gezinebilirsin.