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

Gabriel Casarsa gabriel_casarsa en yahoo.com.ar
Dom Ene 27 00:16:24 CET 2013


Hola
Steven, muchas gracias por contestar.

Cuando
hago  fscanf
(ptrdel, "%s", cadena) != EOF; es para leer hasta
encontrar un espacio. No se si es la forma de hacerlo, pero anduvo bien je.

Yo
tengo almacenado en el archivo algo así:

25/01/2013 16:21:39

NO X Falsificacion Extorsion Toma_de_Rehen Falsificacion Robo
Falsificacion ,

NT + ,

NE X Robo Incendio Usurpacion Robo Asesinato Asesinato ,

OE X Usurpacion Falsificacion Falsificacion Usurpacion Incendio ,

CE ! ,

ES X Robo Asesinato Extorsion Extorsion Asesinato ,

SO X Robo Asesinato ,

SR X Incendio Robo Asesinato Extorsion ,

SE ! Extorsion ,

-

25/01/2013 16:21:40

NO X Extorsion Extorsion Robo Extorsion Usurpacion Falsificacion ,

NT X Falsificacion Robo Falsificacion Usurpacion Incendio
Toma_de_Rehen ,

NE ! Extorsion Extorsion Extorsion Falsificacion ,

OE ! ,

CE X Asesinato Robo Extorsion ,

ES X Falsificacion Extorsion Falsificacion Robo ,

SO X Asesinato Falsificacion ,

SR X Incendio Usurpacion Asesinato Asesinato Falsificacion ,

SE ! Incendio Toma_de_Rehen Usurpacion Usurpacion ,

-

 

Lo
que quiero hacer es leer las palabras. La primera es la fecha, luego la hora y después,
como son 9 zonas hasta iniciar una nueva actualizacion, hago un for en el que
leo la zona que, luego un carácter de estado de alarma y luego, hasta encontrar
una “,”, leo los distintos delitos.

La z me olvide de sacarla, me di cuenta que con j alcanzaba.

El
tema de la longitud de cadena es para los delitos, pero cuando lee zona o
alarma nunca va a tener mas de 2 o 1 carácter.

El
“d” nunca va a poder superar la cantidad de 62, que es la maxima cantidad de
delitos por actualizacion.

Me
funciona bien hasta donde probe, pero me parece que me estoy haciendo mucho
problema con el tema de punteros entonces.

No
entiendo porque zonas[0] = NO; y cuando va a j = 1, ademas de actualizar el
zonas[1] actualiza el zonas[0].



--- El sáb 26-ene-13, Davidson, Steven <srd4121 en njit.edu> escribió:



De: Davidson, Steven <srd4121 en njit.edu>

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

Para: "Lista de correo sobre C y C++"
<cconclase en listas.conclase.net>

Fecha: sábado, 26 de enero de 2013, 19:52

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/f269f21f/attachment.html>


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