我遇到了在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行。
我不是编程专家(一直是我需要学习的人),所以非常感谢帮助解决这个问题。谢谢!
答案 0 :(得分:1)
您的fscanf()
指令有问题。
建议%lf
代替%7lf
。
fprintf()
"%7.3f"
使用至少 7个字符打印浮点数,并根据需要使用' '
填充。
您在"%7lf"
中随后使用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
之间添加空格不会改变功能。
答案 1 :(得分: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的错误,读取在Windows中以二进制文件打开的UNIX文本文件(\n
)模式"r"
并使用fscanf()
最佳阅读文本文件"rt"
。没有发现任何东西指向第123行或其邻居作为问题区域。