2

我在读取 Windows NT 4.0 dll 文件中的 txt 文件时遇到问题;在您问之前,我目前对将其迁移到新操作系统不感兴趣。我只想解决这个问题,让我之后的其他人担心迁移这个超级遗留软件。

使用fscanf读取txt文件时出现问题,如图:

infile_ptr = fopen("c:\\LumaGem\\orbit.txt", "r");
byteoffset=0;
while(!feof(infile_ptr) )
    {   
        r=0.0; s1=0.0; s2=0.0; e1=0.0; e2=0.0; e3=0.0; d=0.0; f=0.0;
        fseek(infile_ptr, byteoffset, SEEK_SET);
        fscanf(infile_ptr,"%7lf %7lf %7lf %7lf %7lf %7lf %7lf %7lf", &r, &s1, &s2, &e1, &e2, &e3, &d, &f);

        byteoffset=0; byteoffset = ftell(infile_ptr);
     }
fclose(infile_ptr);  

使用 MATLAB 创建的 txt 文件由 128 行、每列 8 列组成,由 5 个空格分隔,并且在 MATLAB 中的格式如下:

fprintf(fid,'%7.3f     %7.3f     %7.3f     %7.3f     %7.3f     %7.3f     %7.3f     %7.3f \n', variables);

这段代码不是我写的,工作了好几年。然而,最近我们不得不重建/重新安装 Windows NT 4.0 操作系统和软件,现在我得到一个奇怪的错误。该程序使用顶部提供的代码很好地读取 txt 文件,直到它到达第 123 行,此时它读取第 8 列两次,导致所有后续变量移动一个位置,完全搞砸了最后一个程序的几行。有趣的是,这个问题可以通过手动将前 123 行批量复制并粘贴到一个新的 txt 文件中,然后将最后几行一个接一个地粘贴到同一个新的 txt 文件中并将其用作输入(复制完成在写字板内的 NT 机器上)。这样做可以消除这种双重阅读问题。我不知道什么问题会导致这个错误,但也让它通过这种奇怪/笨拙的方法来修复。新旧输入都会出现问题,所以我认为输入文件不是问题,因为它们没有改变。

哦,另外,如果我更改 txt 文件中每列之间的空格数,错误的位置会发生变化。将其减少到 1 个空格会导致错误发生在第 120 行左右,而增加空格数(尝试 7 个而不是 5 个)会将错误推低到第 124 行。

我不是编程专家(一直是按需学习的人),因此非常感谢您帮助解决这个问题。谢谢!

4

2 回答 2

1

你的fscanf()指令有问题。
推荐%lf而不是%7lf.

您的fprintf()with使用至少"%7.3f"7 个字符打印出浮点数,并根据需要进行填充。' '

您随后使用"%7lf"in表示最多fscanf()扫描7 个字符。因此,当您 printf/scanf 999.999 一切正常,但数字更大(例如 1000.007)时,您的扫描将输入“1000.00”并将“7”留给下一个。"%7lf"

 int main(void) {
  char buf[1000];
  double f1, f2;
  int r;
  sprintf(buf, "%7.3f %7.3f", 1.23, 4.56);
  r = sscanf(buf, "%7lf %7lf", &f1, &f2);
  printf("'%s'\n%d %g %g\n", buf, r, f1, f2);

  sprintf(buf, "%7.3f %7.3f", 999.999, 4.56);
  r = sscanf(buf, "%7lf %7lf", &f1, &f2);
  printf("'%s'\n%d %.10g %.10g\n", buf, r, f1, f2);

  sprintf(buf, "%7.3f %7.3f", 1000.007, 4.56);
  r = sscanf(buf, "%7lf %7lf", &f1, &f2);
  printf("'%s'\n%d %.10g %.10g\n", buf, r, f1, f2);

  return 0;
}

Output:  
'  1.230   4.560'  
2 1.23 4.56  
'999.999   4.560'  
2 999.999 4.56  
'1000.007   4.560'  
2 1000 7  

顺便说一句:对于fscanf(),"%lf%lf%lf ..."是可以的。在两者之间添加空格%lf不会改变功能。

于 2013-07-20T02:51:49.063 回答
0

候选简化

还没有找到问题根源,但建议这样做以简化调试。这会处理 PC 行结尾、文件指针的过度操作、不必要的限制%7lf并提供更好的错误检查。

FILE *infile_ptr = fopen("c:\\LumaGem\\orbit.txt", "rt");  // PC text file
char buf[1000];
while (fgets(buf, sizeof(buf), infile_ptr)) {  // separate I/O from scanning
  int count = sscanf(buf,"%lf%lf%lf%lf%lf%lf%lf%lf", &r, &s1, &s2, &e1, &e2, &e3, &d, &f);  
  if (count != 8) { // check for correct scan count
    ; //handle error;
  }
}
if (ferror(infile_ptr)) {
  ; //handle error;
}
fclose(infile_ptr);

[编辑] OP 发布原始文本文件。

还要将此行添加到循环中以处理仅包含空格的尾随行。

  if (count <= 0) continue;

[编辑]结论。

fseek()和的使用ftell(),通常与二进制文件一起使用,恕我直言,这里不需要,它是一个 Window 的错误,它读取\n在 Windows 中以二进制模式打开的 UNIX 文本文件 (),"r"并且使用fscanf()哪种方式读取打开的文本文件效果最好"rt"。没有发现任何指向 123 行或其邻居的问题区域。

于 2013-07-22T15:41:21.963 回答