Napisy
W tej lekcji dowiesz się, jak używać zmiennych przechowujących tekst. Jako ludzie, tekst jest podstawowym medium, poprzez które wchodzimy w interakcję z programami komputerowymi. Poznanie podstawowych zasad przechowywania tekstu i manipulacji nim jest kluczowe dla tworzenia funkcjonalnych aplikacji, z których ludzie mogą i chcą korzystać.
Motywacja
Zmienne typu tekstowego są bardzo przydatne. Przykładem niech będzie program, który wczytuje imie użytkownika, po czym wita go podając ilość znaków w jego imieniu.
#include <iostream>
#include <string>
int main()
{
std::string name;
std::cout << "Podaj swoje imie: ";
std::cin >> name;
std::cout << "Witaj, " << name << "!\n";
std::cout << "Twoje imie ma " << name.size() << " znakow.\n";
}
Typ przechowujący tekst
W poprzednich lekcjach mówiliśmy o różnych typach zmiennych, głównie tych,
które przechowują liczby. Wspomnieliśmy też o typie char
(od ang.: character), który przechowuje
pojedynczy znak.
W programowaniu, na tekst mówi się łańcuch znaków (ang.: string).
W C++ istnieje typ, który pozwala nam przechowywać i manipulować takimi łańcuchami i jest to std::string
.
Aby móc poprawnie korzystać z std::string
musimy dodać do kodu nagłówek string
,
w ten sam sposób co wcześniej iostream
:
#include <string>
Typu std::string
używamy tak jak każdego innego.
Tutaj deklarujemy dwie zmienne - jedną o typie int
oraz jedną o typie std::string
.
int number;
std::string text;
Inicjalizacja
Przypisanie początkowej wartości wygląda tak samo jak w przypadku zmiennych o innych typach, przy czym należy pamiętać, że tekst podajemy między cudzysłowami, nie pojedynczymi apostrofami:
std::string welcome = "Hello, World!";
std::cout << welcome;
Jeśli nie podamy żadnej wartości, nasz łańcuch znaków będzie pusty. Jego długość będzie wynosić 0, a po wypisaniu na konsolę nie zobaczymy nic,
Operacje na napisach
Interakcja z użytkownikiem
Napisy możemy wyświetlać za pomocą std::cout
oraz wczytywać za pomocą std::cin
.
#include <iostream>
#include <string>
int main()
{
std::string name;
std::cout << "Podaj swoje imie: ";
std::cin >> name;
std::cout << "Witaj, " << name << "!\n";
}
Zauważ, że std::cin
pobiera tekst do napotkania pierwszego białego znaku, czyli np. spacji, znaku nowej linii czy tabulatora.
Przez to, jeśli podamy swoje imię i nazwisko to do zmiennej name
trafi jedynie imię.
Aby pobrać całą linię możemy użyć std::getline
:
std::string full_name;
std::getline(std::cin, full_name);
std::getline
jest funkcją, która przyjmuje dwa argumenty - strumień wejściowy do odczytania linii oraz zmienną std::string
do której ta linia zostanie zapisana.
Ten przykład pokazuje jak można użyć tej funkcji do odczytania linii z std::cin
.
Tak więc funkcję tę "wywołujemy" umieszczając nazwę funkcji std::getline
, następnie nawiasy (...)
,
a wewnątrz nawiasów argumenty, które chcemy podać, oddzielone przecinkiem: std::cin, full_name
.
Łączenie
Operatory +
i +=
mogą być użyte do konkatenacji dwóch napisów oraz dołączenia jednego napisu do drugiego.
Rozważmy następujący skrócony przykład z wejściem Dwayne Johnson
:
std::string first_name;
std::string last_name;
std::cin >> first_name;
std::cin >> last_name;
// Konkatenacja
std::string cool_name = first_name + " \"The Rock\" " + last_name;
std::cout << "Your cool name is:\n" << cool_name << "\n\n";
// Dołączanie
cool_name += " Mk II";
std::cout << "Your new name is:\n" << cool_name;
Your cool name is:
Dwayne "The Rock" Johnson
Your new name is:
Dwayne "The Rock" Johnson Mk II
Zauważ, że cool_name
jest wynikiem konkatenacji trzech łańcuchów - first_name
, "The Rock"
i last_name
.
Dalej w kodzie można zobaczyć, jak modyfikujemy cool_name
poprzez dołącznie do niego " Mk II"
.
Sprawdzanie długości
Aby sprawdzić ile znaków znajduje się w łancuchu używamy tak zwanej metody size
.
O funkcjach i metodach będziemy mówić więcej w dalszej części kursu, gdyż są one bardzo ważnym pojęciem.
Zobaczmy jak wykorzystać metodę size
w praktyce. Rozważmy następujący przykład z wejściem Johnny
:
#include <iostream>
#include <string>
int main()
{
std::string name;
std::cout << "Enter your name: ";
std::cin >> name;
std::cout << "\nWelcome, " << name << "!\n";
std::cout << "Your name has " << name.size() << " characters.\n";
}
Welcome, Johnny!
Your name has 6 characters.
Metodę size
wywołujemy na zmiennej name
w następujący sposób: name.size()
.
Symbol .
wskazuje, że mamy dostęp do czegoś na naszej zmiennej name
.
size
jest nazwą metody, do której uzyskujemy dostęp.
Użycie nawiasów ()
* wywołuje* metodę size
.
Ta zwraca nam całkowitą liczbę znaków w napisie.
Te pojęcia nie są teraz kluczowe do zapamiętania, ale zobaczysz je później w lekcjach Funkcje i Metody; po prostu zapamiętaj jak ich używać.
Dla przypomnienia, określamy zmienną (name
), następnie piszemy size
po kropce, a potem puste nawiasy okrągłe:
name.size()
Konwersja pomięzdy liczbami i tekstem
Liczby i łańcuchy nie mogą być swobodnie konwertowane na siebie bez specjalnych funkcji, która robią to za nas. Dzieje się tak dlatego, że typy liczbowe i typy łańcuchów w C++ są zdecydowanie różne i nie są ogólnie kompatybilne. Choć może to być denerwujące, jest to w rzeczywistości bardzo ważne dla tworzenia kodu wolnego od błędów.
53
"53"
Pierwszą wartością jest liczba 53
. Reprezentuje ona wartość, na której możemy wykonywać operacje matematyczne.
Druga wartość to tekst składający się ze znaków '5'
i '3'
.
Nie możemy wykonywać operacji matematycznych na łańcuchach; raczej, operacje na łańcuchach, które możemy wykonać to konkatenacje.
Następujące kawałki kodu to nieudolne i niepoprawne (kończące się błędem kompilacji) próby konwersji między łańcuchami a liczbami:
- ❌ Niepoprawne
- ❌ Niepoprawne
- ❌ Niepoprawne
- ❌ Niepoprawne
int number = 53;
std::string number_in_str = number; // Błąd
std::string number_in_str = 53; // Błąd
std::string str = "53";
int number = str; // Error
int number = "53"; // Error
Aby przekonwertować z typu liczbowego (np. int
czy float
) na typ łańcuchowy, musimy użyć funkcji std::to_string
.
int number = 53;
std::string number_in_str = std::to_string(number);
W ten sam sposób, jeśli mamy wewnątrz łańcucha znaków zapisaną liczbę, możemy ją
przekonwertować na int
a za pomocą std::stoi
(od ang.: string to int) oraz
typu float
za pomocą std::stof
(od ang.: string to float):
- 🔵 std::stoi
- 🟣 std::stof
std::string number_in_str = "53";
int number = std::stoi(number_in_str);
std::string number_in_str = "53.5"; // w tekście nie podajemy `f` na końcu
float number = std::stof(number_in_str);
Podsumowanie
W tej lekcji dowiedzieliśmy się o typie std::string
, który służy do przechowywania i manipulowania sekwencjami znaków.
Zobacz następujące podlekcje, aby zapoznać się lepiej z łańcuchami znaków: