Ficheros y listas enlazadas en C: ejemplos prácticos de estructuras, lectura y escritura
Programación en C: ficheros, estructuras y listas enlazadas
A continuación se presentan ejemplos prácticos en lenguaje C sobre estructuras, ficheros de texto y binarios y listas enlazadas, con el código comentado y organizado por apartados.
1. Estructura de alumnos, grabación en texto y binario
Se define la estructura talumno y se utilizan funciones para grabar los datos en un fichero de texto (grabaTexto) y en un fichero binario (grabaBinario), y para leer el fichero binario mostrando los alumnos con nota mayor o igual a 6.00 (leeBinario).
typedef struct {
int codigo;
char nombre[50];
char dni[20];
float nota;
} talumno;
void grabaTexto(FILE *pf, talumno *array, int tam);
void grabaBinario(FILE *pfb, talumno *array, int tam);
void leeBinario(FILE *pfb);
int main()
{
talumno *array = (talumno *)malloc(3 * sizeof(talumno));
if (array == NULL)
{
printf("ERROR: falta memoria\n");
exit(0);
}
array[0].codigo = 12345;
strcpy(array[0].nombre, "Juan Perez");
strcpy(array[0].dni, "03888777C");
array[0].nota = 7.50;
/* Igual con array[1] y array[2] */
FILE *pf = fopen("datos.txt", "w");
if (pf == NULL)
{
printf("ERROR al abrir fichero texto\n");
exit(0);
}
FILE *pfb = fopen("datos.bin", "w+b");
if (pfb == NULL)
{
/* Igual que en el caso anterior */
}
grabaTexto(pf, array, 3);
grabaBinario(pfb, array, 3);
leeBinario(pfb);
fclose(pf);
fclose(pfb);
free(array);
return 0;
}
void grabaTexto(FILE *pf, talumno *array, int tam)
{
for (int i = 0; i < tam; i++)
{
fprintf(pf, "Codigo: %d Nombre: %s DNI: %s Nota: %.2f\n",
array[i].codigo, array[i].nombre, array[i].dni, array[i].nota);
}
printf("Fichero texto grabado correctamente\n");
}
void grabaBinario(FILE *pfb, talumno *array, int tam)
{
for (int i = 0; i < tam; i++)
{
fwrite(&array[i], sizeof(talumno), 1, pfb);
}
printf("Fichero binario grabado correctamente\n");
}
void leeBinario(FILE *pfb)
{
rewind(pfb);
talumno reg;
printf("\nALUMNOS CON NOTA >= 6.00\n");
while (fread(®, sizeof(talumno), 1, pfb) == 1)
{
if (reg.nota >= 6.00)
{
printf("%d %s %s %.2f\n", reg.codigo, reg.nombre, reg.dni, reg.nota);
}
}
}2. Lista enlazada de alumnos: inserción al final y visualización
Se define la estructura tlista como nodo de una lista enlazada. La función insertar añade nodos al final de la lista, mostrar recorre la lista completa y mostrarUltimo muestra el último nodo.
typedef struct lista
{
char codigo[10];
char nombre[50];
char dni[10];
float nota;
struct lista *siguiente;
} tlista;
void insertar(tlista **plista, tlista alumno);
void mostrar(tlista *lista);
void mostrarUltimo(tlista *lista);
int main()
{
tlista *lista = NULL;
tlista array[3] =
{
{"A001", "Juan Perez", "12345678A", 7.5, NULL},
{"A002", "Ana Lopez", "87654321B", 5.8, NULL},
{"A003", "Luis Gomez", "11223344C", 8.3, NULL}
};
insertar(&lista, array[0]);
insertar(&lista, array[1]);
insertar(&lista, array[2]);
mostrar(lista);
mostrarUltimo(lista);
return 0;
}
/* INSERTAR AL FINAL */
void insertar(tlista **plista, tlista alumno)
{
tlista *nuevo = (tlista *)malloc(sizeof(tlista));
if (nuevo == NULL)
{
printf("Error: falta memoria\n");
return;
}
strcpy(nuevo->codigo, alumno.codigo);
strcpy(nuevo->nombre, alumno.nombre);
strcpy(nuevo->dni, alumno.dni);
nuevo->nota = alumno.nota;
nuevo->siguiente = NULL;
if (*plista == NULL)
{
*plista = nuevo;
}
else
{
tlista *aux = *plista;
while (aux->siguiente != NULL)
aux = aux->siguiente;
aux->siguiente = nuevo;
}
}
void mostrar(tlista *lista)
{
printf("Contenido de la lista:\n");
while (lista != NULL)
{
printf("Codigo: %s Nombre: %s DNI: %s Nota: %.2f\n",
lista->codigo, lista->nombre, lista->dni, lista->nota);
lista = lista->siguiente;
}
}
void mostrarUltimo(tlista *lista)
{
if (lista == NULL)
{
printf("La lista esta vacia\n");
return;
}
while (lista->siguiente != NULL)
lista = lista->siguiente;
printf("\nUltimo alumno:\n");
printf("Codigo: %s Nombre: %s DNI: %s Nota: %.2f\n",
lista->codigo, lista->nombre, lista->dni, lista->nota);
}3. Atletas: ficheros de texto, lectura con fscanf y modificación de caracteres
Se define la estructura tatleta, se graba un fichero de texto, se lee con fscanf mostrando los atletas con tiempo mayor o igual a 2.00, y se crea un fichero auxiliar donde se sustituye la letra 'P' por 'X'.
typedef struct
{
int numero;
char nombre[50];
char dni[20];
float tiempo;
} tatleta;
void grabaTexto(FILE *pf, tatleta *array, int tam);
void leeTexto(FILE *pf);
void cambiaLetra(FILE *pf);
int main()
{
tatleta *array = (tatleta *)malloc(3 * sizeof(tatleta));
if (array == NULL)
{
printf("ERROR: falta memoria\n");
exit(0);
}
array[0].numero = 123;
strcpy(array[0].nombre, "Juan Perez");
strcpy(array[0].dni, "03888777C");
array[0].tiempo = 2.50;
/* Igual con array[1] y array[2] */
FILE *pf = fopen("datos.txt", "w+");
if (pf == NULL)
{
printf("ERROR al abrir fichero\n");
exit(0);
}
grabaTexto(pf, array, 3);
rewind(pf);
leeTexto(pf);
rewind(pf);
cambiaLetra(pf);
rewind(pf);
printf("\nDATOS MODIFICADOS:\n");
leeTexto(pf);
fclose(pf);
free(array);
return 0;
}
void grabaTexto(FILE *pf, tatleta *array, int tam)
{
for (int i = 0; i < tam; i++)
{
fprintf(pf, "Numero: %d Nombre: %s DNI: %s Tiempo: %.2f\n",
array[i].numero, array[i].nombre, array[i].dni, array[i].tiempo);
}
printf("Fichero grabado correctamente\n");
}
void leeTexto(FILE *pf)
{
tatleta aux;
char palabra1[20];
char palabra2[20];
printf("\nATLETAS CON TIEMPO >= 2.00\n");
fscanf(pf, "%s %d %s %s %s %s %s %f",
palabra1, &aux.numero, palabra2, aux.nombre,
palabra2, aux.dni, palabra2, &aux.tiempo);
while (!feof(pf))
{
if (aux.tiempo >= 2.00)
{
printf("%d %s %s %.2f\n", aux.numero, aux.nombre, aux.dni, aux.tiempo);
}
fscanf(pf, "%s %d %s %s %s %s %s %f",
palabra1, &aux.numero, palabra2, aux.nombre,
palabra2, aux.dni, palabra2, &aux.tiempo);
}
}
void cambiaLetra(FILE *pf)
{
FILE *pf2 = fopen("auxiliar.txt", "w");
if (pf2 == NULL)
{
printf("ERROR\n");
return;
}
char c;
c = fgetc(pf);
while (!feof(pf))
{
if (c == 'P')
{
c = 'X';
}
fputc(c, pf2);
c = fgetc(pf);
}
fclose(pf2);
printf("\nCambios realizados correctamente\n");
}4. Lista enlazada de atletas: inserción al inicio y penúltimo nodo
La función inserta añade cada nuevo nodo al principio de la lista. muestra imprime todos los nodos y verPenultimo muestra el penúltimo.
typedef struct lista
{
int numero;
char nombre[50];
char dni[20];
float tiempo;
struct lista *siguiente;
} tlista;
void inserta(tlista reg, tlista **plista);
void muestra(tlista *q);
void verPenultimo(tlista *q);
int main()
{
tlista *lista = NULL;
tlista array[3] =
{
{123, "Juan Perez", "03888777C", 2.50, NULL},
{124, "Pedro Lopez", "03555666N", 2.20, NULL},
{125, "Jorge Martinez", "03222444Z", 1.70, NULL}
};
for (int i = 0; i < 3; i++)
{
inserta(array[i], &lista);
}
muestra(lista);
verPenultimo(lista);
return 0;
}
void inserta(tlista reg, tlista **plista)
{
tlista *q = (tlista *)malloc(sizeof(tlista));
if (q == NULL)
{
printf("ERROR: falta memoria\n");
return;
}
q->numero = reg.numero;
strcpy(q->nombre, reg.nombre);
strcpy(q->dni, reg.dni);
q->tiempo = reg.tiempo;
q->siguiente = *plista;
*plista = q;
}
void muestra(tlista *q)
{
printf("DATOS DE LA LISTA:\n");
while (q != NULL)
{
printf("%d %s %s %.2f\n", q->numero, q->nombre, q->dni, q->tiempo);
q = q->siguiente;
}
}
void verPenultimo(tlista *q)
{
while (q->siguiente->siguiente != NULL)
{
q = q->siguiente;
}
printf("\nPENULTIMO NODO:\n");
printf("%d %s %s %.2f\n", q->numero, q->nombre, q->dni, q->tiempo);
}5. Operaciones sobre listas enlazadas
Se incluyen funciones para insertar en medio de la lista, borrar el primer y el último nodo, mostrar el primer y el último nodo, mostrar un registro concreto y modificar un número en un fichero binario.
typedef struct lista
{
int numero;
char nombre[50];
char dni[20];
float tiempo;
struct lista *siguiente;
} tlista;
/* Inserta un nodo detrás del nodo con numero == numbuscar */
void insertarMedio(tlista reg, tlista *q, int numbuscar)
{
while (q != NULL && q->numero != numbuscar)
{
q = q->siguiente;
}
if (q == NULL)
{
printf("No encontrado\n");
return;
}
tlista *nuevo = (tlista *)malloc(sizeof(tlista));
if (nuevo == NULL)
{
printf("ERROR\n");
return;
}
nuevo->numero = reg.numero;
strcpy(nuevo->nombre, reg.nombre);
strcpy(nuevo->dni, reg.dni);
nuevo->tiempo = reg.tiempo;
nuevo->siguiente = q->siguiente;
q->siguiente = nuevo;
}
void borrarPrimero(tlista **plista)
{
if (*plista == NULL)
{
printf("Lista vacia\n");
return;
}
tlista *q = *plista;
*plista = (*plista)->siguiente;
free(q);
printf("Primer nodo borrado\n");
}
void borrarUltimo(tlista **plista)
{
if (*plista == NULL)
{
printf("Lista vacia\n");
return;
}
if ((*plista)->siguiente == NULL)
{
free(*plista);
*plista = NULL;
return;
}
tlista *q = *plista;
while (q->siguiente->siguiente != NULL)
{
q = q->siguiente;
}
free(q->siguiente);
q->siguiente = NULL;
printf("Ultimo nodo borrado\n");
}
void mostrarPrimero(tlista *q)
{
if (q == NULL)
{
printf("Lista vacia\n");
return;
}
printf("PRIMER NODO:\n");
printf("%d %s %s %.2f\n", q->numero, q->nombre, q->dni, q->tiempo);
}
void mostrarUltimo(tlista *q)
{
if (q == NULL)
{
printf("Lista vacia\n");
return;
}
while (q->siguiente != NULL)
{
q = q->siguiente;
}
printf("ULTIMO NODO:\n");
printf("%d %s %s %.2f\n", q->numero, q->nombre, q->dni, q->tiempo);
}
void mostrarUno(tlista *q, int numbuscar)
{
int encontrado = 0;
while (q != NULL)
{
if (q->numero == numbuscar)
{
printf("%d %s %s %.2f\n", q->numero, q->nombre, q->dni, q->tiempo);
encontrado = 1;
}
q = q->siguiente;
}
if (!encontrado)
{
printf("Registro no encontrado\n");
}
}
/* Modifica el numero de un atleta en un fichero binario */
void cambiaNumero(char *fichero, int buscar, int nuevo)
{
FILE *f;
tAtleta a;
f = fopen(fichero, "r+b");
if (f == NULL)
{
printf("Error al abrir fichero\n");
return;
}
while (fread(&a, sizeof(Atleta), 1, f) == 1)
{
if (a.numero == buscar)
{
a.numero = nuevo;
fseek(f, -sizeof(Atleta), SEEK_CUR);
fwrite(&a, sizeof(Atleta), 1, f);
break;
}
}
fclose(f);
}