Problema con memcpy() [SOLUCIONADO]

Iniciado por SARGE553413, 22 Noviembre 2013, 16:05 PM

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

SARGE553413

Hola a todos.

Tengo un vector de punteros a char.
Quiero leer todas las líneas de un fichero y almacenar cada una de ellas en cada componente de mi vector de punteros.
No conozco a priori el tamaño del fichero.

El problema es que, no se por qué, al redimensionar el vector de punteros voy perdiendo las cadenas almacenadas. Este es mi código:


#define readErr(ifs) ifs.rdstate() & ifstream::failbit

char ** readFich(ifstream &ifs,const int &BUFFER_S){
char line[BUFFER_S];
char **dev=new char*[1],**aux=NULL;
//dev = vector de strings donde almaceno cada linea del texto.
//aux = var. auxiliar para apuntar a dev mientras ésta es redimensionada.
int i=1;
//leo línea
ifs.getline(line,BUFFER_S);
       //la copio en el vector
       dev[i]=new char[BUFFER_S];
       strcpy(dev[i],line);
       while(!ifs.eof()){
       //Compruebo que no hay errores, si los hay, salgo del bucle.
       if (readErr(ifs)!= 0){
           cout<<"ERROR: INTENTANDO LEER MAS DE 256 CARACTERES"<<endl;
           break;
       }else{
           //libero la memoria a la que apuntaba aux
           delete[] aux;
           //salvo la direcc. de memoria de dev
           aux=dev;
           //redimensiono dev
           dev=new char*[i+1];
           //le paso los datos que tenia hasta ahora
           memcpy(dev,aux,sizeof(aux));
           //le asigno la nueva linea
           dev[i]=new char[BUFFER_S];
           strcpy(dev[i],line);
           //vuelvo a leer
           ifs.getline(line, BUFFER_S);
       }
       i++;
   }
   return dev;
}


No entiendo cual es el problema, ¿Qué puedo hacer?

Muchas gracias

rir3760

Cita de: SARGE553413 en 22 Noviembre 2013, 16:05 PMTengo un vector de punteros a char.
Quiero leer todas las líneas de un fichero y almacenar cada una de ellas en cada componente de mi vector de punteros.
No conozco a priori el tamaño del fichero.

El problema es que, no se por qué, al redimensionar el vector de punteros voy perdiendo las cadenas almacenadas.
Cuando utilizas el operador new este reserva un bloque de memoria del tamaño apropiado, nada mas. El problema es que tu esperas que copie el contenido del bloque anterior y eso no lo hará el operador. Debes hacerlo manualmente reservando un nuevo bloque de memoria, copiando en el las direcciones de memoria y finalmente liberando el bloque original (y utilizando a partir de ese momento el nuevo bloque).

Cita de: SARGE553413 en 22 Noviembre 2013, 16:05 PM¿Qué puedo hacer?
Ya que el lenguaje es C++ es mejor utilizar un vector de objetos de tipo string para almacenar todas las lineas del archivo, con ello te liberas del manejo de memoria.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

SARGE553413

Cita de: rir3760 en 22 Noviembre 2013, 18:29 PM
Cuando utilizas el operador new este reserva un bloque de memoria del tamaño apropiado, nada mas. El problema es que tu esperas que copie el contenido del bloque anterior y eso no lo hará el operador. Debes hacerlo manualmente reservando un nuevo bloque de memoria, copiando en el las direcciones de memoria y finalmente liberando el bloque original (y utilizando a partir de ese momento el nuevo bloque).
Sí, lo sé, de hecho en el código que he escrito lo hago explicitamente con una variable auxiliar y memcpy(), por eso no entiendo que pasa.

Citar
Ya que el lenguaje es C++ es mejor utilizar un vector de objetos de tipo string para almacenar todas las lineas del archivo, con ello te liberas del manejo de memoria.
Cierto, pero esto no me lo permiten hacer usando la STL, tengo que manejar la memoria directamente. Además es algo que quiero entender como funciona.

SARGE553413

He estado haciendo mas pruebas y sustituyendo la parte del memcpy() por un bucle for todo funciona bien.


//Antes:
            //vuelvo a leer
            ifs.getline(line, BUFFER_S,'\n');
            //salvo la direcc. de memoria de dev
            aux=dev;
            //redimensiono dev
            dev=new char*[i+2];
            //le paso los datos que tenia hasta ahora
            memcpy(dev,aux,sizeof(aux));
            //le asigno la nueva linea
            dev[i]=new char[BUFFER_S];
            strcpy(dev[i],line);
            //libero la memoria a la que apuntaba aux
            delete[] aux;

//Después:
            //vuelvo a leer
            ifs.getline(line, BUFFER_S,'\n');
            //salvo la direcc. de memoria de dev
            aux=dev;
            //redimensiono dev
            dev=new char*[i+2];
            //le paso los datos que tenia hasta ahora
            for(int j=0;j<i;j++){
                dev[j]=aux[j];
            }
            //le asigno la nueva linea
            dev[i]=new char[BUFFER_S];
            strcpy(dev[i],line);
            //libero la memoria a la que apuntaba aux
            delete[] aux;


Algo pasa con el memcpy(), ¿Qué es?

Saludos

SARGE553413

Solución:

En la parte en la que se especifica sizeof() en memcpy, hay que multiplicarlo por la cantidad de chars (en este caso) que se quieren copiar.

Esto es porque si tienes un vector de 20 caracteres 'char c[20]', sizeof(c) devuelve 4 (tamaño del puntero a char, que es lo que es en realidad el vector) no devuelve los 20 chars que contiene.

Saludos.