22,2 — std::string budowa i zniszczenie

W tej lekcji przyjrzymy się, jak konstruować obiekty std::string, a także jak tworzyć ciągi znaków z liczb i odwrotnie.

Konstrukcja ciągów

Klasy ciągów posiadają wiele konstruktorów, których można używać do tworzenia ciągów. Przyjrzymy się tutaj każdemu z nich.

Uwaga: string::size_type jest rozpoznawany na size_t, który jest tym samym typem całkowitym bez znaku, który jest zwracany przez operator sizeof. Rzeczywisty rozmiar size_t w zależności od środowiska. Na potrzeby tego samouczka wyobraź sobie, że jest to int bez znaku.

string::string()

  • To jest konstruktor domyślny. Tworzy pusty ciąg znaków.

Przykładowy kod:

std::string sSource;
std::cout << sSource;

Wyjście:

string::string(const string& strString)

  • To jest konstruktor kopiujący. Ten konstruktor tworzy nowy ciąg znaków jako kopię strString.

Przykładowy kod:

std::string sSource{ "my string" };
std::string sOutput{ sSource };
std::cout << sOutput;

Wyjście:

my string

string::string(const string& strString, size_type unIndex)
string::string(const string& strString, size_type unIndex, size_type unLength)

  • Ten konstruktor tworzy nowy ciąg znaków zawierający maksymalnie unLength znaków z strString, zaczynając od indeksu unIndex. Jeśli napotkana zostanie wartość NULL, kopiowanie łańcucha zakończy się, nawet jeśli unLength nie została osiągnięta.
  • Jeśli nie podano unLength, użyte zostaną wszystkie znaki rozpoczynające się od unIndex.
  • Jeśli unIndex jest większy niż rozmiar ciągu, zostanie zgłoszony wyjątek out_of_range.

Przykładowy kod:

std::string sSource{ "my string" };
std::string sOutput{ sSource, 3 };
std::cout << sOutput<< '\n';
std::string sOutput2(sSource, 3, 4);
std::cout << sOutput2 << '\n';

Wyjście:

string
stri

string::string(const char* szCString)

  • Ten konstruktor tworzy nowy ciąg znaków na podstawie łańcucha szCString w stylu C, aż do terminatora NULL, ale nie włączając.
  • Jeśli wynikowy rozmiar przekracza maksymalną długość łańcucha, zostanie zgłoszony wyjąteklength_error.
  • Ostrzeżenie: szCString nie może mieć wartości NULL.

Przykładowy kod:

const char* szSource{ "my string" };
std::string sOutput{ szSource };
std::cout << sOutput << '\n';

Wyjście:

my string

string::string(const char* szCString, size_type unLength)

  • Ten konstruktor tworzy nowy ciąg znaków z pierwszych znaków o mniejszej długości ciąg szCString w stylu C.
  • Jeśli wynikowy rozmiar przekracza maksymalną długość łańcucha, zostanie zgłoszony wyjąteklength_error.
  • Ostrzeżenie: Tylko w przypadku tej funkcji wartości NULL nie są traktowane jako znaki końca łańcucha w szCString! Oznacza to, że możliwe jest odczytanie końca łańcucha, jeśli wartość unLength jest zbyt duża. Uważaj, aby nie przepełnić bufora ciągów!

Przykładowy kod:

const char* szSource{ "my string" };
std::string sOutput(szSource, 4);
std::cout << sOutput << '\n';

Wyjście:

my s

string::string(size_type nNum, char chChar)

  • Ten konstruktor tworzy nowy ciąg znaków inicjowany przez nNum wystąpień znaku chChar.
  • Jeśli wynikowy rozmiar przekracza maksymalną długość łańcucha, zostanie zgłoszony wyjąteklength_error.

Przykładowy kod:

std::string sOutput(4, 'Q');
std::cout << sOutput << '\n';

Wyjście:

QQQQ

template string::string(InputIterator itBeg, InputIterator itEnd)

  • Ten konstruktor tworzy nowy ciąg znaków inicjowany znakami zakresu [itBeg, itEnd).
  • Jeśli wynikowy rozmiar przekracza maksymalną długość łańcucha, zostanie zgłoszony wyjąteklength_error.

Brak przykładowego kodu dla tego. Jest na tyle niejasny, że prawdopodobnie nigdy go nie użyjesz.

