Operacje na Stringach (Tekstach) - Matura z Informatyki
Operacje na stringach (czyli łańcuchach znaków) to absolutna podstawa niemal każdego zadania maturalnego. String to po prostu sekwencja znaków, np. 'Ala ma kota' albo '10110'. Prawie każde zadanie, w którym wczytujesz dane z pliku, zaczyna się od operacji na stringach! Nawet jeśli w pliku masz liczby, to wczytując linię '123\n', najpierw dostajesz stringa. Musisz go 'oczyścić' (np. usunąć znak nowej linii) i dopiero potem zamienić na liczbę. Musisz biegle poruszać się po stringach, umieć pobierać pojedyncze znaki, wycinać fragmenty i łączyć je. Traktuj stringa jak tablicę jednowymiarową, której elementami są pojedyncze znaki. To myślenie bardzo ułatwia sprawę.
Dlaczego to ważne? Nie ma matury bez stringów. Pojawiają się w zadaniach z liczbami binarnymi (gdzie analizujesz string '100110'), zadaniach z palindromami, anagramami, czy jakimkolwiek parsowaniu (wyciąganiu) danych z plików tekstowych. Wczytanie i przetworzenie linii z pliku to fundament, który wykorzystasz w każdym jednym arkuszu.
Teoria
String (łańcuch znaków) to sekwencja znaków. Najważniejsze, co musisz pamiętać: to działa jak tablica. Każdy znak ma swój indeks (pozycję), a numeracja indeksów zawsze zaczyna się od 0. W Pythonie stringi są niemutowalne, co znaczy, że nie możesz zmienić pojedynczego znaku (np. 'napis[0] = "B"'). Musisz stworzyć nowy string. W C++ 'std::string' jest mutowalny (można zmieniać pojedyncze znaki).
Jak to działa?
- Indeksowanie od 0: 'napis[0]' to pierwszy znak.
- Ostatni indeks: 'napis[len(napis)-1]' (w Pythonie) lub 'napis[napis.length()-1]' (w C++). Python ma skrót: 'napis[-1]'.
- Długość: 'len(napis)' w Pythonie, 'napis.length()' lub 'napis.size()' w C++.
- Łączenie (Konkatenacja): 'nowy_napis = napis1 + napis2'.
- Cięcie (Slicing - tylko Python): 'napis[1:4]' daje znaki od indeksu 1 do 3 (bez 4!). 'napis[3:]' daje znaki od indeksu 3 do końca. 'napis[:5]' daje 5 pierwszych znaków (indeksy 0-4).
- Wycinek (C++): 'napis.substr(start, dlugosc)', np. 'napis.substr(1, 3)' da 3 znaki, zaczynając od indeksu 1.
- Iteracja: Po stringu możesz przechodzić pętlą 'for', tak jak po tablicy.
Złożoność: Złożoność czasowa: Odczyt znaku po indeksie (np. `napis[5]`) jest natychmiastowy: O(1). Pobranie długości: O(1). Łączenie (s1 + s2): O(n+m), gdzie n i m to długości stringów (bo trzeba stworzyć nowy string). Wyszukiwanie podciągu (np. `find`): O(n*m) w najgorszym przypadku.
Implementacja
Podstawowe operacje (Indeks, Cięcie, Pętla)
Pythonnapis = "Matura2026"
# 1. Długość i Indeksowanie
print(f"Długość: {len(napis)}") # Długość: 10
print(f"Pierwszy znak: {napis[0]}") # M
print(f"Ostatni znak: {napis[-1]}") # 6
# 2. Cięcie (Slicing)
print(f"Fragment 'tura': {napis[2:6]}") # indeksy od 2 do 5
print(f"Tylko 'Matura': {napis[:6]}") # od początku do 5
print(f"Tylko '2026': {napis[6:]}") # od 6 do końca
# 3. Łączenie
napis2 = napis + "!"
print(napis2) # Matura2026!
# 4. Iteracja (Pętla For)
for litera in napis:
print(litera, end="-")
# Wynik: M-a-t-u-r-a-2-0-2-6-Podstawowe operacje na stringach w Pythonie. Zwróć uwagę na cięcie (slicing) `[start:stop]`, które jest bardzo wygodne i często używane. Pamiętaj, że ostatni znak to `napis[-1]`.
Ważne metody maturalne (strip, find, isdigit)
Python# 1. strip() - usuwanie białych znaków (NAJWAŻNIEJSZE)
linia_z_pliku = " 123 \n"
print(f"Oczyszczona: {linia_z_pliku.strip()}") # '123'
# 2. find() - szukanie podciągu
napis = "Ala ma kota"
print(f"Indeks 'ma': {napis.find('ma')}") # 4
print(f"Indeks 'psa': {napis.find('psa')}") # -1 (gdy nie znajdzie)
# 3. isdigit() - sprawdzanie czy string jest liczbą
print(f"Czy '123' to liczba? {'123'.isdigit()}") # True
print(f"Czy '123a' to liczba? {'123a'.isdigit()}") # False
# 4. split() - dzielenie stringa (np. wczytanie dwóch liczb)
linia_dwoch_liczb = "100 500"
czesci = linia_dwoch_liczb.split(' ')
# czesci to teraz lista ['100', '500']
a = int(czesci[0])
b = int(czesci[1])Metody `.strip()` (usuwa białe znaki, w tym `\n` z pliku) i `.isdigit()` (sprawdza, czy string to same cyfry) są ekstremalnie przydatne na maturze. `.find()` zwraca indeks pierwszego wystąpienia lub -1.
Podstawowe operacje (std::string)
C++#include <iostream>
#include <string>
using namespace std;
int main() {
string napis = "Matura2026";
// 1. Długość i Indeksowanie
cout << "Długość: " << napis.length() << endl; // Długość: 10
cout << "Pierwszy znak: " << napis[0] << endl; // M
cout << "Ostatni znak: " << napis[napis.length() - 1] << endl; // 6
// 2. Łączenie
string napis2 = napis + "!";
cout << napis2 << endl; // Matura2026!
// 3. Iteracja (Pętla For)
for (int i = 0; i < napis.length(); i++) {
cout << napis[i] << "-";
}
// Wynik: M-a-t-u-r-a-2-0-2-6-
// 4. Stringi w C++ SĄ mutowalne!
napis[0] = 'm';
cout << "\nZmieniony napis: " << napis << endl; // matura2026
return 0;
}W C++ musisz dołączyć bibliotekę `<string>`. Używamy `std::string`. Długość pobieramy przez `.length()` (lub `.size()`). Najważniejsza różnica: stringi w C++ są mutowalne, czyli możesz zmienić pojedynczy znak, np. `napis[0] = 'm'`.
Ważne metody maturalne (getline, substr, find)
C++#include <iostream>
#include <string>
#include <fstream> // Do wczytywania plików
using namespace std;
int main() {
// 1. Wczytanie całej linii (jak 'for linia in plik' w Pythonie)
// string linia;
// ifstream plik("dane.txt");
// while (getline(plik, linia)) {
// cout << linia << endl;
// }
string napis = "Ala ma kota";
// 2. find() - szukanie podciągu
cout << "Indeks 'ma': " << napis.find("ma") << endl; // 4
// Gdy nie znajdzie, zwraca string::npos (bardzo duża liczba), a nie -1
if (napis.find("psa") == string::npos) {
cout << "'psa' nie znaleziono" << endl;
}
// 3. substr(indeks_start, dlugosc) - wycinanie
string fragment = napis.substr(4, 2); // od ind. 4, weź 2 znaki
cout << "Fragment: " << fragment << endl; // 'ma'
return 0;
}Wczytywanie linii w C++ robi się pętlą `while (getline(plik, linia))`. `.find()` działa podobnie, ale zwraca `string::npos` zamiast -1, gdy nic nie znajdzie. Do wycinania służy `.substr(indeks, długość)`.
Przykładowe Zadania Maturalne
W pliku 'dane.txt' znajduje się 100 słów, każde w nowej linii. Wypisz wszystkie te słowa, które zaczynają się na literę 'A' i jednocześnie kończą na literę 'a'.
Wskazówka: Musisz wczytać każde słowo (linię) z pliku pętlą FOR. Pamiętaj o użyciu `.strip()`. Dla każdego słowa musisz sprawdzić dwa warunki: pierwszy znak (indeks 0) oraz ostatni znak (indeks -1 w Pythonie lub `s[s.length()-1]` w C++).
Pokaż szkic rozwiązania
1. Otwórz plik 'dane.txt' do odczytu. 2. Rozpocznij pętlę FOR 'for linia in plik:'. 3. W pętli: a. Oczyść słowo: 'slowo = linia.strip()'. b. Sprawdź, czy słowo nie jest puste: 'if len(slowo) > 0:'. c. Sprawdź warunek dla pierwszego znaku: 'pierwszy = slowo[0]'. d. Sprawdź warunek dla ostatniego znaku: 'ostatni = slowo[-1]'. e. Połącz warunki: 'if pierwszy == 'A' and ostatni == 'a':'. f. Jeśli oba są prawdziwe, wypisz 'slowo'.
W pliku symbole.txt zapisano 2000 napisów. Każdy z nich jest zapisany w osobnym wierszu i składa się z dokładnie 12 znaków. Podaj wszystkie takie napisy z pliku symbole.txt, które są palindromami (czytane od przodu i od tyłu są takie same). Wypisz je po jednym w wierszu, w kolejności takiej jak w pliku symbole.txt.
Wskazówka: Palindrom to słowo, które jest identyczne jak jego odwrotność. Musisz wczytać każdy napis z pliku. Dla każdego napisu 's' musisz sprawdzić, czy 's' jest równy 's' odwróconemu. W Pythonie odwrócenie stringa jest trywialnie proste: `s[::-1]`.
Pokaż szkic rozwiązania
1. Zdefiniuj funkcję `czy_palindrom(s)`: a. (Python) Zwróć `s == s[::-1]`. b. (C++) Zrób kopię stringa, odwróć ją pętlą lub funkcją `reverse()` i porównaj. c. (Alternatywnie w C++) Użyj pętli z dwoma wskaźnikami (jeden od początku, drugi od końca) i porównuj znaki idąc do środka. 2. Otwórz plik 'symbole.txt'. 3. Dla każdej linii w pliku: a. Wczytaj napis: `napis = linia.strip()`. b. Sprawdź warunek: `if czy_palindrom(napis):`. c. Jeśli 'True', wypisz 'napis'.
Częste Błędy
❌ Indeksowanie od 1 zamiast od 0
To najczęstszy błąd początkujących. Informatycy liczą od 0. Pierwszy znak to `s[0]`, drugi to `s[1]`. Mylenie tego prowadzi do błędów 'IndexError'.
Poprawka: Wbij sobie do głowy: pierwszy element ma indeks 0, ostatni ma indeks `dlugosc - 1`.
❌ Błąd 'IndexError: string index out of range'
Próba odwołania się do znaku, który nie istnieje, np. `napis[10]` w słowie 'Ala'. Dzieje się tak często przy sprawdzaniu ostatniego znaku, np. `napis[len(napis)]` (błąd!) zamiast `napis[len(napis) - 1]`.
Poprawka: Zawsze pamiętaj, że ostatni indeks to `długość - 1`. W Pythonie bezpieczniej używać `napis[-1]` dla ostatniego znaku.
❌ Python: Próba modyfikacji stringa (Immutability)
W Pythonie stringi są niemutowalne. Kod 's = "Ala"; s[0] = "O"' wyrzuci błąd TypeError. Nie możesz zmieniać stringa 'w miejscu'.
Poprawka: Musisz stworzyć nowy string, np. 's = "O" + s[1:]'. (W C++ ten problem nie występuje, tam stringi są mutowalne).
❌ Zapominanie o .strip() przy wczytywaniu
Wczytujesz linię '123' z pliku. W rzeczywistości wczytałeś string '123\n' (ze znakiem nowej linii). Potem `int('123\n')` daje błąd, a `len('123\n')` to 4, a nie 3.
Poprawka: ZAWSZE przy wczytywaniu linii z pliku używaj `.strip()`: `linia = plik.readline().strip()`.
❌ Python: .find() zwraca -1, a nie False
Uczeń pisze: `if not napis.find('a'): ...`. To błąd. `find('a')` może zwrócić 0 (jeśli 'a' jest na początku), a `not 0` to `True`. Jeśli nie znajdzie, zwróci -1, a `not -1` to `False`.
Poprawka: Zawsze porównuj wynik `find` z `-1`. Poprawnie: `if napis.find('a') != -1:` (czyli 'jeśli znaleziono').
Kluczowe Wnioski
- String to tablica znaków.
- Indeksy zawsze liczymy od 0.
- W Pythonie stringi są niemutowalne (niezmienne) - nie można zmienić znaku przez `s[i] = 'x'`.
- W C++ `std::string` jest mutowalny (można zmieniać znaki).
- Podstawowe operacje to: `+` (łączenie), `[i]` (indeks), `len(s)` lub `s.length()` (długość).
- W Pythonie `.strip()` jest kluczowe przy wczytywaniu danych z plików tekstowych.
- W Pythonie cięcie (slicing) `s[a:b]` i odwracanie `s[::-1]` są bardzo potężne.
Najczęściej Zadawane Pytania
❓ Jak w Pythonie sprawdzić, czy string zawiera tylko cyfry?
Użyj metody `.isdigit()`. Na przykład `"12345".isdigit()` zwróci `True`, ale `"123a".isdigit()` zwróci `False`.
❓ Jak zamienić string na liczbę (int)?
W Pythonie: `liczba = int("123")`. W C++: `#include <string>`, `int liczba = stoi("123");` (string to integer).
❓ Jak zamienić liczbę (int) na string?
W Pythonie: `napis = str(123)`. W C++: `#include <string>`, `string napis = to_string(123);`.
❓ Jak najszybciej odwrócić string w Pythonie, aby sprawdzić palindrom?
Użyj cięcia (slicingu) z odwróconym krokiem: `odwrocony = napis[::-1]`. Wtedy wystarczy sprawdzić `if napis == odwrocony:`.
❓ Co zwraca `s.find('x')` jeśli `x` nie występuje?
W Pythonie zwraca `-1`. W C++ (`std::string::find`) zwraca specjalną stałą `std::string::npos` (która jest bardzo dużą liczbą, a nie -1).
Chcesz opanować wszystkie tematy maturalne?
Dołącz do kursu i zyskaj dostęp do interaktywnych lekcji, edytora kodu i setek zadań.