Ficheros y listas enlazadas en C: ejemplos prácticos de estructuras, lectura y escritura

Informática y Telecomunicaciones12,27 KB

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(&reg, 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);
}

Descargar

PDF Word HTML