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":
fgets((*clientes
).
apellido, 30, *db
); /* Leemos el apellido */ 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:
fgets((*clientes
).
apellido, 30, *db
); /* 1 */ printf("%s\n", (*clientes
).
nombre);
fgets((*clientes
).
apellido, 30, *db
); /* 2 */ printf("%s\n", (*clientes
).
apellido);
fscanf(*db
, "%d", &(*clientes
).
telefono); /* 3 */ printf("%d\n", (*clientes
).
telefono);
fscanf(*db
, "%d", &(*clientes
).
edad); /* 4 */ printf("%d\n", (*clientes
).
edad); }
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:
fgets((*clientes
).
apellido, 30, *db
); printf("%s\n", (*clientes
).
nombre);
/* ... */
fscanf(*db
, "%d", &(*clientes
).
edad); printf("%d\n", (*clientes
).
edad);
{
int ch;
while ((ch
= fgetc(*db
)) != EOF
&& ch
!= '\n') ;
}
}
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