2010-05-16 18 views
31

Para las cadenas C normales, un carácter nulo '\0' significa el final de los datos.¿Puede una cadena std :: contener nulos incorporados?

¿Qué pasa con std::string, puedo tener una cadena con caracteres nulos incrustados?

+1

Ver [std :: string equivalente para datos con caracteres NULL?] (Http://stackoverflow.com/questions/1534335/stdstring-equivalent-for-data-with-null-characters) –

Respuesta

32

Sí puede tener nulos incrustados en su std::string.

Ejemplo:

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

Nota: std::string 's c_str() miembro siempre anexar un carácter nulo al char buffer devuelto; Sin embargo, el miembro std::stringdata() puede o no agregar un carácter nulo al búfer char devuelto.

Tenga cuidado del operador + =

Una cosa a tener en cuenta es no utilizar operator+= con un char* en el lado derecho. Solo se sumará hasta el carácter nulo.

Por ejemplo:

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

La forma correcta:

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

Almacenamiento de datos binarios más común el uso de std :: vector

lo general, es más común el uso std::vector a almacenar datos binarios arbitrarios.

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

es probablemente más común, ya que std::string 's data() y c_str() elementos de retorno punteros const lo que la memoria no es modificable. con & buf.front() puede modificar directamente el contenido del búfer.

+2

En C++ 9x '& s.front()' también se puede modificar y se garantiza que apunta a un búfer contiguo. Si bien no existía dicha garantía en C++ 03, no hay implementaciones conocidas de C++ para las cuales no era cierto en la práctica (que es en parte la razón por la cual se agregó a C++ 0x tan rápidamente). –

+6

Tenga en cuenta que a partir de C++ 11, '.c_str()' y '.data' son sinónimos. En particular, esto significa que la cadena devuelta por '.data' debe tener un terminador nulo adjunto. – nneonneo

+0

@PavelMinaev: Supongo que "C++ 9x" fue un error tipográfico para "C++ 0x" (que se convirtió en C++ 11 después de publicar su comentario). –

-1

Sí, esto es válido.

Puede tener un carácter nulo en el medio de la cadena.

Sin embargo, si se utiliza un std :: string con un carácter nulo en el medio con la cadena AC función estás en la ciudad comportamiento no definido - y nadie quiere estar ahí !!!:

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

'strlen' solo devolver el número de caracteres antes del primer nulo. Puede ser un comportamiento no anticipado, pero no está indefinido. –

8

Sí. Una std :: string es solo un vector<char> con beneficios.

Sin embargo, tenga cuidado acerca de pasar una bestia a algo que llama .c_str() y se detiene en la 0.

+0

El primero no es cierto, como aprendí recientemente. El intercambio de vectores conserva los iteradores y las referencias a los contenidos, las cadenas no son necesariamente. http://stackoverflow.com/questions/25201758/stringswap-complexity-under-visual-studio – Notinlist

+0

@Notinlist: ¡También tiene un nombre diferente! Oh, el horror –

1

Se puede, pero ¿por qué querrías? Incrustar NUL en std :: string es solo un problema, porque las funciones a las que pasas std :: string pueden usar su miembro c_str(), y la mayoría supondrá que el primer NUL indica el final de la cadena. Por lo tanto, esta no es una buena idea para hacer. También tenga en cuenta que en UTF-8, solo '\ 0' dará como resultado un 0, por lo que incluso para propósitos i18n, no hay justificación para incrustar NUL.

+0

Gracias por explicar por qué * no * para hacerlo. – Snoopy

+1

No, es tonto. "No use el rango completo de la funcionalidad de' std :: string', porque _puede pasar el resultado de 'c_str()' a las funciones de C-string sin pasar también una longitud ", ¿en serio? Bueno, si nunca haces eso, estarás bien ... –

Cuestiones relacionadas