Может ли std::string содержать встроенные нули?

Для обычных строк C нулевой символ '\0' означает конец данных.

Как насчет std::string, могу ли я иметь строку со встроенными нулевыми символами?


person WilliamKF    schedule 16.05.2010    source источник
comment
См. эквивалент std::string для данных с символами NULL?   -  person Matthew Flaschen    schedule 17.05.2010


Ответы (4)


Да, вы можете иметь встроенные нули в свой std::string.

Пример:

std::string s;
s.push_back('\0');
s.push_back('a');
assert(s.length() == 2);

Примечание. Член c_str() std::string всегда будет добавлять нулевой символ к возвращаемому буферу char; Однако элемент data() std::string может добавлять или не добавлять нулевой символ к возвращаемому буферу char.

Осторожно с оператором +=

Одна вещь, на которую следует обратить внимание, это не использовать operator+= с char* на правой стороне. Он будет складываться только до нулевого символа.

Например:

std::string s = "hello";
s += "\0world";
assert(s.length() == 5);

Правильный способ:

std::string s = "hello";
s += std::string("\0world", 6);
assert(s.length() == 11);

Для хранения двоичных данных чаще используется std::vector

Обычно чаще используется std::vector для хранения произвольных двоичных данных.

std::vector<char> buf;
buf.resize(1024);
char *p = &buf.front();

Это, вероятно, более распространено, поскольку члены data() и c_str() std::string возвращают константные указатели, поэтому память нельзя изменить. с помощью &buf.front() вы можете напрямую изменять содержимое буфера.

person Brian R. Bondy    schedule 16.05.2010
comment
В C++9x &s.front() также изменяемо и гарантированно указывает на непрерывный буфер. Хотя в C++03 такой гарантии не было, нет известных реализаций C++, для которых она не выполнялась бы на практике (отчасти поэтому она так быстро была добавлена ​​в C++0x). - person Pavel Minaev; 23.07.2010
comment
Обратите внимание, что в C++11 .c_str() и .data являются синонимами. В частности, это означает, что к строке, возвращаемой .data, должен быть добавлен завершающий нуль. - person nneonneo; 07.02.2013
comment
@PavelMinaev: Я предполагаю, что C++9x был опечаткой для C++0x (который стал C++11 через некоторое время после того, как вы разместили свой комментарий). - person Keith Thompson; 04.11.2015
comment
s.append("\0world", 6); лучше, чем s += std::string("\0world", 6); - person n.caillou; 11.12.2017

да. std::string — это просто vector<char> с преимуществами.

Однако будьте осторожны с передачей такого зверя чему-то, что вызывает .c_str() и останавливается на 0.

person bmargulies    schedule 16.05.2010
comment
Первое неверно, как я недавно узнал. Замена вектора сохраняет итераторы и ссылки на содержимое, строки не обязательно. stackoverflow.com/questions/25201758/ - person Notinlist; 12.08.2014
comment
@Notinlist: у него тоже другое имя! о ужас - person Lightness Races in Orbit; 21.05.2017

Вы можете, но зачем вам это? Встраивание NUL в std::string просто напрашивается на неприятности, потому что функции, которым вы передаете std::string, вполне могут использовать его член c_str(), и большинство предположит, что первый NUL указывает на конец строки. Следовательно, это не очень хорошая идея. Также обратите внимание, что в UTF-8 только '\0' приведет к 0, поэтому даже для целей i18n нет никаких оснований для встраивания NUL.

person Michael Aaron Safyan    schedule 16.05.2010
comment
Спасибо за объяснение, почему нельзя этого делать. - person Snoop; 13.03.2017
comment
Нет, это глупо. Не используйте весь спектр функций std::string, потому что вы можете передать результат c_str() функциям C-строки без передачи длины, правда? Ну, если ты никогда этого не сделаешь, все будет в порядке... - person Lightness Races in Orbit; 21.05.2017

Да, это действительно.

Вы можете иметь нулевой символ в середине строки.

Однако, если вы используете std::string с нулевым символом в середине со строковой функцией c, вы находитесь в городе с неопределенным поведением - и никто не хочет быть там !!!:

 int n = strlen( strWithNullInMiddle.c_str() ); // Boom!!!
person Robben_Ford_Fan_boy    schedule 16.05.2010
comment
strlen просто вернет количество символов до первого нуля. Это может быть непредвиденным поведением, но оно не является неопределенным. - person Matthew Flaschen; 17.05.2010