如何使用 C 中的 fscanf() 来读取 .gro 文件?

How can fscanf(), in C, be used to read a .gro file?

我正在尝试通过 C 代码读取以下 gro 文件。

FJP in Pol Water in water t=   0.00000 step= 0
   16
    1FJP      P    1   5.346   7.418   0.319
    2FJP      P    2   5.151   7.405   0.499
    3FJP      P    3   5.260   7.178   0.428
    4FJP      P    4   5.159   6.961   0.342
    5FJP      P    5   5.355   6.909   0.220
    6FJP      P    6   5.169   6.824   0.043
    7FJP      P    7   5.068   6.669  11.454
    8FJP      P    8   4.919   6.861  11.482
    9FJP      P    9   4.835   7.075  11.364
   10FJP      P   10   4.738   6.987  11.197
   11FJP      P   11   4.847   7.115  10.993
   12FJP      P   12   4.642   7.126  10.870
   13FJP      P   13   4.680   6.940  10.674
   14FJP      P   14   4.521   7.052  10.545
   15FJP      P   15   4.321   6.973  10.513
   16FJP      P   16   4.315   6.728  10.516
  11.56681  11.56681  11.56681

我的代码是:

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

int main(int argc, const char * argv[])
{
    char input_file[]="file.gro";

    FILE *input;
    char *myfile=malloc(sizeof(char)*80);

    sprintf(myfile,"%s",input_file); //the .gro file being read in
    input=fopen(myfile,"r");

double dummy1,dummy6,dummy7,dummy8,dummy9,dummy10,dummy11;
int dummy2,dummy3,dummy4,dummy5;

int lines=0;

  while (fscanf(input,"FJP in Pol Water in water t=   %lf step= %d",&dummy1,&dummy2)==2
    ||fscanf(input,"   %d\n",&dummy3)==1
    ||fscanf(input,"    %dFJP      P    %d   %lf   %lf   %lf\n",
        &dummy4,&dummy5,&dummy6,&dummy7,&dummy8)==5
    ||fscanf(input,"  %lf  %lf  %lf\n",&dummy9,&dummy10,&dummy11)==3)
  {
    printf("%lf %d\n",dummy1,dummy2);
    printf("%d\n",dummy3);
    printf("%d %d\n",dummy4,dummy5);
    printf("%lf %lf %lf\n",dummy6,dummy7,dummy8);
    printf("%lf %lf %lf\n",dummy9,dummy10,dummy11);

    lines=lines+1;
  }

  printf("lines=%d\n",lines);

    fclose(input);
}

问题是各种虚拟变量打印的值与文件中的值不匹配。此外,读取的行数是 3,而不是与文件匹配的 19。我不确定读取此文件的 fscanf() 语句有何不正确之处。对此问题的任何帮助将不胜感激。

您的主要问题是您假设 scanf 比实际情况要好。

Scanf 将读取和解析尽可能多的参数,然后放弃。它不会倒退到 scanf 的开始。它还将空格和换行符(和制表符)视为简单的 "skip all whitespace"

所以printf("%d\n",dummy3)行会尝试解析主线,例如1FJP

它会将数字 1 OK 读入 dummy3,但随后会卡住,因为 P != 空格。

然后所有其他规则都将卡住,因为其中 none 个规则首先需要 P 或任何字符串。

如果你想这样做,你只需要在预期的时候更智能地应用 scanf 语句。

问题是您尝试重复读取和匹配 header,在读取每一行之前(在 while 循环中)您应该读取一次头部,然后读取行。您也只需要跳过任何给定的空白片段一次。所以你最终得到这样的代码:

if (fscanf(input,"FJP in Pol Water in water t=%lf step=%d%d", &dummy1, &dummy2, &dummy3) != 3) {
    fprintf(stderr, "Invalid header\n");
    exit(1); }
while (fscanf(input,"%dFJP P%d%lf%lf%lf", &dummy4, &dummy5, &dummy6, &dummy7, &dummy8) == 5)  {
    ... read a line of the table