string::~string()

Niszczenie łańcucha

  • To jest destruktor. Niszczy ciąg znaków i zwalnia pamięć.

Nie ma tu również przykładowego kodu, ponieważ destruktor nie jest wywoływany jawnie.

Konstruowanie ciągów z liczb

Jedynym godnym uwagi pominięciem w klasie std::string jest brak możliwości tworzenia ciągów znaków z liczb. Na przykład:

    std::string sFour{ 4 };

Wywołuje następujący błąd:

c:vcprojectstest2test2test.cpp(10) : error C2664: 'std::basic_string<_Elem,_Traits,_Ax>::basic_string(std::basic_string<_Elem,_Traits,_Ax>::_Has_debug_it)' : cannot convert parameter 1 from 'int' to 'std::basic_string<_Elem,_Traits,_Ax>::_Has_debug_it'

Pamiętasz, co mówiłem o klasach łańcuchowych generujących okropnie wyglądające błędy? Odpowiednia informacja jest następująca:

cannot convert parameter 1 from 'int' to 'std::basic_string

Innymi słowy, próba przekonwertowania liczby typu int na ciąg znaków zakończyła się niepowodzeniem.

Najłatwiejszym sposobem przekonwertowania liczb na ciągi znaków jest użycie klasy std::ostringstream. std::ostringstream jest już skonfigurowany tak, aby akceptować dane wejściowe z różnych źródeł, w tym znaki, liczby, ciągi znaków itp. Jest także w stanie wysyłać ciągi znaków (albo za pomocą operatora ekstrakcji>>, albo za pomocą funkcji str()). Aby uzyskać więcej informacji na temat std::ostringstream, zobacz 28.4 — Klasy strumieniowe dla ciągów znaków.

Oto proste rozwiązanie do tworzenia std::string z różnych typów danych wejściowych:

#include <iostream>
#include <sstream>
#include <string>
 
template <typename T>
inline std::string ToString(T tX)
{
    std::ostringstream oStream;
    oStream << tX;
    return oStream.str();
}

Oto przykładowy kod do przetestowania:

int main()
{
    std::string sFour{ ToString(4) };
    std::string sSixPointSeven{ ToString(6.7) };
    std::string sA{ ToString('A') };
    std::cout << sFour << '\n';
    std::cout << sSixPointSeven << '\n';
    std::cout << sA << '\n';
}

A wynik:

4
6.7
A

Zauważ, że to rozwiązanie pomija sprawdzanie błędów. Możliwe, że wstawienie tX do oStream może się nie udać. Właściwą reakcją byłoby zgłoszenie wyjątku, jeśli konwersja się nie powiedzie.

Powiązana treść

Biblioteka standardowa zawiera również funkcję o nazwie std::to_string() , której można użyć do konwersji liczb na std::string. Chociaż jest to prostsze rozwiązanie w podstawowych przypadkach, wynik std::to_string może różnić się od wyniku std::cout lub naszej powyższej funkcji ToString(). Niektóre z tych różnic są obecnie udokumentowane tutaj.

Konwersja ciągów znaków na liczby

Podobnie jak w powyższym rozwiązaniu:

#include <iostream>
#include <sstream>
#include <string>
 
template <typename T>
inline bool FromString(const std::string& sString, T& tX)
{
    std::istringstream iStream(sString);
    return !(iStream >> tX).fail(); // extract value into tX, return success or not
}

Oto przykładowy kod do przetestowania:

int main()
{
    double dX;
    if (FromString("3.4", dX))
        std::cout << dX << '\n'; 
    if (FromString("ABC", dX))
        std::cout << dX << '\n'; 
}

A wynik:

3.4

Zauważ, że druga konwersja nie powiodła się i zwróciła wartość false.

guest
Twój adres e-mail nie zostanie wyświetlony
Znalazłeś błąd? Zostaw komentarz powyżej!
Komentarze związane z poprawkami zostaną usunięte po przetworzeniu, aby pomóc zmniejszyć bałagan. Dziękujemy za pomoc w ulepszaniu witryny dla wszystkich!
Awatary z https://gravatar.com/ są połączone z podanym adresem e-mail.
Powiadamiaj mnie o odpowiedziach:  
70 Komentarze
Najnowsze
Najstarsze Najczęściej głosowane
Wbudowane opinie
Wyświetl wszystkie komentarze