【问题标题】:Parsing a txt file解析一个txt文件
【发布时间】:2013-10-11 06:01:22
【问题描述】:

我正在尝试解析包含以下格式名称的 txt 文件:

"MARY","PATRICIA","LINDA","BARBARA","ELIZABETH",...

这是我写的代码:


#include <stdio.h>
// Names scores
int problem22() {
    FILE *f = fopen("names.txt", "r");
    char name[100];
    fscanf(f, "\"%[^\"]s", name);
    printf("%s\n", name); // MARY
    fscanf(f, "\"%[^\"]s", name);
    printf("%s\n", name); // ,
    fscanf(f, "\"%[^\"]s", name);
    printf("%s\n", name); // PATRICIA
    return 0;
}

int main() {
    problem22();
    return 0;
}

每次调用fscanf 都会给我一个名字,而另一个则浪费在获取逗号上。我尝试了几种格式,但我不知道该怎么做。

谁能帮我正确的格式?

【问题讨论】:

  • 看起来你的代码按照你的意愿工作,你想要什么?
  • 在这种情况下你应该试试 strtok()
  • @GrijeshChauhan:我希望每次调用fscanf 获取名称。
  • @xylon97 注意 "\"%[^\"]s" , s 不需要

标签: c parsing scanf


【解决方案1】:

将输入格式字符串更改为"%*[,\"]%[^\"]" 可以满足您的要求:

fscanf(f, "%*[,\"]%[^\"]", name);
printf("%s\n", name); // MARY
fscanf(f, "%*[,\"]%[^\"]", name);
printf("%s\n", name); // PATRICIA
fscanf(f, "%*[,\"]%[^\"]", name);
printf("%s\n", name); // LINDA

%* 只是跳过匹配的输入。

【讨论】:

  • 绝对精彩[+1]。您能否给我们更多信息,我们可以在哪里找到如何制作转义序列的信息。使用 scanf 或 fscanf,我们是否应该使用带有 %* 的普通 PCRE 正则表达式如果匹配则转义
  • @Gangadhar 与%*%s 相同,只是丢弃了输入。
  • @villekulla 注意%[^\"]s" 不需要
  • @Gangadhar PCRE 正则表达式不受支持。
  • @villekulla 我看到你是新人,但对 SO 有很好的贡献,请继续保持 :).. 要了解 scanf/printf 的行为,我想分享a link with you(可能你已经知道)。我会改正的,但是有人连续对我投了反对票,所以现在要唱了:( ...
【解决方案2】:

我总是喜欢使用strtok()strtok_r() 函数来解析文件。 (要么更喜欢使用一些 csv 库)。

但只是为了好玩,我写了一个代码可能是你喜欢的,我没有在我的答案中发布代码,而是检查 @codepad 的输出,仅适用于特定格式。

使用 strtok()

在我看来,正确的方法如下所示:

int main(){
// while(fp, csv, sizeof(csv)){   
    // First read into a part of file  into buffer
    char csv[] = "\"MARY\",\"PATRICIA\",\"LINDA\",\"BARBARA\",\"ELIZABETH\"";
    char *name = "", 
       *parse = csv;
    while(name = strtok(parse, "\",")){
        printf(" %s\n", name);
        parse = NULL;
    }
    return 0;
} // end while 

检查codepade 的输出:

 MARY
 PATRICIA
 LINDA
 BARBARA
 ELIZABETH

我在第二个代码中建议绘制一个外部循环以将行从文件读取到临时缓冲区,然后应用 strtok() 代码,例如:while(fgets(fp, csv, sizeof(csv))){ use strtok code}

【讨论】:

  • 所以你假设整个文件在解析之前被读入内存?
【解决方案3】:

你必须使用 fseek()

此代码成功运行:

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

int problem22()
{
    FILE *f = fopen("names.txt", "r");
    char name[100];
    int pos = 0, maxnames = 4, n;

    for(n = 0; n <= maxnames; n++)
    {
        fseek(f, pos, 0);
        fscanf(f, "\"%[^\"]s", name);
        printf("%s\n", name);
        pos += (strlen(name) + 3);
    }
    return 0;
}

int main()
{
    problem22();
    return 0;
}

【讨论】:

    【解决方案4】:

    您可以使用strtok() 读取整行并使用 delin 字符串 "," 将其拆分为标记

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    // Names scores
    int problem22() {
        FILE *f = fopen("file", "r");
        char *tok=NULL;
        char name[100];
        fscanf(f,"%s",name);
    
        printf("string before strtok(): %s\n", name);
        tok =  strtok(name, ",");
        while (tok) {
            printf("Token: %s\n", tok);
            tok = strtok(NULL, ",");
        }
    
    
    return 0;
    }
    
    int main() {
        problem22();
        return 0;
    }
    

    注意:strtok() 函数在解析时使用静态缓冲区,因此它不是线程安全的。如果这对您很重要,请使用 strtok_r()

    man strtok_r

    【讨论】:

      猜你喜欢
      • 2011-07-15
      • 1970-01-01
      • 2015-10-06
      • 1970-01-01
      • 1970-01-01
      • 2014-03-28
      • 2016-10-29
      • 1970-01-01
      • 2016-04-07
      相关资源
      最近更新 更多