从具有结构的文件I/O读取然后打印的问题 [英] Issues reading then printing from File I/O with structs

查看:51
本文介绍了从具有结构的文件I/O读取然后打印的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试读取CSV文件并打印出所述文件中的选择值,所有这些值都为字符串(末尾带有一个字符),而实际上无法打印出来.应该忽略输入中的特定数据,例如ASO,ORL,PR,并且当然跳过空白区域.我不知道这是文件I/O的问题还是打印错误.有人可以帮忙吗?

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 supposed to ignore specific data from the input, like ASO,ORL,PR, and of course skip over the empty spaces. I don't know if it's a problem with the File I/O or I'm printing it wrong. Can anyone help?

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




typedef struct airdata{
    char *siteNum;
    char *LocalID;
    char *portName;
    char *city;
    char *state;
    char *lat;
    char *lon;
    char Tower;
} airdata;

int main(){
    FILE * fin = fopen("florida.csv", "rw");

    if((fin = fopen("florida.csv", "r")) == NULL){
        printf("etl ERROR: File inputFile not found.\n");
        return(0);
    }
    printf("\nFile opened successfully\n\n");
        printf("%-12s %-11s %-42s %-34s %-3s %-15s %-16s Tower\n",
                "FAA Site", "Short Name", "Airport Name", "City", "ST",
                "Latitude", "Longitude");

        printf("%-12s %-11s %-42s %-34s %-3s %-15s %-16s =====\n",
                "========", "==========", "============", "====", "==",
                "========", "=========");

            char buffer[1000];
            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);
        }

        fclose(fin);
}

这是输入和输出

IN:
03010.1*A,63FD,LINK FIELD,ALACHUA,FL,ASO,ORL,PR,29-41-53.0000N,082-29-29.0000W,PR,,NON-NPIAS,,N,,,2,0

OUT: 
03010.1*A    63FD        LINK FIELD                                 ALACHUA                            FL  29-41-53.0000N  082-29-29.0000W  N

有人可以帮我吗?

推荐答案

您的代码很奇怪,使用已发布的代码,您将无法在其中编写任何内容 fin,因为您将其打开仅供阅读.

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)
...

您一次打开它以进行读/写,然后使用相同的FILE*再次将其重新打开 变量,读/写句柄丢失. fprintf(fin, ...)调用应 返回-1.

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.

第二个问题是:

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);
}

在每个循环中为airdata对象分配内存,但始终 未初始化,因此在打印其成员时会出现垃圾.同时打开fin仅供阅读, 写入操作将失败.您也没有释放内存,所以您 在Ever循环迭代中泄漏内存.最后,您无需检查malloc 返回NULL.

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.

请注意,fscanf调用只会让您得到下一个单词,而不是整行, 就是因为%s与一系列非空格字符匹配.

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.

无论如何,您都应该以其他方式进行解析.阅读整行 fgets,然后使用strtok来获取值:

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;
}

free功能:

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);
}

如果您的系统没有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);
}

这篇关于从具有结构的文件I/O读取然后打印的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