W tej chwili zaakceptowana odpowiedź od @jahhaj jest sprzeczna z odpowiedzią użytkownika529758, którego odpowiedź jest prawdopodobnie bardziej aktualna. Podczas lektury pominąłem komentarz Jessego Gooda, więc tutaj chcę podkreślić jego wagę.
Jonathan Komar
Odpowiedzi:
99
Nie, ale jeśli powiesz, że temp.c_str()w wyniku zwracanym z tej metody zostanie uwzględniony terminator zerowy.
Warto również powiedzieć, że możesz umieścić znak null w ciągu, tak jak każdy inny znak.
Jeśli zadzwonisz, temp.c_str()znak null zostanie uwzględniony. Jeśli naprawdę potrzebujesz tego w ciągu, po prostu dodaj go jak każdy inny znak. temp.push_back('\0'). Teraz temp.c_str()będzie zawierać dwa znaki null.
jahhaj
1
@dupdupdup, jak wspomniały niektóre odpowiedzi, jeśli potrzebujesz ciągu zakończonego znakiem null, powinieneś wywołać s.c_str () na skonstruowanym obiekcie. Zwróci wskaźnik do tablicy znaków, która ma na końcu '\ 0'.
Maksim Skurydzin
@Rico, Jahhaj Jak w takim razie zakończyć ciąg. Na przykład - dodałem kilka znaków do mojego ciągu jako str [i]. Teraz nie mogę go wydrukować za pomocą cout.
Bhavuk Mathur
Aby dodać do twojego punktu: Ponieważ operator << jest przeciążony, cout << s, chociaż wydrukuje cały łańcuch char po znaku, ale jeśli weźmiesz c_str () i wstawisz do operatora <<, wydrukuje do null char. następujący program przedstawia ten punkt. {string s ("SampleString"); cout << s.size () << "\ t" << s << endl; s [3] = '\ 0'; cout << "\ n \ n After Null \ n \ n" << s.size () << "\ t" << s << endl; cout << "\ n \ n Biorąc c_str \ n \ n" << s.size () << "\ t" << s.c_str () << endl; }
Fooo
70
Nie w C ++ 03 i nie jest nawet gwarantowane przed C ++ 11, że w C ++ std :: string jest ciągła w pamięci. Tylko ciągi C (tablice char, które są przeznaczone do przechowywania ciągów) miały terminator zerowy.
W C ++ 11 i nowszych mystring.c_str()wersjach mystring.data()jest równoważne jest równoważne &mystring[0]i mystring[mystring.size()]gwarantuje, że będzie '\0'.
Dzięki C ++ 11 ciągi są teraz gwarantowane jako ciągłe w pamięci.
zneak
@zneak thanks! Zaktualizowano. Ale wątpię, czy istnieją jakiekolwiek kompilatory kompilujące C ++ 11, które przynajmniej w rozsądnym zakresie ... nawet GCC ma zepsute wsparcie dla tego.
4
@ H2CO3: Pomijając C ++ 11, problem ten został rozwiązany w DR 530 w 2005 roku . Zdecydowana większość implementacji bibliotek standardowych przechowuje dane łańcuchowe w ciągłej pamięci przez co najmniej tak długo.
ildjarn
3
Dziękuję @ildjarn, właśnie tego szukałem. Po części uzasadnieniem posunięcia było to, że nikt w komitecie nie wiedział o implementacji STL, która nie używa pamięci ciągłej.
zneak
7
@ H2CO3: Szczerze, jeśli cię to uraziło, potrzebujesz grubszej skóry.
ildjarn
8
Zależy to od Twojej definicji „zawiera”. W
std::string temp = "hello whats up";
jest kilka rzeczy, na które należy zwrócić uwagę:
temp.size()zwróci liczbę znaków od pierwszego hdo ostatniego p(łącznie)
Ale w tym samym czasie temp.c_str()lub temp.data()powróci z nullterminatorem
Innymi słowy, int(temp[temp.size()])będzie wynosić zero
Wiem, brzmię podobnie do niektórych odpowiedzi tutaj, ale chcę zwrócić uwagę, że sizeof std::stringin C++jest utrzymywane osobno i nie jest tak, jak w Cprzypadku liczenia, dopóki nie znajdziesz pierwszego nullterminatora.
Aby dodać, historia byłaby trochę inna, gdyby string literalzawierała osadzone \0. W tym przypadku konstrukcja std::stringzatrzymuje się na pierwszym nullznaku, jak poniżej:
std::string s1 = "ab\0\0cd"; // s1 contains "ab", using string literalstd::string s2{"ab\0\0cd", 6}; // s2 contains "ab\0\0cd", using different ctrstd::string s3 = "ab\0\0cd"s; // s3 contains "ab\0\0cd", using ""s operator
Tak, jeśli zadzwonisz temp.c_str(), zwróci łańcuch c zakończony znakiem null.
Jednak rzeczywiste dane przechowywane w obiekcie tempmogą nie być zakończone znakiem null, ale nie ma to znaczenia i nie powinno mieć znaczenia dla programisty, ponieważ gdy programista tego chce const char*, wywołuje c_str()obiekt, który gwarantuje zwrócenie wartości null -terminated string.
Ani terminator zerowy (jeśli istnieje) nie zostanie uwzględniony w powrocie z temp.size().
jahhaj
1
W przypadku ciągów C ++ nie musisz się o to martwić i prawdopodobnie zależy to od implementacji.
Używając temp.c_str()otrzymasz reprezentację napisu w C, która z pewnością będzie zawierała \0znak. Poza tym tak naprawdę nie widzę, jak byłoby to przydatne w łańcuchu C ++
std::stringwewnętrznie liczy liczbę znaków. Wewnętrznie działa przy użyciu tej liczby. Jak powiedzieli inni, kiedy potrzebujesz łańcucha do wyświetlenia lub z jakiegokolwiek powodu, możesz użyć jego c_str()metody, która da ci łańcuch z zakończeniem zerowym na końcu.
Czy możesz podać jakieś odniesienia do tej instrukcji, "std :: string wewnętrznie przechowuje liczbę znaków. Wewnętrznie działa przy użyciu tej liczby"
Odpowiedzi:
Nie, ale jeśli powiesz, że
temp.c_str()
w wyniku zwracanym z tej metody zostanie uwzględniony terminator zerowy.Warto również powiedzieć, że możesz umieścić znak null w ciągu, tak jak każdy inny znak.
string s("hello"); cout << s.size() << ' '; s[1] = '\0'; cout << s.size() << '\n';
wydruki
5 5
a nie
5 1
tak, jak można by się spodziewać, gdyby znaki puste miały specjalne znaczenie dla łańcuchów.źródło
temp.c_str()
znak null zostanie uwzględniony. Jeśli naprawdę potrzebujesz tego w ciągu, po prostu dodaj go jak każdy inny znak.temp.push_back('\0')
. Teraztemp.c_str()
będzie zawierać dwa znaki null.Nie w C ++ 03 i nie jest nawet gwarantowane przed C ++ 11, że w C ++ std :: string jest ciągła w pamięci. Tylko ciągi C (tablice char, które są przeznaczone do przechowywania ciągów) miały terminator zerowy.
W C ++ 11 i nowszych
mystring.c_str()
wersjachmystring.data()
jest równoważne jest równoważne&mystring[0]
imystring[mystring.size()]
gwarantuje, że będzie'\0'
.źródło
Zależy to od Twojej definicji „zawiera”. W
std::string temp = "hello whats up";
jest kilka rzeczy, na które należy zwrócić uwagę:
temp.size()
zwróci liczbę znaków od pierwszegoh
do ostatniegop
(łącznie)temp.c_str()
lubtemp.data()
powróci znull
terminatoremint(temp[temp.size()])
będzie wynosić zeroWiem, brzmię podobnie do niektórych odpowiedzi tutaj, ale chcę zwrócić uwagę, że
size
ofstd::string
inC++
jest utrzymywane osobno i nie jest tak, jak wC
przypadku liczenia, dopóki nie znajdziesz pierwszegonull
terminatora.Aby dodać, historia byłaby trochę inna, gdyby
string literal
zawierała osadzone\0
. W tym przypadku konstrukcjastd::string
zatrzymuje się na pierwszymnull
znaku, jak poniżej:std::string s1 = "ab\0\0cd"; // s1 contains "ab", using string literal std::string s2{"ab\0\0cd", 6}; // s2 contains "ab\0\0cd", using different ctr std::string s3 = "ab\0\0cd"s; // s3 contains "ab\0\0cd", using ""s operator
Bibliografia:
źródło
Tak, jeśli zadzwonisz
temp.c_str()
, zwróci łańcuch c zakończony znakiem null.Jednak rzeczywiste dane przechowywane w obiekcie
temp
mogą nie być zakończone znakiem null, ale nie ma to znaczenia i nie powinno mieć znaczenia dla programisty, ponieważ gdy programista tego chceconst char*
, wywołujec_str()
obiekt, który gwarantuje zwrócenie wartości null -terminated string.źródło
temp.size()
.W przypadku ciągów C ++ nie musisz się o to martwić i prawdopodobnie zależy to od implementacji.
Używając
temp.c_str()
otrzymasz reprezentację napisu w C, która z pewnością będzie zawierała\0
znak. Poza tym tak naprawdę nie widzę, jak byłoby to przydatne w łańcuchu C ++źródło
std::string
wewnętrznie liczy liczbę znaków. Wewnętrznie działa przy użyciu tej liczby. Jak powiedzieli inni, kiedy potrzebujesz łańcucha do wyświetlenia lub z jakiegokolwiek powodu, możesz użyć jegoc_str()
metody, która da ci łańcuch z zakończeniem zerowym na końcu.źródło