#01 Operacje na plikach

📂 Podstawowe otwarcie pliku

Weryfikacja if(!plik) pozwala uniknąć błędów, gdy program nie widzi zasobów.

#include <iostream>
#include <fstream>
using namespace std;

int main() {
    ifstream plik("dane.txt");
    if(!plik) {
        cout << "Blad otwarcia pliku!" << endl;
        return 1;
    }

    // Tutaj robisz co trzeba...
    
    plik.close();
    return 0;
}

🔢 Wczytywanie liczb do tablicy

Najczęstszy przypadek na maturze. Liczby oddzielone spacjami lub enterami.

#include <iostream>
#include <fstream>
using namespace std;

int main() {
    ifstream plik("liczby.txt");
    
    int tab[1000];  // tablica na dane
    int n = 0;      // licznik wczytanych
    
    while(plik >> tab[n]) {
        n++;
    }
    
    // Teraz masz n liczb w tablicy tab[]
    cout << "Wczytano " << n << " liczb" << endl;
    
    plik.close();
    return 0;
}

📝 Wczytywanie tekstu (słowo po słowie)

Operator >> wczytuje do spacji/entera. Idealne dla pojedynczych słów.

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    ifstream plik("tekst.txt");
    
    string slowo;
    while(plik >> slowo) {
        cout << slowo << endl;
        // Tutaj przetwarzasz każde słowo
    }
    
    plik.close();
    return 0;
}

📄 Wczytywanie całych linii (getline)

Gdy linia zawiera spacje (zdania, adresy, etc.). getline() bierze całą linię.

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    ifstream plik("zdania.txt");
    
    string linia;
    while(getline(plik, linia)) {
        cout << linia << endl;
        // Tutaj przetwarzasz całą linię
    }
    
    plik.close();
    return 0;
}

🔀 Wczytywanie mieszanych danych

Np. plik z formatem: Kowalski 25 Warszawa (string, int, string w jednej linii).

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    ifstream plik("dane.txt");
    
    string nazwisko, miasto;
    int wiek;
    
    while(plik >> nazwisko >> wiek >> miasto) {
        cout << nazwisko << " ma " << wiek << " lat, mieszka w " << miasto << endl;
    }
    
    plik.close();
    return 0;
}

💾 Zapis do pliku

Używamy ofstream zamiast ifstream. Plik tworzony automatycznie.

#include <iostream>
#include <fstream>
using namespace std;

int main() {
    ofstream plik("wynik.txt");
    
    plik << "Linia tekstu" << endl;
    plik << "Liczba: " << 42 << endl;
    
    for(int i = 1; i <= 5; i++) {
        plik << i << " ";
    }
    
    plik.close();
    cout << "Zapisano do pliku!" << endl;
    return 0;
}

📊 Wczytywanie do vectora (elastyczne)

Vector sam się rozszerza - nie musisz znać rozmiaru z góry. Polecane!

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;

int main() {
    ifstream plik("dane.txt");
    
    vector<int> liczby;
    vector<string> slowa;
    
    int x;
    while(plik >> x) {
        liczby.push_back(x);
    }
    
    // Albo dla stringów:
    // string s;
    // while(plik >> s) {
    //     slowa.push_back(s);
    // }
    
    cout << "Wczytano " << liczby.size() << " liczb" << endl;
    
    plik.close();
    return 0;
}

#02 Operacje na stringach

✂️ substr() – wycinanie kawałków

Składnia s.substr(start, długość). Pierwszy znak ma indeks 0.

string s = "230095";
int polowa = s.size() / 2;

string lewa = s.substr(0, polowa);       // "230"
string prawa = s.substr(polowa);         // "095" (do końca)
string srodek = s.substr(2, 2);          // "00"

// Ostatnie 3 znaki:
string koniec = s.substr(s.size() - 3);  // "095"

🔄 stoi() / to_string() – konwersje

Zamiana między stringiem a liczbą. Mega przydatne!

// String -> Int
string tekst = "0095";
int liczba = stoi(tekst);    // 95 (bez zer wiodących)

// String -> Double
string txt = "3.14";
double pi = stod(txt);       // 3.14

// Int -> String
int x = 42;
string s = to_string(x);     // "42"

// Przydatne: dodawanie zer wiodących
int num = 5;
string wynik = (num < 10 ? "0" : "") + to_string(num);  // "05"

🔁 Iteracja po znakach

Podstawa pracy z tekstem. Dwa sposoby - klasyczny i range-based.

string s = "matura";

// Sposób 1: klasyczna pętla (gdy potrzebujesz indeksu)
for(int i = 0; i < s.size(); i++) {
    cout << "s[" << i << "] = " << s[i] << endl;
}

// Sposób 2: range-based (prostsze, gdy nie potrzebujesz indeksu)
for(char c : s) {
    cout << c << " ";
}

// Sposób 3: modyfikacja znaków (referencja!)
for(char &c : s) {
    c = toupper(c);  // zmienia oryginalny string
}
cout << s;  // "MATURA"

🔍 find() – szukanie w stringu

