2010-05-16 4 views
31

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

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

+1

См. [Std :: string-эквивалент для данных с NULL-символами?] (Http://stackoverflow.com/questions/1534335/stdstring-equivalent-for-data-with-null-characters) –

ответ

32

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

Пример:

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

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

Будьте осторожны оператора + =

Одна вещь, чтобы смотреть на это, чтобы не использовать 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<char> buf; 
buf.resize(1024); 
char *p = &buf.front(); 

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

+2

В C++ 9x '& s.front()' также может быть изменен и гарантированно указывать на непрерывный буфер. Хотя в C++ 03 не было такой гарантии, не существует известных реализаций C++, для которых она не выполнялась на практике (отчасти это было добавлено в C++ 0x так быстро). –

+6

Обратите внимание, что с C++ 11 '.c_str()' и '.data' являются синонимами. В частности, это означает, что строка, возвращаемая '.ata ', должна иметь добавленный нулевой ограничитель. – nneonneo

+0

@PavelMinaev: Я предполагаю, что «C++ 9x» был опечаткой для «C++ 0x» (который стал C++ 11 через некоторое время после того, как вы отправили свой комментарий). –

-1

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

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

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

int n = strlen(strWithNullInMiddle.c_str()); // Boom!!! 
+12

'strlen' будет просто вернуть число символов до первого значения null. Это может быть непредвиденное поведение, но это не является неопределенным. –

8

Да. Строка std :: это всего лишь vector<char> с преимуществами.

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

+0

Первое не так, как я недавно узнал. Смена вектора сохраняет итераторы и ссылки на содержимое, строка не обязательно. http://stackoverflow.com/questions/25201758/stringswap-complexity-under-visual-studio – Notinlist

+0

@Notinlist: У него другое имя! О, ужас –

1

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

+0

Спасибо за объяснение, почему * не *, чтобы это сделать. – Snoopy

+1

Нет, это глупо. Msgstr "Не использовать весь диапазон функций' std :: string', потому что вы _might_ передаете результат 'c_str()' в функции C-строки без передачи длины ", действительно? Ну, если ты этого не сделаешь, с тобой все будет хорошо ... –

Смежные вопросы