Урок 6. Строки std::string
Текст в C++ хранится в строках — переменных типа string. Строка умеет узнавать свою длину, склеиваться с другими строками, искать в себе подстроку и многое другое. Для неё нужен #include <string>.
Создание, длина, символы
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "Hello";
string t = "world";
string u = s + ", " + t + "!";
cout << u << "\n";
cout << u.size() << "\n";
cout << u[0] << u[7] << "\n";
u[0] = 'J';
cout << u << "\n";
return 0;
}Hello, world!
13
Hw
Jello, world!- Строка пишется в двойных кавычках:
"Hello". Один символ (char) — в одинарных:'J'. u.size()(илиu.length(), это одно и то же) — число символов.u[i]— символ с индексомi; как и в массиве, нумерация с нуля, и границы не проверяются.+склеивает строки,+=дописывает в конец:s += "!";.
Пустая строка — "", у неё size() равен 0, а s.empty() — true.
Ввод строки
cin >> s читает одно слово — до первого пробела или перевода строки. Целую строку с пробелами читает getline(cin, s). У getline есть ловушка после cin >>, она разобрана в справке Как прочитать строку с пробелами.
Символы и их коды
Каждый символ — это число, его код. Латинские буквы, цифры и знаки препинания имеют коды из таблицы ASCII: 'A' — 65, 'a' — 97, '0' — 48. Буквы и цифры идут в таблице подряд, поэтому с символами можно считать:
#include <iostream>
using namespace std;
int main() {
char c = 'A';
cout << c + 1 << "\n";
cout << char(c + 1) << "\n";
char d = '7';
int digit = d - '0';
cout << digit * 2 << "\n";
return 0;
}66
B
14c + 1 — уже число (66), а char(c + 1) превращает его обратно в символ. d - '0' — частый приём: из символа цифры получается сама цифра.
Проверить символ можно сравнениями (c >= '0' && c <= '9' — цифра) или функциями из <cctype>:
| Функция | Что проверяет или делает |
|---|---|
isdigit(c) | цифра ли это |
isalpha(c) | латинская буква ли это |
isspace(c) | пробел, табуляция, перевод строки |
toupper(c), tolower(c) | та же буква большая или маленькая |
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main() {
string s;
cin >> s;
int letters = 0, digits = 0;
for (char& c : s) {
if (isdigit(c)) {
digits++;
} else if (isalpha(c)) {
letters++;
c = toupper(c);
}
}
cout << letters << " " << digits << " " << s << "\n";
return 0;
}abc123x4 3 ABC123XЧасть строки и поиск
#include <iostream>
#include <string>
using namespace std;
int main() {
string date = "2024-11-05";
string year = date.substr(0, 4);
string month = date.substr(5, 2);
cout << year << " " << month << "\n";
cout << date.find('-') << "\n";
cout << date.find("11") << "\n";
if (date.find("abc") == string::npos) {
cout << "not found\n";
}
return 0;
}2024 11
4
5
not founds.substr(pos, len)— кусок строки:lenсимволов начиная с индексаpos. Без второго числа — до конца строки.s.find(x)— индекс первого вхождения символа или подстрокиx. Если ничего не найдено, возвращается особое значениеstring::npos. Проверяйте именно сравнением сstring::npos, а не с-1или0.
Ещё полезное: s.erase(pos, len) удаляет кусок, s.insert(pos, t) вставляет строку t, s.back() — последний символ, s.pop_back() — удалить последний символ.
Сравнение строк
Строки сравниваются обычными ==, !=, <, >. Порядок — словарный (лексикографический): по первому различающемуся символу, точнее по его коду.
#include <iostream>
#include <string>
using namespace std;
int main() {
string a = "apple", b = "banana", c = "Zebra";
cout << (a < b) << "\n";
cout << (c < a) << "\n";
cout << (string("10") < string("9")) << "\n";
return 0;
}1
1
1Две неожиданности: "Zebra" меньше "apple", потому что код большой Z (90) меньше кода маленькой a (97). А "10" меньше "9", потому что '1' меньше '9': строки из цифр сравниваются не как числа. Перевести строку в число и обратно помогает справка Как перевести строку в число.
Переворот строки и палиндром
Функция reverse из <algorithm> переворачивает строку. Палиндром — слово, которое одинаково читается в обе стороны:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string s;
cin >> s;
string r = s;
reverse(r.begin(), r.end());
if (r == s) {
cout << "palindrome\n";
} else {
cout << "not palindrome\n";
}
return 0;
}levelpalindromes.begin() и s.end() — начало и конец строки. Так же, парой «начало — конец», работают и другие функции стандартной библиотеки — о них урок STL: sort, map и set.
Русские буквы
string хранит не буквы, а байты. В кодировке UTF-8 (она обычна в Linux, macOS и для g++) латинская буква занимает один байт, а русская — два:
#include <iostream>
#include <string>
using namespace std;
int main() {
string en = "world";
string ru = "мир";
cout << en.size() << " " << ru.size() << "\n";
return 0;
}5 6Поэтому с русским текстом size(), s[i], reverse и toupper работают не по буквам. Для задач с русскими словами нужны отдельные средства; на олимпиадах текст обычно латинский.
Коротко
string s = "text";— строка, нужен#include <string>;'c'— один символchar.s.size()— длина,s[i]— символ,+и+=— склейка.substr(pos, len)— часть строки,find— поиск, «не найдено» —string::npos.- Символы — числа:
d - '0'даёт цифру,char(c + 1)— следующую букву. - Строки сравниваются по словарю, по кодам символов:
"10" < "9". - Русская буква в UTF-8 — два байта.