elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Introducción a la Factorización De Semiprimos (RSA)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Problema con registros
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Problema con registros  (Leído 1,955 veces)
jaxoR

Desconectado Desconectado

Mensajes: 93

?


Ver Perfil WWW
Problema con registros
« en: 4 Septiembre 2014, 01:54 am »

Hola, tengo un problema al leer un archivo en el que guardo un registro. El problema es que me muestra varios signos y numeros que yo no ingrese. Les paso a dejar las funciones en donde escribo y leo el fichero (Paso el fichero y el archivo por referencia):

Código
  1. void DarDeAlta(registro *clientes, int n, FILE **db)
  2. {
  3.    int a = 1;
  4.  
  5.    while (a == 1)
  6.    {
  7.        printf("Ingrese un nombre: ");
  8.        scanf("%s", ((*clientes).nombre));
  9.        fprintf(*db, "%s\n", (*clientes).nombre);
  10.  
  11.        printf("Ingrese su apellido: ");
  12.        scanf("%s", ((*clientes).apellido));
  13.        fprintf(*db, "%s\n", (*clientes).apellido);
  14.  
  15.        printf("Ingrese el telefono: ");
  16.        scanf("%d", &(*clientes).telefono);
  17.        fprintf(*db, "%d\n", (*clientes).telefono);
  18.  
  19.        printf("Ingrese la edad: ");
  20.        scanf("%d", &(*clientes).edad);
  21.        fprintf(*db, "%d\n", (*clientes).edad);
  22.  
  23.        Seguir(&a);
  24.    }
  25.  
  26.    fclose(*db);
  27.    return;
  28. }
  29.  
  30. void MostrarClientes(registro *clientes, int n, FILE **db)
  31. {
  32.    *db = fopen("clientes.dat", "r");
  33.    if(*db == NULL)
  34.    {
  35.        printf("El archivo no existe\n");
  36.    }
  37.    else{
  38.        while(feof(*db) == 0)
  39.        {
  40.            fgets((*clientes).apellido, 30, *db);
  41.            printf("%s\n", (*clientes).nombre);
  42.  
  43.            fgets((*clientes).apellido, 30, *db);
  44.            printf("%s\n", (*clientes).apellido);
  45.  
  46.            fscanf(*db, "%d", &(*clientes).telefono);
  47.            printf("%d\n", (*clientes).telefono);
  48.  
  49.            fscanf(*db, "%d", &(*clientes).edad);
  50.            printf("%d\n", (*clientes).edad);
  51.        }
  52.    }
  53.  
  54.    fclose(*db);
  55.    return;
  56. }


« Última modificación: 4 Septiembre 2014, 03:09 am por wiD^ » En línea

rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: Problema con registros
« Respuesta #1 en: 4 Septiembre 2014, 05:19 am »

Si no tienes un curso o libro de calidad deberías conseguir uno, para recomendaciones basta con utilizar el motor de búsqueda de los foros.

Deficiencias en el fragmento hay bastantes:

* Falta consistencia: una función cierra el archivo, la otra lo abre y cierra. Bien ambas funciones operan sobre el archivo (lo abren y cierran) o ambas solo realizan la operación en turno.

* No es necesario emular el paso por referencia.

* En la función "DarDeAlta" la ultima sentencia esta de mas (las funciones terminan con su llave de cierre), hay que cambiar la función "Seguir" para utilizar su valor de retorno y una vez hecho lo anterior se cambia el bucle por uno do ... while eliminando de paso la variable local "a".

* En la función "MostrarClientes" los dos últimos parámetros no son necesarios: "n" no es utilizado en la función mientras que lo primero que haces con "db" es sobrescribir su valor, este ultimo se debe cambiar por una variable local.

* Hay un error lógico en la función "MostrarClientes":
Código
  1. fgets((*clientes).apellido, 30, *db); /* Leemos el apellido    */
  2. printf("%s\n", (*clientes).nombre);   /* Imprimimos el nombre  */

* En ambas funciones utilizas la notación "(*variable).campo" cuando puedes acortar evitando los paréntesis con "variable->campo".

* El error que mencionas se debe al uso intercalado de fgets y fscanf en la función "MostrarClientes". Para explicarlo mejor etiquetamos los pasos en cada iteracion:
Código
  1. while (feof(*db) == 0){
  2.   fgets((*clientes).apellido, 30, *db);     /* 1 */
  3.   printf("%s\n", (*clientes).nombre);
  4.  
  5.   fgets((*clientes).apellido, 30, *db);     /* 2 */
  6.   printf("%s\n", (*clientes).apellido);
  7.  
  8.   fscanf(*db, "%d", &(*clientes).telefono); /* 3 */
  9.   printf("%d\n", (*clientes).telefono);
  10.  
  11.   fscanf(*db, "%d", &(*clientes).edad);     /* 4 */
  12.   printf("%d\n", (*clientes).edad);
  13. }

Primera iteración:

1 fgets lee el nombre (ya se menciono que hay un error lógico).
2 fgets lee el apellido.
3 fscanf lee el telefono, deja el ultimo carácter invalido (el avance de linea) en el bufer correspondiente.
3 fscanf lee la edad, deja el ultimo carácter invalido (el avance de linea) en el bufer correspondiente.

