c - 使用 C 语言结构进行文件 I/O 提取

标签 c string io data-extraction

任务是使用命令行参数读取 .txt 文件,该文件中有一个非结构化信息列表,列出了佛罗里达州每个机场注意 这只是整个文件的一个片段。有一些数据必须忽略,例如 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 个字符,因此任何具有四个字母长的数字/字母组合的内容都可以存储到 airPdata.LocID 中。

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

最佳答案

我不知道格式是什么。它不能用空格分隔,有些字段中有空格。它看起来不是固定宽度的。因为您提到了 strtok 我将假设它是制表符分隔的。

您可以使用 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,请寻找更好的资源来学习。

现在我们已经有了每一列及其位置,我们可以用它做我们喜欢的事情。我将使用开关来仅选择我们想要的列。

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

关于c - 使用 C 语言结构进行文件 I/O 提取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42193975/

相关文章:

python - 抓取文本文件中未替换标签的行

java - 正则表达式:如何处理空引号

Java:Str_用新行替换字符 "\n"

java - 仅从文件中读取一个整数的最有效习惯用法?

C 程序不给出素数

与 Windows 相比,Linux 上的代码速度较慢

c socket发送大文件时出现broken pipe错误

C - 使用 unsigned int 是否只是糟糕的编码实践?

c++ - While 循环检查中的赋值

python解析文件