[C con Clase] ayuda con ficheros y estructura porfiss :)

Davidson, Steven srd4121 en njit.edu
Lun Jun 3 23:07:34 CEST 2013


Hola Felician,

2013/6/3 felician draghici <felix1900toamna en yahoo.es>

> Hola tengo una duda con los ficheros y las estructuras,si alguien me puede
> echar una mano
> Resulta que es un proyecto final y no se si esta bien utilizar una
> estructura para guardar todos los datos introducidos en un fichero o habra
> que utilizar una estructura de tipo array struct ejemplo estructura[]..ya
> sabeis,mi profe me esta volviendo un poco loco y necesito vuestra
> ayuda,tengo este programa de pedidos telefonicos(como por ejemplo un
> telecomida china),la pregunta es: si guardo todo en una estructura y se
> escribe luego en el fichero,luego puedo utilizar la misma estructura o
> habra que hacer una estructura "array"
> ,si se hace con una estructura nada mas los datos de ella deberan ser
> escritos en una fila del fichero o da igual de la escritora de este porque
> a mi me la escribe a continuacion y no puede hacer la comparacion entre
> numeros si los busco...gracias un saludo
>
>
Ciertamente hay dos maneras de resolver el problema presentado. Puedes
optar por obtener el registro y escribirlo inmediatamente. De esta forma,
puedes reusar la misma variable para obtener más registros. Es decir, creas
una solución de lectura parcial del usuario y escritura parcial al fichero.

La otra solución es obtener todos los registros del usuario y guardarlos en
memoria. Luego, escribes todos los registros en memoria al fichero. La
ventaja es que podemos manipular los registros - y la información contenida
en ellos - directamente en memoria. Cuando queramos, guardamos estos
registros en el fichero. Realizar operaciones con el fichero suelen ser más
lentas en ejecutarse que realizar las mismas operaciones en memoria.

Personalmente, si vas a realizar varias operaciones con los registros
dados, entonces aconsejo que las hagas en memoria. Cuando estés listo para
guardar esos registros, porque no van a ser modificados, entonces los
guardas en el fichero. Por otro lado, si estás pensando en permitir miles
de millones de registros y cada uno ocupa 100 bytes, entonces esto
implicaría más de 93 GB. En el disco duro, esto no es un grave problema hoy
día, pero para memoria RAM sí que lo es. En este caso, optaríamos por
realizar las operaciones necesarias por tandas (grupos) de millones de
registros, que seguramente ocuparán unos cententares de megabytes en
memoria. La otra opción es simplemente crear una estructura de datos para
dirigirnos a las posiciones en el fichero de los registros que queremos
acceder, para poder realizar las operaciones con cada registro leído uno a
uno.

Hay algunos matices a destacar en tu código fuente.


> struct pedido introducir_datos(struct pedido telef);
> int menu_programa(void);
> int ver_menu(void);
> void mostrar_pedidos(struct pedido telef);
> struct pedido{
>          char telefono[10];//numero de telefono del cliente
>          char calle[40];//nombre de calle del cliente
>          char portal[4];
>          char piso[5];
>          float pedidos;//valor pedido
>          float total_pedidos;//valor total de los pedidos
>        };
>

Debes definir esta estructura antes de tus funciones, porque algunos
prototipos hacen referencia a este tipo de dato, que el compilador
desconoce, porque defines 'pedido' póstumamente a usarlo.

