Issues reading then printing from File I/O with structs

前端 未结 1 748
旧时难觅i
旧时难觅i 2021-01-28 11:40

I\'m trying to read a CSV file and print out select values from said file, all of them strings (with one char at the end) and I\'m having trouble actually printing it out. It\'s

相关标签:
1条回答
  • 2021-01-28 12:28

    Your code is strange, with your posted code you shouldn't be able to write anything in fin, because you opened it for reading only.

    FILE * fin = fopen("florida.csv", "rw");
    
    if((fin = fopen("florida.csv", "r")) == NULL)
    ...
    

    You opened it once for read/write and the reopen it again using the same FILE* variable, the read/write handle is lost. The fprintf(fin, ...) calls should return -1.

    The second problem is:

    while(fscanf(fin, "%s", buffer) != EOF){
        airdata * entry = malloc(sizeof(airdata));
        fprintf(fin, "%s%s%s%s%s%*s%*s%*s%s%s%*s%*s%c%*s%*s", entry->siteNum, entry->LocalID,
                entry->portName, entry->city, entry->state, entry->lat, entry->lon, entry->Tower);
        printf("%s%s%s%s%s%*s%*s%*s%s%s%*s%*s%c%*s%*s", entry->siteNum, entry->LocalID,
            entry->portName, entry->city, entry->state, entry->lat, entry->lon, entry->Tower);
    }
    

    You allocate memory for an airdata object in every loop, but it is always uninitialized, so you will get garbage when you print its members. Also fin is opened for reading only, the write operation will fail. You are not freeing the memory either, so you are leaking memory on ever loop iteration. Lastly you don't check if malloc returns NULL.

    Note that the fscanf call will only get you the next word, not the whole line, that's it because %s matches a sequence of non-white-space characters.

    The output you've shown us in the question is not possible with your code.

    Regardless, you should do the parsing in a different way. Read the whole line with fgets and then use strtok to get the values:

    int main(void)
    {
        airdata **entries = NULL, **tmp;
        size_t num_of_entries = 0;
        char buffer[1024];
        const char *delim = ",\r\n";
    
        while(fgets(buffer, sizeof buffer, fin))
        {
            tmp = realloc(entries, sizeof *entries);
            if(tmp == NULL)
            {
                // one possible error handling
                fclose(fin);
                free_airdata_array(entries, num_of_entries);
                return 1;
            }
    
            entries = tmp;
    
            airdata *data = calloc(1, sizeof *data);
    
            if(data == NULL)
            {
                fclose(fin);
                free_airdata_array(entries, num_of_entries);
                return 1;
            }
    
            // parsing
            char **params[] = {
                &data->siteNum,
                &data->LocalID,
                &data->portName,
                &data->city,
                &data->state,
                &data->lat,
                &data->lon,
            };
    
            char *input = buffer, *token;
    
            for(size_t i = 0; i < sizeof params / sizeof *params; ++i)
            {
                token = strtok(input, delim);
                if(token == NULL)
                {
                    flcose(fin);
                    free_airdata_array(entries, num_of_entries);
                    free_airdata(data);
                    return 1;
                }
    
                *params[i] = strdup(token);
    
                if(*params[i] == NULL)
                {
                    flcose(fin);
                    free_airdata_array(entries, num_of_entries);
                    free_airdata(data);
                    return 1;
                }
    
                input = NULL; // subsequent calls of strtok expect NULL
            }
    
            token = strtok(NULL, delim);
            if(token == NULL)
                data->Tower = 0;
            else
                data->Tower = *token;
    
            entries[num_of_entries++] = data;
        }
    
        fclose(fin);
        do_something_with_the(entries, num_of_entries);
    
        free_airdata_arra(entries);
    
        return 0;
    }
    

    And the free functions:

    void free_airdata_array(airdata **array, size_t num_of_entries)
    {
        if(array == NULL)
            return;
    
        for(size_t i = 0; i < num_of_entries; ++i)
            free_airdata(array[i]);
    
        free(array);
    }
    
    void free_airdata(airdata *data)
    {
        if(data == NULL)
            return;
    
        char **params[] = {
            &data->siteNum,
            &data->LocalID,
            &data->portName,
            &data->city,
            &data->state,
            &data->lat,
            &data->lon,
        };
    
        for(size_t i = 0; i < sizeof params / sizeof *params; ++i)
            free(*params[i]);
    
        free(data);
    }
    

    If your system does not have strdup:

    char *strdup(const char *text)
    {
        if(text == NULL)
            return NULL;
    
        char *ret = malloc(strlen(text) + 1);
        if(ret == NULL)
            return NULL;
    
        return strcpy(ret, text);
    }
    
    0 讨论(0)
提交回复
热议问题