Kurz: Anders als in C ist std::string ein wachsender, verwalteter Text:
Teil des Kurses C++
std::string
Anders als in C ist std::string ein wachsender, verwalteter Text:
#include <iostream>
#include <string>
#include <string_view>
#include <algorithm>
int main() {
std::string s = "Hallo Welt";
s += "!";
std::cout << s << " " << s.size() << " " << s[0] << " " << s.at(1) << '\n';
std::cout << s.substr(6, 4) << " " << s.find("Welt") << " " << (s.find("x") == std::string::npos) << '\n';
s.replace(0, 5, "Servus");
s.insert(s.size(), "!!");
std::cout << s << '\n';
std::string a = "abc", b = "abd";
std::cout << (a < b) << (a == "abc") << ' ' << a + b << '\n';
std::transform(a.begin(), a.end(), a.begin(), [](unsigned char c) { return std::toupper(c); });
std::cout << a << ' ' << std::to_string(42) + "x" << ' ' << std::stoi("123") + 1 << ' ' << std::stod("2.5") * 2 << '\n';
std::string_view sicht = s; // nur ansehen, nicht kopieren
std::cout << sicht.substr(0, 6) << " " << s.starts_with("Servus") << '\n'; // C++20
return 0;
}Ausgabe:
Hallo Welt! 11 H a
Welt 6 1
Servus Welt!!!
11 abcabd
ABC 42x 124 5
Servus 1std::string_view (C++17) ist eine leichte Sicht auf bestehenden Text ohne Kopie: ideal für Parameter, die nur lesen.
vector: das Standard-Array
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> v{5, 3, 9};
v.push_back(1); // hinten anhängen (wächst automatisch)
v.insert(v.begin() + 1, 42); // an Position einfügen
std::cout << v.size() << ' ' << v.front() << ' ' << v.back() << ' ' << v[2] << ' ' << v.at(3) << '\n';
v.pop_back();
v.erase(v.begin()); // erstes Element löschen
std::sort(v.begin(), v.end());
for (int x : v) std::cout << x << ' ';
std::cout << '\n';
std::vector<std::string> namen{"Mia", "Tom"};
namen.emplace_back("Zoe"); // direkt im Vektor erzeugen
std::vector<int> nullen(5, 0); // fünf Nullen
std::vector<std::vector<int>> matrix(2, std::vector<int>(3, 1));
std::cout << namen.size() << nullen.size() << matrix[1][2] << '\n';
try { v.at(99); } catch (const std::out_of_range& e) { std::cout << "außerhalb\n"; }
return 0;
}Ausgabe:
5 5 1 3 9
3 9 42
351
außerhalbat(i) prüft die Grenze und wirft eine Ausnahme, [i] prüft nicht (schneller, aber UB bei Fehlern).
Weitere Container
| Container | Eigenschaft | Typische Nutzung |
|---|---|---|
std::array<T, N> | feste Größe, auf dem Stack | kleine feste Felder |
std::vector<T> | wachsend, zusammenhängend | Standardwahl |
std::deque<T> | vorn und hinten schnell | Warteschlange |
std::list<T> | doppelt verkettet | selten sinnvoll |
std::set<T>, std::map<K,V> | sortiert, Baum | sortierte Mengen/Tabellen |
std::unordered_set<T>, std::unordered_map<K,V> | Hashtabelle | schnelles Suchen |
std::stack<T>, std::queue<T>, std::priority_queue<T> | Adapter | Stapel, Schlange, Priorität |
#include <iostream>
#include <map>
#include <unordered_map>
#include <set>
#include <string>
#include <queue>
#include <array>
int main() {
std::map<std::string, int> alter; // sortiert nach Schlüssel
alter["Tom"] = 19;
alter["Mia"] = 17;
alter.insert({"Zoe", 21});
for (const auto& [name, jahre] : alter) std::cout << name << '=' << jahre << ' ';
std::cout << '\n';
if (auto it = alter.find("Mia"); it != alter.end()) std::cout << "gefunden " << it->second << '\n';
std::cout << alter.count("Max") << alter.contains("Tom") << '\n'; // contains: C++20
std::unordered_map<char, int> haeufig;
for (char c : std::string("mississippi")) haeufig[c]++;
std::cout << haeufig['s'] << haeufig['i'] << haeufig['p'] << '\n';
std::set<int> menge{3, 1, 3, 2};
std::cout << menge.size() << ' ' << *menge.begin() << '\n';
std::priority_queue<int> pq;
for (int x : {5, 1, 8, 3}) pq.push(x);
std::cout << pq.top() << '\n';
std::array<int, 3> fest{1, 2, 3};
std::cout << fest.size() << fest[1] << '\n';
return 0;
}Ausgabe:
Mia=17 Tom=19 Zoe=21
gefunden 17
01
442
3 1
8
32Achtung
map[key]legt einen fehlenden Schlüssel neu an (mit Standardwert). Zum bloßen Nachsehen nimmfind,containsoderat.
Iteratoren
Iteratoren sind verallgemeinerte Zeiger auf Elemente. Container liefern sie mit begin() und end() (hinter das letzte Element). Algorithmen arbeiten mit Iterator-Paaren:
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <list>
int main() {
std::vector<int> v{4, 8, 15, 16, 23, 42};
auto it = std::find(v.begin(), v.end(), 15);
std::cout << (it - v.begin()) << ' ' << *it << '\n';
v.erase(std::remove_if(v.begin(), v.end(), [](int x) { return x % 2; }), v.end()); // Erase-Remove-Idiom
for (int x : v) std::cout << x << ' ';
std::cout << '\n';
std::cout << std::reduce(v.begin(), v.end()) << ' ' << std::accumulate(v.begin(), v.end(), 1, [](int a, int b) { return a + b / 2; }) << '\n';
std::reverse(v.begin(), v.end());
std::list<int> l(v.begin(), v.end());
std::cout << l.front() << l.back() << '\n';
std::erase_if(v, [](int x) { return x > 30; }); // C++20: kürzer
std::cout << v.size() << '\n';
return 0;
}Ausgabe:
2 15
4 8 16 42
70 36
424
3Welcher Container?
- Im Zweifel
std::vector. Er ist cachefreundlich und meist am schnellsten - Schlüssel → Wert:
std::unordered_map(schnell) oderstd::map(sortiert) - Duplikate entfernen / Mengen:
std::setoderstd::unordered_set - Feste kleine Größe:
std::array - Warteschlange:
std::dequeoderstd::queue
Merke
std::stringverwaltet Text selbst;std::string_viewist eine kopierfreie Sichtstd::vectorist der Standardcontainer:push_back,size,at,erasemap/setsortiert,unordered_map/unordered_setper Hashmap[key]legt fehlende Schlüssel an:find/containszum Suchen- Iteratoren (
begin(),end()) verbinden Container mit Algorithmen
Übungsaufgabe
Zähle die Häufigkeit der Wörter in einem Satz mit std::map und gib die Wörter sortiert mit ihrer Anzahl aus.
Quiz zur Selbstkontrolle
Welcher Container ist meist die beste Standardwahl?
- std::vector (richtig)
- std::list
- std::map
- std::deque
für einen fehlenden Schlüssel?
- Legt den Eintrag mit Standardwert neu an (richtig)
- Wirft immer eine Ausnahme
- Gibt nullptr zurück
- Ignoriert den Zugriff
Was ist string_view?
- Eine kopierfreie, nur lesende Sicht auf Text (richtig)
- Eine grafische Darstellung
- Ein veränderlicher String
- Ein Dateistrom
Weiter im Kurs
Zurück: Funktionen, Lambdas und constexpr
Weiter: Klassen und Objekte
Alle Kapitel: C++ im Überblick