int menu_programa(void)
> {//FUNCION QUE PERMITE MOSTRAR EL MENU PRINCIPAL DEL PROGRAMA
>     int var;
>     system("cls");
>
>     printf("\n\tMENU PRINCIPAL");
>     printf("\n\n1) Insertar telefono ");
>     printf("\n2) Modificar pedido(ultimos 4 digitos telefonicos) ");
>     printf("\n3) Ver total dinero sacado en el dia ");
>     printf("\n4) Consultar precios productos y modificarlos ");
>     printf("\n5) Mostrar total pedidos(numeros de telefonos)");
>     printf("\n6) Borrar pedido por pedido");
>     printf("\n0) Salir programa");
>
>     printf("\n\nTeclea opcion: ");
>     scanf("%d",&var);
>     fflush(stdin);
>
>

Ten presente que este comportamiento de 'fflush()' no es estándar; pero en
MS-DOS y MS-Windows, sí funcionará.

 return var;
> getchar();
>

Esto no tiene sentido. Si retornas, la función termina de ejecutarse
inmediatamente, por lo que nunca llega a 'getchar()'.

}
> struct pedido introducir_datos(struct pedido telef)
> {//FUNCION QUE PERMITE AÑADIR DATOS EN EL FICHERO DE LOS PEDIDOS
>       struct pedido {
>          char num_tel[50];
>          char direccion[50];
>          char portal2[50];
>          char piso2[50];
>         }lectura;
>
>

Esto no tiene sentido y además puede no funcionar como quieres. El error
está en redefinir 'pedido'; porque ya la tienes definida globalmente.
Simplemente usa el tipo de dato:

struct pedido lectura;

Es cierto que los campos tienen diferentes nombres, pero más importante es
la diferencia de tipos.

     FILE *fichero;
>      int a,b,encontrado=0;//contador
>      char t,p,po,c;
>
>      for(b=0;b<50;b++)
>      {
>          lectura.direccion[b] = '\0';
>          lectura.piso2[b] = '\0';
>          lectura.portal2[b] = '\0';
>          lectura.num_tel[b] = '\0';
>      }
>
>

Esto no es necesario. Simplemente indica el carácter nulo para el comienzo
de cada cadena. Por ejemplo,

lectura.direccion[0] = lectura.piso2[0] = lectura.portal2[0] =
lectura.num_tel[0] = '\0';

Por otro lado, podrías haber inicializado la estructura, 'lectura', en
lugar de asignar valores iniciales después de su definición. Esto es,

struct pedido lectura = { "", "", "", "" };

        scanf("%s",&lectura.num_tel);
>

Esto es incorrecto. 'num_tel' es un array. No tiene sentido encontrar su
dirección de memoria, porque un array ya es una dirección de memoria. Por
lo tanto, escribe:

scanf( "%s", lectura.num_tel );

        fflush(stdin);
>
>
>         fread(&telef.telefono,sizeof(telef.telefono),1,fichero);
>

Aquí, lo mismo; 'telefono' ya es una dirección de memoria. Escribe:

fread( telef.telefono, sizeof(telef.telefono), 1, fichero );

       if(strcmp(telef.telefono,lectura.num_tel)!=0)
>

Aquí puedes tener un error. Como 'telefono' contiene menos caracteres que
'num_tel', es posible que la comparación sea errónea.


>        //if(encontrado==0)
>        {
>           printf("\nEscriba el nombre de la calle:");
>           scanf("%s",&lectura.direccion);
>           fflush(stdin);
>           printf("\nPortal:");
>           scanf("%s",&lectura.portal2);
>           fflush(stdin);
>           printf("\nPiso y letra:");
>           scanf("%s",&lectura.piso2);
>

Nuevamente, estos campos son arrays: no uses el operador &.

          fflush(stdin);
>
>           strcpy(telef.telefono,lectura.num_tel);
>           strcpy(telef.portal,lectura.portal2);
>           strcpy(telef.piso,lectura.piso2);
>           strcpy(telef.calle,lectura.direccion);
>

Aquí puedes tener errores. Como los campos de 'telef' contienen menos
caracteres que los de 'lectura', se puede dar el caso peligroso de copiar
caracteres de más que rebasen las limitaciones de tales campos. Esto supone
sobreescribir memoria posterior.

          fwrite(&telef.telefono,sizeof(telef.telefono),1,fichero);
>           fwrite(&telef.calle,strlen(telef.calle),1,fichero);
>
          fwrite(&telef.portal,strlen(telef.portal),1,fichero);
>           fwrite(&telef.piso,strlen(telef.piso),1,fichero);
>

Nuevamente, estos campos son arrays; no uses el operador &.

De todas maneras, tienes un error al intentar escribir las cadenas al
fichero binario, en lugar de escribir los arrays. Como se trata de un
fichero binario, la idea es poder leer un campo o incluso el registro
entero de una sola sentada porque sus tamaños son fijos.

Podrías escribir el registro con una sola llamada a 'fwrite()'.

       }
>        else
>        {
>           fread(&telef.telefono,sizeof(telef.telefono),1,fichero);
>           fread(&telef.calle,strlen(telef.calle),1,fichero);
>           fread(&telef.portal,strlen(telef.portal),1,fichero);
>           fread(&telef.piso,strlen(telef.piso),1,fichero);
>

No tiene sentido calcular el tamaño de la cadena, cuando vas a leer desde
el fichero una cadena completamente diferente a la que tienes en memoria.
Nuevamente, deberías leer los arrays enteros con la cantidad fija. Además,
podrías leer todo el registro de golpe con una sola llamada a 'fread()'.

       //   fgets(telef.calle,1,fichero);
>         //  fgets(telef.portal,1,fichero);
>         //  fgets(telef.piso,1,fichero);
>           printf("\nTelefono: %s",telef.telefono);
>           printf("\nCalle: %s",telef.calle);
>           printf("\nPortal: %s",telef.portal);
>           printf("\nPiso: %s",telef.piso);
>        }
>      }
>
>
>  ///   }//fin operaciones con el fichero
>      fclose(fichero);
>
>
> getchar();
>

La función debe retornar una estructura; pero no retornas nada.


> }
> //FUNCION PARA VER EL LISTADO DE LAS COMIDAS Y PRECIOS QUE HAY EN EL
> RESTAURANTE
> int ver_menu(void)
> {
>      system("cls");
>      FILE *fm;//fichero menu comidas
>      char letra;
>
>      fm = fopen("C://c_files//proyecto//comidas.txt","rb");
>
>      if(fm==NULL)
>      {
>         printf("\nError de lectura de fichero menu");
>      }
>      else
>      {
>         letra = fgetc(fm);
>          while(feof(fm)==0)
>          {
>             printf("%c",letra);
>             letra = fgetc(fm);
>          }
>      }
>
>      fclose(fm);
>
>  getchar();
> return 0;
>

Si no tienes pensado retornar nada; entonces indica 'void' como el tipo de
retorno de esta función.

}
>


Espero que todo esto te sea de ayuda.

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


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