[C con Clase] Duda para almacenar datos leidos desde un archivo

Davidson, Steven srd4121 en njit.edu
Sab Ene 26 23:52:01 CET 2013


Hola Gabriel,

2013/1/26 Gabriel Casarsa <gabriel_casarsa en yahoo.com.ar>

> Hola, tengo un problema al que no encuentro solucion. Yo tengo creado un
> archivo de acceso aleatorio.
>
> No vale la pena ahondar demasiado en lo que hace el programa en si.
> Leo bien todos los datos, pero a la hora de almacenarlos, tengo un error.
> Apenas iniciado el for, guardo en una variable char una palabra. Esta
> palabra le guardo en la posicion j=0 de una variable char*.
> Cuando guardo la siguiente iteración, me la guarda tanto en la posicion 0
> como en la j=1.
> O sea, al final de las 9 iteraciones, me queda el vector char* zonas[9]
> con 9 datos idénticos.
>

El problema tiene que ver con que estás guardando punteros y no los datos
en sí; es decir, guardas las direcciones de memoria de la información. Lo
explico más abajo en el código fuente.

Veámoslo.

#ifndef _HISTORIAL_H_
> #define _HISTORIAL_H_
> #include <stdio.h>
> #include <string.h>
> #include <stdlib.h>
>
> void historial(){
>  FILE *ptrdel;
> char archivodelitos[] = "delitos.txt";
> char cadena[20];
> char fecha[20];
> char hora[20];
> char alarma[2];
>  char *alarmas[9] = {0};
> char zona[2];
>  char *zonas[9] = {0};
> char delito[20];
>
> char *delitos[54] = {0};
>
> int i = 0; int d = 0; int j = 0;
> ptrdel = fopen(archivodelitos, "r");
>
> fseek(ptrdel,0,SEEK_SET);
>
> fscanf (ptrdel, "%s", cadena) != EOF;
>

Esto es gramaticalmente correcto, pero no tiene sentido. Me imagino que
quieres comprobar si no has llegado al final del fichero. Para esto, usa
'feof()', pero necesitas usar 'if' para tomar decisiones en la lógica del
programa. Por ejemplo,

fscanf( ptrdel, "%s", cadena );
if( !feof(ptrdel) )
{
  ...
}

strcpy(fecha,cadena);
> fscanf (ptrdel, "%s", cadena) != EOF;
> strcpy(hora,cadena);
>
> for(j=0;j<9;j++,z++){
>

No usas 'z', ni tampoco la declaraste previamente. Supongo que se te olvidó
eliminar del código que nos enviaste.

   fscanf (ptrdel, "%s", cadena) != EOF;
>    strcpy(zona,cadena);
>

Esto es peligroso, porque 'zona' es un array de 2 'char', mientras 'cadena'
es un array de 20 'char'. Esto significa que posiblemente se copien más
caracteres en 'zona' que pueda almacenar, por lo que rebasaría la memoria
reservada para 'zona', peligrando la estabilidad del programa.

   zonas[j] = zona;
>    fscanf (ptrdel, "%s", cadena) != EOF;
>    strcpy(alarma,cadena);
>

Aquí tienes el mismo problema de antes: 'alarma' es de 2 'char', mientras
que 'cadena' puede contener más, y por tanto la copia puede resultar
peligrosa para el programa.

   alarmas[j] = alarma;
>    while(strcmp(cadena,",")!=0){
>        if (strcmp(cadena,",")!=0){
>        fscanf (ptrdel, "%s", cadena) != EOF;
>        strcpy(delito,cadena);
>        delitos[d] = delito;
>        d++;
>

Cuidado con usar 'd' como índice sin limitar su valor en este bucle, ya que
puede rebasar el intervalo válido de índices. Deberías comprobar el valor
de 'd' en la condición del bucle 'while'.

       }
>    }
> }
>
> printf("%s\n",fecha);
> printf("%s\n",hora);
>
> for(i=0;i<9;i++){
>    printf("%d %s %c\n", i, zonas[i], alarmas[i]);
>

Hay un error con el último parámetro, ya que en la cadena de formato,
quieres representar el puntero, 'alarmas[i]', como un solo carácter. O bien
accedes a un carácter,

printf( "%d %s %c\n", i, zonas[i], alarmas[i][0] );  // Mostramos el primer
carácter de una "alarma"

O bien quieres mostrar una cadena,

printf( "%d %s %s\n", i, zonas[i], alarmas[i] );  // Mostramos la cadena
apuntada por 'alarmas[i]'

}
> fclose(ptrdel);
> }
>
> #endif
>
>
El problema es que usas punteros a cadenas, pero sólo apuntas a la misma
cadena; por ejemplo, escribes,

zonas[j] = zona;

El contenido de 'zona' puede cambiar en cada iteración, por lo que cada
puntero en 'zonas' apuntará a la misma cadena y por tanto al mismo
contenido.

Viendo el código, creo que te conviene usar arrays y no punteros. Si
quieres mantenter una lista de 9 cadenas de caracteres, entonces haz eso
mismo:

char alarmas[9][2] = { "" };  // 9 arrays de 2 'char' cada uno
char zonas[9][2] = { "" };
char delitos[54][20] = { "" };

Puedes eliminar los otros arrays: 'zona', 'alarma', 'delito', y 'cadena',
porque podemos usar los otros arrays directamente. Por ejemplo,

fscanf( ptrdel, "%s", fecha );
fscanf( ptrdel, "%s", hora );
...
fscanf( ptrdel, "%s", zonas[j] );
fscanf( ptrdel, "%s", alarmas[j] );
...
fscanf( ptrdel, "%s", delitos[d] );

Además, creo que esto es más legible.


Espero que esto te ayude.

Steven
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20130126/8796273a/attachment.html>


Más información sobre la lista de distribución Cconclase