🚀 C# ile Programlamaya Giriş: Kodlamaya İlk Adımını At, Kendi Projelerini Geliştirmeye Başla!
00ANASAYFA 01YAZILAR 02EĞİTİM 03ELEKTRİK_ENERJİ 04OTOMOTİV_MÜHENDİSLİĞİ 05ARAÇLAR 06LAB 07SÖZLÜK 08ETİKETLER ♡OKUMA LİSTEM ⌕ARA
TRENG

STL’e giriş: map, sort, algoritmalar ve lambda

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::sort ortalamada 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

  1. Üç ölçüm vektörünün her birinin ortalamasını accumulate ile hesapla.
  2. Ölçümlerden 20'den küçük olanları count_if ve lambda ile say; eşiği değişkenle ver.
  3. std::map<std::string, double> ile "sensör adı -> son ölçüm" tablosu tut ve hepsini yazdır.
  4. std::find ile 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.

1. std::accumulate(v.begin(), v.end(), 0.0) çağrısında başlangıç değerinin 0 yerine 0.0 yazılmasının sebebi nedir?
2. Lambda ifadesinde köşeli parantez [] ne işe yarar?
3. std::map elemanlarını hangi sırayla tutar?

Bitirdiğinde işaretle: ilerlemen kaydolur, +20 XP kazanırsın.

İpucu: ← → tuşlarıyla dersler arasında gezinebilirsin.