Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Yenifer22 en 17 Febrero 2022, 12:35 pm



Título: duda urgente sobre vector
Publicado por: Yenifer22 en 17 Febrero 2022, 12:35 pm
Hola,
Alguien me puede decir que esta mal en este codigo pues la lista al final esta llena en todas sus posiciones con el valor de la ultima fila del file.

      
Código:
 
        vector<char*> lista;
char* linea = new char[100];
int i = 0;

while (!feof(file))
{
fgets(linea, 50, file);
lista.push_back(linea);

}
//Cierro el archivo
fclose(file);


Título: Re: duda urgente sobre vector
Publicado por: K-YreX en 17 Febrero 2022, 22:01 pm
Es sencillo y complejo a la vez, veamos:
(Voy a dar por supuesto que tienes nociones básicas sobre punteros)

Aquí tengo mi lista en la que voy a guardar punteros char (char*):
Código:
lista = [] // la lista esta vacia

Ahora creo el puntero 'linea' y le asigno un espacio de 5 caracteres (pongo 5 para simplificarlo más):
Código:
linea = [_, _, _, _, _] // linea apunta a la direccion de memoria 0x1 (por ejemplo) 

Vamos a leer la primera línea del fichero: "Hola" y lo guardamos en 'linea' (recordemos: está en memoria 0x1):
Código:
linea = [H, o, l, a, \0] // Podemos obviar el \0 
Y ahora guardamos el puntero en la lista:
Código:
lista = [linea]
// Esto realmente es lo mismo que:
lista = [0x1] // Guardamos la dirección a la que esta apuntando el puntero 'linea'

Ahora leemos la segunda línea del fichero "Mundo" y lo guardamos en 'linea':
Código:
linea = [M, u, n, d, \0] // UPS! No cabe (no importa porque fgets() lo soluciona solito) 
Y lo guardamos en la lista de nuevo:
Código:
lista = [linea, linea]
// O lo que es lo mismo (seguro que ya has visto el problema):
lista = [0x1, 0x1]

Y ahora te muestro ambos elementos de la lista:
Código:
Elemento 0 -> Vamos a 0x1 y tenemos: [M, u, n, d, \0]
Elemento 1 -> Vamos a 0x1 y tenemos: [M, u, n, d, \0]

Parece que el "Hola" ha desaparecido (y así es).

Para solucionar esto tienes que reservar memoria para cada elemento que insertes en la lista para que cada uno esté en un espacio de memoria diferente y no se pisen unos elementos con otros
Esquematizado sería:
Código:
MIENTRAS !fin(fichero) HACER
  linea = leerLinea(fichero)
  lista.agregar(new char[SIZE])
  copiar(linea, lista[ultimoElemento])
FIN MIENTRAS
Recuerda copiar (strcpy()) el contenido del char* y no asignarlo sin más (=) pues sino te verás en las mismas.
Y cuando tu programa termine tendrás que liberar toda la memoria de la lista.

Un par de consejos extra:
  • Estás utilizando C++, por lo que puedes aprovechar el tipo string para facilitarte el trabajo con los char*.
  • Utiliza una constante para el tamaño del array y en el fgets() aprovecha el mismo tamaño. Para qué sino reservar un array de tamaño 100 si luego sólo vas a copiar como máximo 50 caracteres??
Código
  1. const int LINE_SIZE = 100;
  2.  
  3. int main() {
  4.  char* linea[LINE_SIZE]; // Puede ser estatico (mas sencillo)
  5.  //...
  6.  fgets(linea, LINE_SIZE, file);
  7.  char *nuevo_puntero = new char[strlen(linea) + 1]; // Puedes ahorrar espacio creando los arrays con la longitud justa necesaria
  8.  strcpy(nuevo_puntero, linea);
  9.  // Ahora ya puedes modificar 'linea' todo lo que quieras que no afectara a nuevo_puntero
  10. }