Чи містить std :: рядок нульовий термінатор?


87

Чи міститиме нижченаведений рядок нульовий термінатор '\ 0'?

std::string temp = "hello whats up";

Дякую! :)



1
На даний момент прийнята відповідь від @jahhaj суперечить відповіді користувача user529758, відповідь якого, можливо, є більш сучасною. Переглядаючи, я пропустив коментар Джессі Гуда, тому це тут, щоб підкреслити його важливість.
Джонатан Комар,

Відповіді:


99

Ні, але якщо ви скажете, що temp.c_str()до повернення від цього методу буде включено нульовий термінатор.

Також варто сказати, що ви можете включити в рядок нульовий символ, як і будь-який інший символ.

string s("hello");
cout << s.size() << ' ';
s[1] = '\0';
cout << s.size() << '\n';

відбитки

5 5

а не так, 5 1як можна було б очікувати, якби нульові символи мали особливе значення для рядків.


5
При виклику temp.c_str()буде включено нульовий символ. Якщо вам це дійсно потрібно у рядку, просто додайте його як будь-який інший символ. temp.push_back('\0'). Тепер temp.c_str()буде включати два нульові символи.
jahhaj

1
@dupdupdup, як згадували деякі відповіді, якщо вам потрібен рядок із нульовим закінченням, ви повинні викликати s.c_str () для побудованого об'єкта. Він поверне вказівник на масив символів, який гарантовано матиме "\ 0" в кінці.
Максим Скуридзін

@Rico, Jahhaj Як тоді закінчити рядок. Наприклад, - я додав кілька символів до свого рядка як str [i]. Тепер я не можу надрукувати його за допомогою cout.
Bhavuk Mathur

Щоб додати до вашої точки: Оскільки оператор << перевантажений так, cout << s, хоч і надрукує повний рядок char символом char, але якщо взяти c_str () і поставити оператора <<, він буде друкувати до нульовий символ. наступна програма відповідає цій точці. {рядок s ("SampleString"); cout << s.size () << "\ t" << s << endl; s [3] = '\ 0'; cout << "\ n \ n Після Null \ n \ n" << s.size () << "\ t" << s << endl; cout << "\ n \ n Беручи c_str \ n \ n" << s.size () << "\ t" << s.c_str () << endl; }
Fooo 02

70

Не в C ++ 03, і ​​навіть не гарантовано до C ++ 11, що в C ++ std :: string є безперервним в пам'яті. Тільки рядки C (масиви символів, призначені для зберігання рядків) мали нульовий термінатор.

У C ++ 11 та пізніших версіях mystring.c_str()еквівалент mystring.data()є еквівалент &mystring[0]і mystring[mystring.size()]гарантовано '\0'.


4
З C ++ 11 рядки гарантовано будуть суміжними в пам'яті.
zneak

@zneak дякую! Оновлено. Але я сумніваюся, що існують хоча б розумно компілятивні компілятори C ++ 11 ... навіть GCC порушила підтримку.

4
@ H2CO3: C ++ 11 в сторону, це було розглянуто в DR 530 у 2005 році . Переважна більшість стандартних реалізацій бібліотеки зберігають дані рядків у суміжній пам'яті принаймні стільки часу.
ildjarn

3
Дякую @ildjarn, я саме це шукав. Частково обгрунтуванням цього кроку було те, що ніхто в комітеті не знав про реалізацію STL, яка не використовувала безперервну пам’ять.
zneak

7
@ H2CO3: Чесно кажучи, якщо це вас образило, вам потрібна товста шкіра.
ildjarn

8

Це залежить від вашого визначення поняття "містити" тут. В

std::string temp = "hello whats up";

є кілька речей, на які слід звернути увагу:

  • temp.size()поверне кількість символів від першого hдо останнього p(обидва включно)
  • Але в той же час temp.c_str()або temp.data()повернеться з nullтермінатором
  • Або іншими словами int(temp[temp.size()])буде дорівнювати нулю

Я знаю, я звук , схожий на деякі з відповідей тут , але я хочу відзначити, що sizeз std::stringв C++це підтримується окремо , і це не так, як в , Cде ви зберігаєте підрахунок , якщо ви не знайдете перший nullтермінатор.

Додамо, історія буде дещо іншою, якщо ваш string literalвміст буде вбудованим \0. У цьому випадку побудова std::stringзупинок на першому nullсимволі, як показано нижче:

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

Список літератури:


2

Так, якщо ви зателефонуєте temp.c_str(), він поверне нульовий термін c-string.

Однак фактичні дані, що зберігаються в об'єкті, tempможуть не закінчуватися нулем, але це не має значення і не повинно мати значення для програміста, оскільки тоді, коли програміст захоче const char*, він буде викликати c_str()об'єкт, який гарантовано поверне null -кінчена рядок.


1
Також нульовий термінатор (якщо він існує) не буде включений у повернення від temp.size().
jahhaj

1

З рядками C ++ вам не доведеться турбуватися про це, і це, можливо, залежить від реалізації.

Використовуючи temp.c_str()ви отримуєте подання рядка C, яке обов’язково міститиме \0символ. Окрім цього, я насправді не бачу, як це було б корисно для рядка C ++


1

std::stringвнутрішньо веде підрахунок кількості символів. Внутрішньо це працює, використовуючи цей підрахунок. Як сказали інші, коли вам потрібен рядок для відображення або з якоїсь іншої причини, ви можете його c_str()метод, який дасть вам рядок із нульовим термінатором в кінці.


Чи можете ви дати деякі посилання на цей вислів, "std :: string внутрішньо веде підрахунок кількості символів. Внутрішньо він працює, використовуючи цей підрахунок"
rimalonfire
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.