Pasar de char* a string pérdida de datos

Iniciado por Kaxperday, 6 Noviembre 2015, 11:01 AM

0 Miembros y 1 Visitante están viendo este tema.

Kaxperday

Si char* tiene un caracter nulo en mitad de la secuencia al construir la string se corta allí:

Código (cpp) [Seleccionar]
char *e = "aisjiajisfj\0buenas";
cout << string(e);


Y pierdo el poder convertir el char* en string, ¿no hay alguna solución para poderlo hacer?.

Saludos.

Bueno, quizás si nos aseguramos de lo que vamos a leer no contiene caracteres nulos hasta el final.
Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.

class_OpenGL

#1
Lo que delimita el tamaño de una cadena de caracteres es precisamente el carácter nulo. Si no hubiera un carácter nulo, entonces no sabríamos cual es el tamaño de la cadena. Entonces, cuando un objeto de tipo std::string toma los datos, lo hace hasta que encuentra un carácter nulo (repito, no hay otra forma segura de hacerlo). Lo único que puedes hacer es saber a ciencia cierta el tamaño de la cadena (el tamaño podría estar almacenado en una variable, por ejemplo). Una vez sabido esto, podrías reemplazar todos los caracteres nulos por otro carácter a tu elección:

Código (cpp) [Seleccionar]
std::string cString;
char *lpbyData = "aisjiajisfj\0buenas";
size_t nNumCharacters = 19; // No contamos el carácter nulo del final

for(size_t i = 0; i < nNumCharacters; i++ {
   if(lpbyData[i] == '\0')
       lpbyData[i] = '~'; // Pon el carácter de tu elección
}

cString = lpbyData;

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL

Kaxperday

Cita de: class_OpenGL en  6 Noviembre 2015, 12:10 PMUna vez sabido esto, podrías reemplazar todos los caracteres nulos por otro carácter a tu elección

Es lo que pensé pero podría fallar, ya que lo que hago es cifrar un archivo donde escribo bytes (u_char*), para llamar a write de ofstream debo usar un char* entonces hago la conversión, pero si algún byte vale nulo, valdrá \0 en la conversión y me cortará la cadena, podría sustiruirlo por otro carácter, aunque al final creo que lo mejor es usar fwrite.

Y aprovecho para preguntar si alguien conoce alguna clase de C++ para escribir bytes, ya que ofstream.write() en teoria es solo para char*. Y se corta en el primer carácter nulo.

Un saludo.
Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.

class_OpenGL

Entonces, lo único que se me ocurre es que almacenes la cadena en un vector de chars:

Código (cpp) [Seleccionar]
std::vector<char> cData;
const char *lpbyData = "aisjiajisfj\0buenas";
size_t uNumCharacters = 19;

cData.reserve(uNumCharacters);

for(int i = 0; i < uNumCharacters; i++) {
    cData[i] = lpbyData[i];
}

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL

ivancea96

string no se basa siempre en los caracteres nulos para iniicalizarse mediante un puntero a char.
string tiene un constructor que recibe como primer parámetro el puntero a char, y como segundo parámetro la longitud de la cadena. Es uno de los constructores posibles cuando se trabaja con cadenas de datos binarios.

Kaxperday

#5
Si pero luego al llamar a c_str() se cortará en el primer \0 ¿no?, luego no habría valido para nada.

Código (cpp) [Seleccionar]

struct datos{u_char *contenido; int tamaño;};//vector<u_char>

void almacen::escribir(datos _datos)
{
ofstream archivo;
archivo.open(directorio, ofstream::app | ofstream::binary);
_datos = encriptador.encriptar_AES(_datos);
archivo.write(reinterpret_cast<char*>(_datos.contenido), _datos.tamaño);
//archivo.write(string((char*)_datos.contenido, _datos.tamaño).c_str(), _datos.tamaño);
archivo.close();
}


Ahí dejo el code problemático.

Saludos.

Edito: lo que dice ivancea es verdad gracias por la informacion del constructor, pero al pasar a c_str() se corta en la primera \0 como es de esperar, luego para escribir bytes con ofstream.write() no podemos hacerlo, puesto que necesitamos char* y si hay algun byte nulo se nos cortara la cadena.

Seguramente pase a fwrite.

Saludos.
Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.

ivancea96

c_str() retorna la cadena completa. Y size() retorna el tamaño de la cadena. Así pues, no, no corta nada. Pero eso sí, si trabajar con cadenas binarias, trabajas siempre con métodos para ese tipo de cadenas. ni ostream::operator<<, ni strlen, ni otras funciones o métodos que se valgan de '\0' directa o indirectamente para determinar la longitud de la cadena.
Lo único que hace c_str(), al igual que data() a partir de C++11, es agregar un caracter nulo al final, siendo el tamaño real de la cadena devuelta de size()+1. Pero si trabajas con datos binarios, ese caracter nulo final es suplerfluo.

Kaxperday

Buenas socio, me recomiendas usar fwrite y fread para trabajar con bytes en C++, ¿o conoces algo mejor?.

Por lo que has dicho, ¿esto no se cortaría?:

Código (cpp) [Seleccionar]
string cadena = reinterpret_cast<char*>(_datos.contenido);
archivo.write(cadena.c_str(), cadena.size());


?? Saludos.
Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.

ivancea96

Cita de: Kaxperday en  8 Noviembre 2015, 12:14 PM
Buenas socio, me recomiendas usar fwrite y fread para trabajar con bytes en C++, ¿o conoces algo mejor?.

Por lo que has dicho, ¿esto no se cortaría?:

Código (cpp) [Seleccionar]
string cadena = reinterpret_cast<char*>(_datos.contenido);
archivo.write(cadena.c_str(), cadena.size());


?? Saludos.

Estás construyendo mal la string. Estás construyendola pasándole solo un char*.

Citarstring tiene un constructor que recibe como primer parámetro el puntero a char, y como segundo parámetro la longitud de la cadena. Es uno de los constructores posibles cuando se trabaja con cadenas de datos binarios.


Kaxperday

Ah si perdon, se me escapó, pero si la construyo con 2 argumentos (char*, tamaño) pasa lo mismo, pues el c_str() corta al primer \0, aunque le digamos escribe 50 char, cuando el write encuentra el primer \0 deja de escribir ¿no?.

Saludos.
Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.