【问题标题】:Is there a more efficient way of reading a formatted file in C than I have done?有没有比我用 C 读取格式化文件更有效的方法?
【发布时间】:2010-12-25 21:43:34
【问题描述】:

我需要读取一个看起来像这样的格式化文件。

代码:HARK

姓名:奥斯卡

MRTE:火车

目前我的代码如下所示。

FILE *file;
char unneeded[10];
char whitespace[2];
char actual[10];
file = fopen("scannertest.txt","r");
fscanf(file,"%s",unneeded); // this is the identifier and the colon (code:)
fscanf(file,"%[ ]",whitespace); // this takes in the white space after the colon.
fscanf(file,"%s",actual); // this is the value I actually need.
/**
* Do stuff with the actual variable
**/
fclose(file);

这种方法对我有用,但我不认为为文本文件中的每一行编写三个 fscanf() 是最好的方法,尤其是因为我稍后会在循环中这样做。

我试着这样做:

fscanf(file, "%s %[ ] %s",unneeded,whitespace,real);

但是,当我尝试打印输出时,这给了我奇怪的符号。

【问题讨论】:

    标签: c file-io whitespace scanf


    【解决方案1】:

    %s scanf 说明符已经忽略了空格。如果你这样做了

    scanf("%s%s", unneeded, actual)
    

    输入是“代码:HARK”,unneeded 将具有“代码:”,actual 将具有“HARK”。

    警告:scanf 是一个麻烦的功能(它“难以”安全使用)。如果您想要更安全,请指定您愿意在每个字符串中接受的最大字符数(记住零终止符)

    scanf("%9s%9s", unneeded, actual); /* arrays defined with 10 elements */
    

    最好使用fgets,然后使用sscanf

    在阅读对另一个答案的评论后进行编辑

    记住*总是*检查scanf的返回值。

    chk = scanf("%9s%9s", unneeded, actual);
    if (chk != 2) /* error reading data */;
    

    【讨论】:

      【解决方案2】:

      在 C 中,文件函数使用缓冲 I/O。这意味着 fscanf 不会在每次调用时都访问磁盘,因此使用 3 次调用而不是 1 次调用的性能损失应该可以忽略不计。

      然而,最好的办法是让您的程序运行起来,然后如果它太慢,请测量性能瓶颈在哪里,并首先解决这些问题。尝试猜测哪些代码段会导致性能问题是不值得的。

      【讨论】:

        【解决方案3】:

        您的代码不起作用,因为

        fscanf(file,"%s",unneeded);
        fscanf(file,"%[ ]",whitespace);
        fscanf(file,"%s",actual);
        

        不做同样的事情

        fscanf(file,"%s %[ ] %s", unneeded, whitespace, actual);
        

        功能相同

        fscanf(file,"%s%[ ]%s", unneeded, whitespace, actual); // No spaces in fmt string
        

        HTH

        【讨论】:

          【解决方案4】:

          如果您正在寻找加快代码速度的方法,您可以读取整个文件或文件的缓冲区。一次读取整个块比根据需要读取数据要快。

          然后您可以在您读取的缓冲区上使用sscanf

          【讨论】:

          • 我尝试在 fgets() 上使用 sscanf,我就是这样。 fgets(行,20,文件); sscanf(line,"%s %[ ] %s,unneeded,whitespace,actual); 但这仍然给了我同样的问题,变量中有奇怪的符号。
          • 如果您看到奇怪的符号,听起来更像是溢出了缓冲区。一定要检查 sscanf 的返回值,这样你就知道它实际上读取了一些东西。
          【解决方案5】:

          我是一个病态的人,时不时地想念用 C 编写代码。我写了一些似乎有效的东西:

          test.txt 的内容

          Code: HARK
          Name: Oscar
          MRTE: Train
          

          text.c 的内容

          #include <stdio.h>
          
          #define MAX_LEN 256
          
          int main(void)
          {
            FILE *file;
            char str_buf[MAX_LEN + 1]; // One extra byte needed
                                       // for the null character
            char unneeded[MAX_LEN+1];
            char actual[MAX_LEN+1];
          
          
            file = fopen("test.txt","r");
          
            while(fgets(str_buf, MAX_LEN + 1, file) != NULL)
            {
              sscanf(str_buf, "%s%s", unneeded, actual);
              printf("unneeded: %s\n", unneeded);
              printf("actual: %s\n", actual);
            }
          
            return 0;
          }
          

          编译后的代码输出:

          unneeded: Code:
          actual: HARK
          unneeded: Name:
          actual: Oscar
          unneeded: MRTE:
          actual: Train
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-21
            • 1970-01-01
            • 2012-03-02
            • 1970-01-01
            • 1970-01-01
            • 2014-08-04
            相关资源
            最近更新 更多