I've been having a problem with a C program that works with a binary file, by passing it's contents to a linked list. When the file is empty, I just create the linked list and manipulate it in the program, that mostly works fine (debugging the solutions as we speak). And when I am ready to leave the program, it moves the linked list back into the file with apparently no problems. But when I try to open the program again, it writes what it's on the file plus one more linked list node (if there are 2 registers saved in the binary file, it will create 3 nodes, 2 with the file info and 1 totally empty. Does anyone know why this happens and what I can do to fix it??
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
typedef struct {
int dia;
int mes;
int anio;
} fecha;
typedef struct {
int protocolo;
char paciente [50];
char medico [50];
int tieneOS;
char obraSocial [50];
int montoOS;
int montoPaciente;
fecha fechaAnalisis;
} cobro;
typedef struct Tnodo{
cobro info;
struct Tnodo *next;
} nodo;
fecha leerFecha();
void cargarInforme(nodo **c, fecha f);
void modificarInforme(nodo *c);
void eliminarInforme(nodo **c);
void buscarProtocolo(nodo *c);
void listarInformes(nodo *c);
void listarMontosOS(nodo *c);
void myflush ( FILE *in );
void mypause ( void );
int sumaMontoOS(nodo *c, char nOS[20], int mT);
FILE *archivo;
int main () {
int opcion;
int size;
fecha fechaActual;
fechaActual = leerFecha();
printf("La fecha ingresada es: %d/%d/%d", fechaActual.dia, fechaActual.mes, fechaActual.anio);
nodo *head = malloc(sizeof(nodo));
nodo *cursor = head->next;
archivo = fopen("cobros.dat", "ab+");
if (NULL != archivo) {
fseek (archivo, 0, SEEK_END);
size = ftell(archivo);
}
if (size == 0) {
printf("El archivo no existe. Creando Lista....\n");
sleep(3);
cursor = head;
} else {
printf("El archivo existe. Cargando Lista.\n");
sleep(3);
rewind (archivo);
cursor = head;
while (!feof(archivo)) {
nodo *nuevo = malloc(sizeof(nodo));
fread(&nuevo->info, sizeof(cobro), 1, archivo);
cursor->next = nuevo;
cursor = cursor->next;
}
}
do
{
system ("clear");
printf ("MENU DE OPCIONES:\n\n");
printf ("1. Cargar Informe\n");
printf ("2. Modificar Informe\n");
printf ("3. Eliminar Informe\n");
printf ("4. Buscar un Protocolo\n");
printf ("5. Listar Informes\n");
printf ("6. Listar Montos OS por mes\n");
printf ("7. Guardar y Salir\n");
printf ("Elige una opcion: ");
scanf ("%d", &opcion);
switch (opcion)
{
case 1:
system ("clear");
cursor = head;
cargarInforme(&cursor, fechaActual);
break;
case 2:
system ("clear");
cursor = head;
modificarInforme(cursor);
break;
case 3:
system ("clear");
cursor = head->next;
eliminarInforme(&cursor);
break;
case 4:
system ("clear");
break;
case 5:
system ("clear");
cursor = head->next;
listarInformes(cursor);
break;
case 6:
system ("clear");
cursor = head->next;
listarMontosOS(cursor);
break;
case 7:
system ("clear");
cursor = head->next;
rewind (archivo);
while (cursor != NULL) {
fwrite(&cursor->info, sizeof(cobro), 1, archivo);
cursor = cursor->next;
}
fclose(archivo);
break;
default:
system ("clear");
printf ("La opcion ingresada no es correcta. Por favor intente nuevamente.");
break;
};
}while (opcion != 7);
}
fecha leerFecha() {
fecha f;
printf("Ingrese la fecha actual (dd/mm/aaaa): ");
scanf("%d/%d/%d", &f.dia, &f.mes, &f.anio);
return f;
}
void cargarInforme(nodo **c, fecha f) {
nodo *aux = malloc(sizeof(nodo));
while ((*c)->next != NULL) {
(*c) = (*c)->next;
}
aux->info.protocolo = (*c)->info.protocolo + 1;
printf("Ingrese el nombre del paciente: ");
scanf("%s", aux->info.paciente);
printf("Ingrese el nombre del medico: ");
scanf("%s", aux->info.medico);
printf("Tiene obra social? (1 = si, 0 = no): ");
scanf("%d", &aux->info.tieneOS);
if (aux->info.tieneOS == 1) {
printf("Ingrese el nombre de la obra social: ");
scanf("%s", aux->info.obraSocial);
printf("Ingrese el monto de la obra social: ");
scanf("%d", &aux->info.montoOS);
} else {
strcpy (aux->info.obraSocial, "No tiene");
aux->info.montoOS = 0;
}
printf("Ingrese el monto a pagar por el paciente: ");
scanf("%d", &aux->info.montoPaciente);
aux->info.fechaAnalisis = f;
(*c)->next = aux;
}
void modificarInforme(nodo *c) {
int protocolo;
int o;
printf("Ingrese el protocolo del informe a modificar: ");
scanf("%d", &protocolo);
while (c != NULL) {
if (c->info.protocolo == protocolo) {
do {
system ("clear");
printf ("QUE CAMPO DESEA MODIFICAR? (NO PUEDE MODIFICAR FECHA NI NUMERO DE PROTOCOLO):\n\n");
printf ("1. Nombre del Paciente\n");
printf ("2. Nombre del Medico\n");
printf ("3. Estado de Obra Social (Tiene OS o no, Nombre y Monto a pagar)\n");
printf ("4. Monto a Pagar del Paciente\n");
printf ("5. No deseo modificar mas, Guardar y Salir\n");
printf ("Elige una opcion: ");
scanf ("%d", &o);
switch (o) {
case 1:
system ("clear");
printf("Ingrese el nuevo nombre del paciente: ");
scanf("%s", c->info.paciente);
break;
case 2:
system ("clear");
printf("Ingrese el nuevo nombre del medico: ");
scanf("%s", c->info.medico);
break;
case 3:
system ("clear");
printf("Quiere cambiar status de obra social? (1 = si, 0 = no): ");
scanf("%d", &c->info.tieneOS);
if (c->info.tieneOS == 1) {
printf("Ingrese el nuevo nombre de la obra social: ");
scanf("%s", c->info.obraSocial);
printf("Ingrese el nuevo monto de la obra social: ");
scanf("%d", &c->info.montoOS);
} else {
strcpy (c->info.obraSocial, "No tiene");
c->info.montoOS = 0;
}
break;
case 4:
system ("clear");
printf("Ingrese el nuevo monto a pagar por el paciente: ");
scanf("%d", &c->info.montoPaciente);
break;
case 5:
system ("clear");
break;
default:
system ("clear");
printf ("La opcion ingresada no es correcta. Por favor intente nuevamente.");
break;
}
}while (o != 5);
break;
}
c = c->next;
}
}
void eliminarInforme(nodo **c) {
int protocolo;
nodo *aux;
printf("Ingrese el protocolo del informe a eliminar: ");
scanf("%d", &protocolo);
while ((*c) != NULL) {
if ((*c)->info.protocolo == protocolo) {
aux = (*c);
(*c) = (*c)->next;
free(aux);
break;
}
(*c) = (*c)->next;
}
}
void listarInformes(nodo *c) {
while (c != NULL) {
printf("Protocolo: %d\n", c->info.protocolo);
printf("Paciente: %s\n", c->info.paciente);
printf("Medico: %s\n", c->info.medico);
printf("Tiene OS: %d\n", c->info.tieneOS);
printf("OS: %s\n", c->info.obraSocial);
printf("Monto OS: %d\n", c->info.montoOS);
printf("Monto Paciente: %d\n", c->info.montoPaciente);
printf("Fecha Analisis: %d/%d/%d\n\n", c->info.fechaAnalisis.dia, c->info.fechaAnalisis.mes, c->info.fechaAnalisis.anio);
c = c->next;
}
myflush(stdin);
mypause();
}
void listarMontosOS(nodo *c) {
int mes;
int cantOS = 0;
typedef struct {
char nombreOS[20];
int montoTotal;
} os;
typedef struct {
os o [100];
int cantOS;
} reg;
reg r;
r.cantOS = 0;
int i = 0;
printf("Ingrese el mes a consultar (1-12): ");
scanf("%d", &mes);
while (c->next != NULL) {
if (c->info.tieneOS == 1 && c->info.fechaAnalisis.mes == mes) {
for (i = 0; i < r.cantOS; i++)
{
if (strcmp(r.o[i].nombreOS, c->info.obraSocial) == 0) {
r.o[i].montoTotal = sumaMontoOS(c, r.o[i].nombreOS, r.o[i].montoTotal);
break;
}
}
if (r.cantOS > 0)
{
cantOS = r.cantOS - 1;
}
if (i == cantOS)
{
strcpy(r.o[i].nombreOS, c->info.obraSocial);
r.o[i].montoTotal = sumaMontoOS(c, r.o[i].nombreOS, r.o[i].montoTotal);
r.cantOS++;
}
}
c = c->next;
}
for (int j = 0; j < r.cantOS; j++)
{
printf("El monto total a pagar por la obra social %s es de: %d\n", r.o[i].nombreOS, r.o[i].montoTotal);
myflush(stdin);
mypause();
}
}
int sumaMontoOS(nodo *c, char nOS[20], int mT) {
if (c == NULL){
return mT;
}
else if ((c->info.tieneOS == 1) && (strcmp(c->info.obraSocial, nOS) == 0)) {
return sumaMontoOS(c->next, nOS, mT + c->info.montoOS);
}
}
void myflush ( FILE *in )
{
int ch;
do
ch = fgetc ( in );
while ( ch != EOF && ch != '\n' );
clearerr ( in );
}
void mypause ( void )
{
printf ( "Apriete Enter para continuar . . ." );
fflush ( stdout );
getchar();
}