Segunda iteración:

1 fgets lee el '\n' como una linea en blanco y se almacena esta en el nombre.
2 fgets lee el nombre y lo almacena en el apellido.
3 fscanf falla al tratar de leer el telefono del apellido.
4 fscanf falla al tratar de leer la edad del apellido.

Tercera iteración

1 fgets lee el nombre (apellido del registro anterior)
2 fgets lee el apellido (telefono del registro anterior)
etc.

Para solucionarlo se tienen dos opciones:

A) Leer todas las lineas del archivo con fgets, de ser necesario (por ejemplo en este caso con el teléfono y la edad) se utiliza un array de caracteres auxiliar y la función sscanf para extraer el valor.

B) Justo después de la llamada a fscanf y antes de la llamada a fgets se descarta el resto de la linea con un bucle, tomando tu caso como ejemplo:
Código
  1. while (feof(*db) == 0){
  2.   fgets((*clientes).apellido, 30, *db);
  3.   printf("%s\n", (*clientes).nombre);
  4.  
  5.   /* ... */
  6.  
  7.   fscanf(*db, "%d", &(*clientes).edad);
  8.   printf("%d\n", (*clientes).edad);
  9.  
  10.   {
  11.      int ch;
  12.  
  13.      while ((ch = fgetc(*db)) != EOF && ch != '\n')
  14.         ;
  15.   }
  16. }

Por ultimo en la función "MostrarClientes" se debe evitar el uso de la función "feof" ya que esto resultara en un iteración de mas, en su lugar hay que verificar el valor de retorno de las funciones fgets y fscanf.

Un saludo


En línea

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
jaxoR

Desconectado Desconectado

Mensajes: 93

?


Ver Perfil WWW
Re: Problema con registros
« Respuesta #2 en: 4 Septiembre 2014, 22:50 pm »

rir, gracias como siempre. Resolví todos los errores pero no entendí lo siguiente:

* En ambas funciones utilizas la notación "(*variable).campo" cuando puedes acortar evitando los paréntesis con "variable->campo".

No entiendo a que te refieres con: variable->campo

Y lo otro que no entendí es lo siguiente:

Código
  1. while (feof(*db) == 0){
  2.   fgets((*clientes).apellido, 30, *db);
  3.   printf("%s\n", (*clientes).nombre);
  4.  
  5.   /* ... */
  6.  
  7.   fscanf(*db, "%d", &(*clientes).edad);
  8.   printf("%d\n", (*clientes).edad);
  9.  
  10.   {
  11.      int ch;
  12.  
  13.      while ((ch = fgetc(*db)) != EOF && ch != '\n')
  14.         ;
  15.   }
  16. }

No entiendo que hace el segundo while y cuando entraría adentro de esas llaves
En línea

rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: Problema con registros
« Respuesta #3 en: 5 Septiembre 2014, 17:35 pm »

no entendí lo siguiente:

* En ambas funciones utilizas la notación "(*variable).campo" cuando puedes acortar evitando los paréntesis con "variable->campo".

No entiendo a que te refieres con: variable->campo
En C "->" es un operador y se utiliza para en base a un puntero a estructura acceder al campo indicado. Donde sea que utilices "(*puntero).nombre_del_campo" puedes sustituirlo por "puntero->nombre_del_campo" con el mismo resultado.

Tomando tu programa como ejemplo puedes cambiar esta parte:
Código
  1. fgets((*clientes).apellido, 30, *db);
  2. printf("%s\n", (*clientes).nombre);
A:
Código
  1. fgets(clientes->apellido, 30, *db);
  2. printf("%s\n", clientes->nombre);

No entiendo que hace el segundo while
Ese bucle lee un carácter y lo descarta (lee otro) hasta encontrarse con uno que sea igual a EOF (indica error) o '\n' (indica el final de la linea). El objetivo de ello es descartar el resto de la linea ya que fscanf no lee por linea (fgets si y ahí empiezan los problemas que ya comente).

y cuando entraría adentro de esas llaves
Siempre. Puedes tener un bloque delimitado por llaves en cualquier lugar donde una sentencia sea valida y no hay problema, el objetivo de utilizar un bloque es evitar un conflicto de nombres si, por alguna razón, ya existe una variable con el nombre "ch".

Un saludo
En línea

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
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Problema registros con vbscript
Programación Visual Basic
Bardick 0 952 Último mensaje 6 Octubre 2007, 01:18 am
por Bardick
[Registros] existe algún registro para Outlook en los registros de windows?
Windows
moikano→@ 5 6,881 Último mensaje 14 Febrero 2011, 14:56 pm
por dantemc
problema con modificar registros
Programación C/C++
bambam93 0 1,442 Último mensaje 1 Mayo 2014, 04:24 am
por bambam93
Problema - Registros y archivos
Programación C/C++
jaxoR 6 2,859 Último mensaje 6 Noviembre 2014, 13:33 pm
por eferion
Problema al leer registros en ficheros
Programación C/C++
neveldine 1 1,458 Último mensaje 25 Noviembre 2015, 14:09 pm
por neveldine
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines