文件 I/O 使用 C 中的结构提取

File I/O Extraction with structures in C

任务是读取一个带有命令行参数的.txt文件,文件中有一个非结构化信息列表every 佛罗里达州的机场 注意 这只是整个文件的一小部分。有些数据必须忽略,例如 ASO ORL PR A 0 18400 - 任何与 AirPdata 中的结构化变量无关的数据。

作业要求站点编号、locID、字段名、城市、州、纬度、经度,以及是否有控制塔。

输入

03406.20*H 2FD7 AIR ORLANDO ORLANDO FL ASO ORL PR 28-26-08.0210N 081-28-23.2590W PR NON-NPIAS N A 0 18400

03406.18*H 32FL MEYER- INC ORLANDO FL ASO ORL PR 28-30-05.0120N 081-22-06.2490W PR NON-NPAS N 0 0

输出

   Site# LocID Airport Name City ST Latitude Longitude Control Tower        
------------------------------------------------------------------------     
03406.20*H 2FD7 AIR ORLANDO ORLANDO FL 28-26-08.0210N 081-28-23.2590W N
03406.18*H 32FL MEYER       ORLANDO FL 28-30.05.0120N 081-26-39.2560W N
etc..      etc. etc..       etc..   .. etc..          etc..           ..
etc..      etc. etc..       etc..   .. etc..          etc..           ..

到目前为止我的代码看起来像

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

typedef struct airPdata{
char *siteNumber;
char *locID;
char *fieldName;
char *city;
char *state;
char *latitude;
char *longitude;
char controlTower;
} airPdata;

int main (int argc, char* argv[])
{

char text[1000];
FILE *fp;
char firstwords[200];


if (strcmp(argv[1], "orlando5.txt") == 0)
{

    fp = fopen(argv[1], "r");
    if (fp == NULL) 
    {
        perror("Error opening the file");
        return(-1);
    }

    while (fgets(text, sizeof(text), fp) != NULL) 
    {
        printf("%s", text);
    }
}
else
    printf("File name is incorrect");


fflush(stdout);
fclose(fp);


}

到目前为止,我能够读取整个文件,然后将非结构化输入输出到命令行。

我想弄清楚的下一件事是逐段提取字符串并将它们存储到结构中的变量中。目前我停留在这个阶段。我查阅了有关 strcpy 和其他字符串库函数、数据提取方法、ETL 的信息,我只是不确定在我的代码中正确使用哪个函数。

我在 java 中使用子字符串做了一些非常相似的事情,如果有办法从大量文本字符串中获取子字符串,并设置关于哪些子字符串保存在什么中的参数变量,这可能会起作用。例如... LocID 的长度永远不会超过 4 个字符,因此任何带有 numerical/letter 组合且长度为四个字母的内容都可以存储到 airPdata.LocID 中。

变量存储在结构中后,我知道我必须使用 strtok 将它们组织在 site#、locID...等下的列表中。但是,这是我最好的猜测这个问题,我很迷茫。

我不知道格式是什么。不能是space-separated,有些字段里面有空格。看起来不像fixed-width。因为你提到 strtok 我将假设它 tab-separated.

您可以使用 strsep 使用它。 strtok has a lot of problems that strsep solves,但 strsep 不是标准 C。我假设这是一些需要标准 C 的作业,所以我会不情愿地使用 strtok

最基本的做法是读取每一行,然后用 strtokstrsep.

将其分成几列
char line[1024];
while (fgets(line, sizeof(line), fp) != NULL) {
    char *column;
    int col_num = 0;
    for( column = strtok(line, "\t");
         column;
         column = strtok(NULL, "\t") )
    {
        col_num++;

        printf("%d: %s\n", col_num, column);
    }
}
fclose(fp);

strtok 很有趣。它保留自己在字符串中的内部状态。第一次调用它时,将您正在查看的字符串传递给它。要获取其余字段,您可以使用 NULL 调用它,它会继续读取该字符串。所以这就是为什么有那个有趣的 for 循环看起来像是在重复自己。

全局状态很危险而且很容易出错。 strsepstrtok_r 解决了这个问题。如果您被告知要使用 strtok,请寻找更好的资源来学习。

现在我们有了每一列及其位置,我们可以用它做我们想做的事了。我将使用 switch 来仅选择我们想要的列。

    for( column = strtok(line, "\t");
         column;
         column = strtok(NULL, "\t") )
    {
        col_num++;

        switch( col_num ) {
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 9:
            case 10:
            case 13:
                printf("%s\t", column);
                break;
            default:
                break;
        }
    }

    puts("");

此时您可以对列进行任何操作。您可以立即打印它们,或将它们放入列表或结构中。

只要记住 column 指向 line 中的内存, line 将被覆盖。如果要存储 column,则必须先复制它。您可以使用 strdup 来做到这一点,但*叹*这不是标准的 C。strcpy 真的很容易使用错误。如果您坚持使用标准 C,请编写您自己的 strdup.

char *mystrdup( const char *src ) {
    char *dst = malloc( (sizeof(src) * sizeof(char)) + 1 );
    strcpy( dst, src );
    return dst;
}