Znajduje pozycję podciągu. Zwraca string::npos gdy nie znajdzie.

string s = "alamakota";

// Szukanie znaku
int poz = s.find('m');           // 3
int poz2 = s.find('m', 4);       // 5 (szukaj od indeksu 4)

// Szukanie podciągu
int gdzie = s.find("kot");       // 5

// Sprawdzenie czy istnieje
if(s.find("pies") == string::npos) {
    cout << "Nie znaleziono" << endl;
}

// Znajdź wszystkie wystąpienia
int pos = 0;
while((pos = s.find('a', pos)) != string::npos) {
    cout << "Znaleziono 'a' na pozycji " << pos << endl;
    pos++;
}

🔤 Sprawdzanie typu znaku

Funkcje z <cctype>. Zwracają true/false.

#include <cctype>

char c = 'A';

isalpha(c)   // true - czy litera (a-z, A-Z)
isdigit(c)   // false - czy cyfra (0-9)
isalnum(c)   // true - czy litera LUB cyfra
isupper(c)   // true - czy wielka litera
islower(c)   // false - czy mała litera
isspace(c)   // false - czy biały znak (spacja, tab, enter)

// Przykład: policz cyfry w stringu
string s = "abc123def456";
int cyfry = 0;
for(char c : s) {
    if(isdigit(c)) cyfry++;
}
cout << cyfry;  // 6

🔠 toupper() / tolower() – zmiana wielkości

Konwersja pojedynczych znaków. Dla całego stringa - pętla.

#include <cctype>

char c = 'a';
char wielka = toupper(c);  // 'A'
char mala = tolower('Z');  // 'z'

// Cały string na wielkie litery
string s = "Hello World";
for(char &c : s) {
    c = toupper(c);
}
cout << s;  // "HELLO WORLD"

// Albo z użyciem transform (bardziej pro)
#include <algorithm>
string s2 = "Test";
transform(s2.begin(), s2.end(), s2.begin(), ::toupper);
cout << s2;  // "TEST"

✏️ Modyfikacje stringa

Dodawanie, usuwanie, zamiana fragmentów.

string s = "Hello";

// Dodawanie na koniec
s += " World";           // "Hello World"
s.push_back('!');        // "Hello World!"
s.append("!!");          // "Hello World!!!"

// Wstawianie
s.insert(5, "XXX");      // "HelloXXX World!!!"

// Usuwanie
s.erase(5, 3);           // "Hello World!!!" (usuń 3 znaki od pozycji 5)
s.pop_back();            // "Hello World!!" (usuń ostatni znak)

// Zamiana (replace)
string txt = "kot i kot";
txt.replace(0, 3, "pies");    // "pies i kot"

// Czyszczenie
s.clear();               // "" (pusty string)
bool pusty = s.empty();  // true

⚡ Przydatne właściwości

Długość, porównywanie, dostęp do znaków.

string s = "matura";

// Długość
int len = s.length();    // 6
int len2 = s.size();     // 6 (to samo)

// Dostęp do znaków
char pierwszy = s[0];        // 'm'
char ostatni = s[s.size()-1]; // 'a'
char pierwszy2 = s.front();  // 'm'
char ostatni2 = s.back();    // 'a'

// Porównywanie (leksykograficzne)
string a = "abc", b = "abd";
if(a < b) cout << "a jest przed b";  // true
if(a == b) cout << "równe";

// Sortowanie znaków w stringu
sort(s.begin(), s.end());
cout << s;  // "aamrtu"

#03 Algorytmy

Kliknij na algorytm, żeby zobaczyć kod.

🔢 Liczby i matematyka

📊 Sortowanie

🔎 Wyszukiwanie

📝 Operacje na tekstach

🔄 Systemy liczbowe

🎲 Inne przydatne

#04 Struktury danych

📦 Vector – dynamiczna tablica

Tablica, która sama się rozszerza. Nie musisz znać rozmiaru z góry!

#include <vector>

vector<int> v;                    // pusty vector
vector<int> v2(10);               // 10 elementów (wartość 0)
vector<int> v3(10, 5);            // 10 elementów o wartości 5
vector<int> v4 = {1, 2, 3, 4};    // inicjalizacja listą

// Dodawanie elementów
v.push_back(10);        // dodaj na koniec
v.push_back(20);

// Dostęp do elementów
int x = v[0];           // pierwszy element
int y = v.back();       // ostatni element
int z = v.front();      // pierwszy element

// Rozmiar i pojemność
int n = v.size();       // ile elementów
bool pusty = v.empty(); // czy pusty?

// Usuwanie
v.pop_back();           // usuń ostatni
v.clear();              // usuń wszystko

// Iteracja
for(int i = 0; i < v.size(); i++) {
    cout << v[i] << " ";
}
// lub
for(int x : v) {
    cout << x << " ";
}

🗺️ Map – słownik (klucz → wartość)

Przechowuje pary klucz-wartość. Idealna do zliczania, indeksowania po stringu.

#include <map>

map<string, int> wiek;

