Quiero analizar un archivo .csv del formulario: grade(float), year(int), name(string), county(string), number(int) y no veo mi error:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 300

typedef struct{
    char *name, *county;
    float grade;
    unsigned long int year, number;
}info;

int main(int argc, char **argv)
{
    FILE *fin = fopen("lab3.txt", "r");
    if(!fin)
    {
        fprintf(stderr, "ERROR OPENING THE FILE.\n");
        exit(1);
    }
    char buf[MAX];
    while(fgets(buf, MAX, fin))
    {
        buf[strcspn(buf,"\n")] = '\0'; // remove the trailing newline
        char *fields[6], *word = strtok(buf, ",");
        int i = 0;
        while(word)
        {
            info *array = (info *)malloc(sizeof(info));
            fields[i] = word;
            array->name = strdup(fields[2]);
            array->county = strdup(fields[3]);
            array->grade = atof(fields[0]);
            array->year = atoi(fields[1]);
            array->number = atoi(fields[4]);
            printf("Name : %s | County: %s | Year : %ld | Grade : %f | Number: %ld",array->name, array->county, array->year, array->grade, array->number);
            //printf("Word : %s\n", fields[i]);
            word = strtok(NULL,",");
            i++;
            free(array->county);
            free(array->name);
            free(array);

        }
    }
    fclose(fin);
    return 0;
}

Hay exactamente 5 campos en cada línea, así que quería dividir cada línea en palabras y también usé gdb para verificar qué está mal y el problema parece estar aquí array->name = strdup(fields[2]);. He intentado muchas cosas hasta ahora, he asignado memoria para la matriz y el nombre y el condado, estoy liberando la memoria, entonces, ¿cuál es el error?

c
2
Andrei0408 3 mar. 2021 a las 23:08

1 respuesta

La mejor respuesta

Hay una serie de problemas.

Realmente no necesitas [ni quieres] ni fields ni word. Puede usar realloc para aumentar el tamaño de la matriz y operar directamente en el puntero actual.

Hacer malloc(sizeof(char)), como lo tiene, solo pierde memoria debido al strdup que sigue.

No quieres hacer free al final del ciclo, simplemente mata lo que hiciste strdup.

No expandirá el tamaño de array en cada iteración [usando realloc], por lo que el tamaño de su matriz se mantiene en uno. Y, elimina el valor anterior en cada iteración, por lo que, nuevamente, está perdiendo memoria.

Aquí hay una versión refactorizada:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 300

typedef struct {
    char *name;
    char *county;
    float grade;
    unsigned long int year;
    unsigned long int number;
} info;

#define TOK \
    ({ \
        cp = strtok(bp,","); \
        bp = NULL; \
        cp; \
    })

#define SAVE_S(_sym) \
    arrcur->_sym = strdup(TOK)
#define SAVE_F(_sym) \
    arrcur->_sym = atof(TOK)
#define SAVE_I(_sym) \
    arrcur->_sym = atol(TOK)

int
main(int argc, char **argv)
{
    FILE *fin = fopen("lab3.txt", "r");

    if (!fin) {
        fprintf(stderr, "ERROR OPENING THE FILE.\n");
        exit(1);
    }

    char buf[MAX];
    info *arrbase = NULL;
    int arrcnt = 0;
    int arrmax = 0;
    char *bp;
    char *cp;

    while (fgets(buf, MAX, fin)) {
        // remove the trailing newline
        buf[strcspn(buf, "\n")] = '\0';

        // enlarge array -- use of arrmax limits number of realloc calls
        if (arrcnt >= arrmax) {
            arrmax += 100;
            arrbase = realloc(arrbase,sizeof(*arrbase) * arrmax);
        }

        // point to current array entry
        info *arrcur = &arrbase[arrcnt];

        bp = buf;

        SAVE_S(name);
        SAVE_S(county);
        SAVE_F(grade);
        SAVE_I(year);
        SAVE_I(number);

        printf("Name : %s | County: %s | Year : %ld | Grade : %f | Number: %ld",
            arrcur->name, arrcur->county, arrcur->year, arrcur->grade,
            arrcur->number);

        ++arrcnt;
    }

    fclose(fin);

    // trim to size used
    arrbase = realloc(arrbase,sizeof(*arrbase) * arrcnt);

    return 0;
}
1
Craig Estey 3 mar. 2021 a las 20:40