读取文件:如何使用fscanf移动文件指针以及scanf / fscanf如何使用缺少的%类型

时间:2014-07-02 05:23:49

标签: c++ c string pointers

我对C中的文件处理非常陌生,我想问几个问题!

  1. 我正在使用fscanf / fget将文件转换为不同的格式。但是我不太清楚fscanf和fgets之间的区别。
  2. 特别是,我不确定fscanf()和fgets()是否会逐行自动递增文件指针。根据我对测试和文档的理解,fscanf()一次只能将文件指针移动1个字符/类型;但fgets()似乎逐行读取文件(因为它遇到换行符时终止)。从文档中,fscanf()将忽略任何空格字符。那么这是否意味着即使我有逐行输入文件,fscanf将无法逐行读取它?即使我指定了确切的格式,换行符也不会被保留?

    1. 使用所有fscanf / scanf()/ sscanf(),我不确定如何解析字符串。
    2. 特别是,如果一行包含10个非空白部分(单词,整数,双精度等),但我只指定其中3个被读入变量(使用%*或者根本不放任何东西) ),这些读取函数会做什么?

      例如,我的输入文件如下所示:

       9      opls_182         9    DNP      CT       9    0.140     12.0110
      10      opls_182        10    DNP      CT      10    0.140     12.0110
      11      opls_145        11    DNP      CA      11   -0.115     12.0110   
      12      opls_145        12    DNP      CA      12   -0.115     12.0110 
      

      我只想阅读opls_182和CT和9部分(第2,第5和第6列)。 使用fgets()和sscanf(),我会这样写:

      fgets(fp,500,buffer);
      
      sscanf(buffer, "%*s %s %*d %*s %s %d %*f %*f", variables);
      or this:
      sscanf(buffer, "%*s %s %*d %*s %s %d %*s", variables);
      or this:
      sscanf(buffer, "%*s %s %*d %*s %s %d", variables);
      

      这三个功能是否会以相同的方式工作?那么在第二个版本中,最后一个%* s会解析整个最后两列,还是只解析最后一列? (%s似乎从非白色空格字符开始到非白色空格字符)。

      如果我有比每行中的部分更多的说明符怎么办?是否会出现错误或额外变量只保持0 /空?

      如果我使用fscanf(),只有第一个版本能正常工作,而第二个和第三个版本会弄乱读数,因为fscanf()不会自动跳转,对吗?

      1. 这个问题涉及一个模式:[债券] 387
      2. scanf函数中的所有格式说明符都将忽略空格字符。但是,如果我想跳过第一部分([bonds])并读取最后一个整数,有没有办法做一些像%* some_format%d(忽略直到找到整数)? %[^ format]会工作吗?我尝试了%[^%d]或%[^ d],要么只停留在角色" d"并给予" [bon"。我知道您可以使用%[^]指定要排除的字符数,但是,如果该数字在整个文件中发生变化,则无法使用此方法。

        1. 如果所有部件连接在一起没有空格,scanf能否区分不同的格式。示例:9opls_182DNPCT91.40STUI8。模式%d%s%d%s%f%s%d读出:9,opls_,182,DNPCT,91.40,STUI,8?
        2. 我发现C中的读/写功能非常强大,但要做到这一点也很棘手。非常感谢你们!

1 个答案:

答案 0 :(得分:0)

  1. 规则非常简单:fgets()读取整行,除非行的长度超过提供的缓冲区,在这种情况下,它会尽可能多地读取。另一方面,fscanf()读取你告诉它的内容,跳过前面的空格。例如,给定一行"1 2 3"(不带引号),fgets()将读取整行,而fscanf(fp, "%d %d", &i1, &i2)将读取两个整数并将它们存储到提供的地址,并留下{{1 (注意包括空格)未读。

  2. 在第二次" 3"调用中,最后一个sscanf()仅解析第二列到最后一列。如果你想跳过所有内容直到行尾,请使用%*s之类的内容。你是正确的,如果你使用%*[^\n],只有第一个版本可以做你想要的,因为fscanf将换行视为另一个空格。您仍然可以使用fscanf()格式说明符修复fscanf()版本。

  3. %*[^\n]无法“搜索”输入,它必须始终根据指定的格式进行解析。没有相当于scanf正则表达式的格式。

  4. 您的.*调用将无法执行您想要的操作,因为scanf的第一个实例会占用剩余的字符串,因此只会处理两个格式字符。但是,如果您将%s替换为%s,它将完全符合您的要求(对于此输入)。