// Dodawanie/modyfikacja
wiek["Jan"] = 25;
wiek["Anna"] = 30;
wiek["Jan"] = 26;       // nadpisuje

// Odczyt
cout << wiek["Anna"];   // 30

// Sprawdzenie czy klucz istnieje
if(wiek.count("Piotr") > 0) {
    cout << "Piotr istnieje";
}

// Iteracja po wszystkich parach
for(auto para : wiek) {
    cout << para.first << ": " << para.second << endl;
}

// Zliczanie wystąpień słów - KLASYKA MATURALNA!
map<string, int> ile;
string slowo;
while(cin >> slowo) {
    ile[slowo]++;
}
for(auto p : ile) {
    cout << p.first << " wystapilo " << p.second << " razy" << endl;
}

🎯 Set – zbiór unikalnych elementów

Przechowuje unikalne wartości (bez duplikatów), automatycznie posortowane.

#include <set>

set<int> s;

// Dodawanie
s.insert(5);
s.insert(3);
s.insert(5);    // ignorowane - już jest!
s.insert(8);

// s zawiera: {3, 5, 8} - posortowane!

// Sprawdzenie czy element istnieje
if(s.count(5) > 0) {
    cout << "5 jest w zbiorze";
}

// lub (C++20)
if(s.contains(5)) {
    cout << "5 jest w zbiorze";
}

// Rozmiar (liczba unikalnych)
cout << s.size();   // 3

// Iteracja
for(int x : s) {
    cout << x << " ";   // 3 5 8
}

// Usuwanie
s.erase(5);     // usuwa 5 ze zbioru

// Przydatne: wypisz unikalne elementy tablicy
int tab[] = {1, 2, 2, 3, 1, 4, 3};
set<int> unikalne(tab, tab + 7);
for(int x : unikalne) {
    cout << x << " ";   // 1 2 3 4
}

📚 Pair – para wartości

Przechowuje dwie wartości razem. Przydatne przy sortowaniu z zachowaniem indeksów.

#include <utility>  // lub po prostu <algorithm>

pair<int, int> p;
p.first = 10;
p.second = 20;

// Lub od razu
pair<int, int> p2 = {5, 15};
pair<string, int> osoba = {"Jan", 25};

// Tworzenie pary
auto p3 = make_pair(100, 200);

// Vector par - przydatne!
vector<pair<int, int>> punkty;
punkty.push_back({3, 4});
punkty.push_back({1, 2});

// Sortowanie par (najpierw po first, potem po second)
sort(punkty.begin(), punkty.end());

// Sortowanie z zachowaniem oryginalnych indeksów
vector<pair<int, int>> v;  // {wartość, indeks}
int tab[] = {5, 2, 8, 1};
for(int i = 0; i < 4; i++) {
    v.push_back({tab[i], i});
}
sort(v.begin(), v.end());
// Teraz v[0].second to indeks najmniejszego elementu

📋 Struct – własna struktura

Grupowanie powiązanych danych. Lepsze niż kilka osobnych tablic!

// Definicja struktury
struct Uczen {
    string imie;
    string nazwisko;
    int wiek;
    double srednia;
};

int main() {
    // Tworzenie
    Uczen u1;
    u1.imie = "Jan";
    u1.nazwisko = "Kowalski";
    u1.wiek = 18;
    u1.srednia = 4.5;
    
    // Lub od razu
    Uczen u2 = {"Anna", "Nowak", 17, 5.0};
    
    // Tablica struktur
    Uczen uczniowie[100];
    uczniowie[0] = {"Piotr", "Wisniewski", 18, 3.5};
    
    // Vector struktur
    vector<Uczen> klasa;
    klasa.push_back({"Maria", "Kaczmarek", 17, 4.8});
    
    // Sortowanie po wybranym polu
    sort(klasa.begin(), klasa.end(), [](Uczen a, Uczen b) {
        return a.srednia > b.srednia;  // malejąco po średniej
    });
    
    return 0;
}

📊 Tablica 2D – macierz

Tablica dwuwymiarowa - do gier planszowych, grafów, obrazów.

// Statyczna tablica 2D
int tab[3][4];              // 3 wiersze, 4 kolumny

// Inicjalizacja
int macierz[2][3] = {
    {1, 2, 3},
    {4, 5, 6}
};

// Dostęp: tab[wiersz][kolumna]
cout << macierz[0][2];      // 3 (pierwszy wiersz, trzecia kolumna)

// Wypełnianie
for(int i = 0; i < 3; i++) {
    for(int j = 0; j < 4; j++) {
        tab[i][j] = i * j;
    }
}

// Wypisywanie
for(int i = 0; i < 3; i++) {
    for(int j = 0; j < 4; j++) {
        cout << tab[i][j] << " ";
    }
    cout << endl;
}

// Vector 2D (elastyczny rozmiar)
int n = 5, m = 10;
vector<vector<int>> v(n, vector<int>(m, 0));
// n wierszy, m kolumn, wypełnione zerami

v[2][3] = 42;   // dostęp jak do tablicy