gpt4 book ai didi

C fscanf 返回错误值

转载 作者:行者123 更新时间:2023-12-02 08:23:16 28 4
gpt4 key购买 nike

我真的卡在某事上了。

我有一个文本文件,其中有 1 个单词后跟 ~100 个 float 。 float 由空格、制表符或换行符分隔。这种格式在整个文本文件中重复多次。

例如,这是文本文件的样子:

one 0.00591 0.07272 -0.78274 ... 
0.0673 ...
0.0897 ...
two 0.0654 ...
0.07843 ...
0.0873 ...
three ...
...
...

这是我的代码片段:

char word[30];
double a[1000];
double j;

while (!feof(fp))
{
fscanf(fp, "%s", word);
printf("%s\n", word);
while (!feof(fp) && (fscanf(fp, " %lf", &j)) == 1)
{
a[z] = j;
z++;
num_of_vectors++;
}
z = 0;
}

文本文件中的单词“nine”打印为“ne”。而且“in”这个词甚至没有打印出来,而是打印了一个 float 。

我做错了什么?

如有任何帮助,我们将不胜感激。

谢谢。

最佳答案

按照标准:

An input item is defined as the longest sequence of input characters which does not exceed any specified field width and which is, or is a prefix of, a matching input sequence.

nine 给你 ne 的可能原因是,当读取 double 值时,nan 是可接受的值之一。因此,读取 ni 以确定它不是 nan

类似地,对于单词 ininf 的有效前缀表示无穷大。

该标准还在脚注中指出:

fscanf pushes back at most one input character onto the input stream.

所以这很可能就是 nine 中的 i 没有被推回的原因。

最重要的是,当 fscanf 操作由于某种原因失败时,假设文件指针将结束的位置基本上是不安全的。


解决此问题的一种方法是使用 ftellfseek 为每个成功的项目保存文件指针,这样您就可以返回正确的文件位置您尝试阅读的内容成功。

假设您有输入文件:

one 1 2 3 4 5
nine 9 8 7 6 5
in 3.14159 2.71828

以下代码将保存和恢复文件位置以使其按您希望的方式工作:

#include <stdio.h>

int main(void) {
char buff[50]; double dbl; size_t pos;
FILE *fin = fopen("inputFile.txt", "r");
while (fscanf(fin, "%s", buff) == 1) {
printf("Got string [%s]\n", buff);
pos = ftell(fin);
while (sscanf(buff, "%lf", &dbl) == 1) {
printf("Got double [%f]\n", dbl);
pos = ftell(fin);
}
fseek(fin, pos, SEEK_SET);
}
fclose(fin);
return 0;
}

通过注释掉 fseek,您可以看到与您描述的类似的行为:

Got string [one]
Got double [1.000000]
Got double [2.000000]
Got double [3.000000]
Got double [4.000000]
Got double [5.000000]
Got string [ne]
Got double [9.000000]
Got double [8.000000]
Got double [7.000000]
Got double [6.000000]
Got double [5.000000]
Got double [3.141590]
Got double [2.718280]

我认为这个解决方案有点困惑,因为它必须不断调用 ftell 并偶尔调用 fseek 才能使其正常工作。


另一种方法是将所有都作为字符串读取,并在读取后通过sscanf操作确定它是数字还是字符串,如以下代码(带有上述输入文件):

#include <stdio.h>

int main(void) {
char buff[50]; double dbl;
FILE *fin = fopen("inputFile.txt", "r");
while (fscanf(fin, "%s", buff) == 1) {
if (sscanf(buff, "%lf", &dbl) == 1) {
printf("Got double [%f]\n", dbl);
} else {
printf("Got string [%s]\n", buff);
}
}
fclose(fin);
return 0;
}

之所以可行,是因为浮点值实际上是字符串的真子集(即,它没有嵌入空格)。


上述两个程序的输出是:

Got string [one]
Got double [1.000000]
Got double [2.000000]
Got double [3.000000]
Got double [4.000000]
Got double [5.000000]
Got string [nine]
Got double [9.000000]
Got double [8.000000]
Got double [7.000000]
Got double [6.000000]
Got double [5.000000]
Got string [in]
Got double [3.141590]
Got double [2.718280]

这基本上就是我们想要的。


您需要注意的一件事是,将 infnan 之类的东西扫描为 double 实际上会起作用 - 这是库的预期行为(并且如果没有问题,您的原始代码将如何工作)。如果这 Not Acceptable ,您可以执行一些操作,例如在尝试将其扫描为 double 值之前评估字符串,以确保它不是那些特殊值之一。

关于C fscanf 返回错误值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34757838/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com