繁体   English   中英

无限循环fscanf字符串textfile c编程

[英]infinite loop fscanf string textfile c programming

为什么当我扫描文本文件中的字符串时,它总是陷入无限循环?

while(val = fscanf(stdin,"%lf%c",d,c) != EOF)
{if(val==0){//error}
else if(c='\n'){//error print char}
else{//print double}
}

文本文件:

4.5
r5
23
s

我想要的是打印所有内容,但是当我到达字符串时,它总是给我一个无限循环。

scanf()系列函数是一种折磨测试,对新手程序员不应进行。 准确地使用它们非常困难。

分析

甚至忽略代码布局(完全令人震惊-这是一种专业的评估),并假设您具有以下变量声明:

double  value;
double *d = &value;
char    newline;
char   *c = &newline;
int     val;

而不是更合理:

double d;
char   c;
int    val;

您的片段中充满了数不胜数的问题。

while(val = fscanf(stdin,"%lf%c",d,c) != EOF)
{if(val==0){//error}
else if(c='\n'){//error print char}
else{//print double}
}

您已将比较结果分配给val ,而不是将fscanf()的返回值分配给val并将其与EOF进行比较。

while ((val = fscanf(stdin, "%lf%c", d, c)) != EOF)

现在代码只是错误的; fscanf()可以返回EOF(通常是,但不保证, -1 ),或0 ,或12 ,而其中只有2就是你要找的答案。 因此,循环条件应为:

while ((val = fscanf(stdin, "%lf%c", d, c)) == 2)

或者,如果您有更简单的定义,则应为:

while ((val = fscanf(stdin, "%lf%c", &d, &c)) == 2)

现在您知道读取了两个值。 现在,循环内的if (val == 0)检查是多余的; 仅当val == 2时才输入循环体。

您可以检查*c的值是否是进行比较而不是赋值的换行符:

    if (*c == '\n')

(或if (c == '\\n') ;让我们假设您使用了简单的声明,而忘记了原始代码中的&字符。)但是,如果c不是换行符,则会出现错误,因此实际上它应该是一个!=测试。

while ((val = fscanf(stdin, "%lf%c", &d, &c)) == 2)
{
    if (c != '\n')
        ...print error...
    else
        printf("Number = %g\n", d);
}

循环之后,您可以测试val == EOF vs val == 0 vs val == 1 第一个表示您已达到EOF或发生了错误; 第二个字母表示输入的下一个字符既不是空格也不是有效数字的一部分(例如, .+-以外的字母或标点符号)。 val == 1情况深奥; 它要求文件的末尾出现在后面没有换行符(或其他任何字符)的数字之后。

无限循环

顺便说一句,最有可能导致无限循环的原因是输入中的字符无效(非数字,非空格)。 而且,仔细检查后,我发现第二行输入中有一个r 这将触发代码无限循环。 fscanf()始终返回0,而不是EOF,因此循环继续。 (它无法用%c读取r ,因为它必须先成功读取一个数字。)

合成

%lf格式将跳过任何前导空格,包括换行符,因此您的代码试图确保每行有一个数字,且没有尾随空格。 在这种情况下,使用fgets()strtod()可能会做得更好,尽管完全正确地使用strtod()并非完全无关紧要。 以下代码忽略了strtod()优点。

char line[4096];
double d;

while (fgets(line, sizeof(line), stdin) != 0)
{
    char *end;
    d = strtod(line, &end);
    if (end == line || *end != '\n')
        ...incorrect format...
    else
        printf("Number = %g\n", d);
}

fgets()返回空指针的唯一原因是您已达到EOF或发生了错误。 您可能要设置errno = 0; 在调用strtod()之前,然后检查其值以发现超出范围的数字。

代码进入无限循环,因为fscanf(stdin,"%lf%c",d,c)试图读取一个数字并找到一个字母: r5r 如果无法扫描任何内容,它将返回0 0 != EOF为true,并且true分配给val 并且while (val)重复。 问题是r未被任何东西消耗,因此下一个`fscanf()会重复重复尝试,结果相同。

推荐

if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
  result = sscanf(buffer, "%lf %c", &d, &c);
  if (result != 1) ; //handle error
}

一个问题是您不应尝试扫描换行符。 另一个问题是,不等于运算符!=具有更高的 优先级比分配,这意味着val是比较的结果。 第三个错误是您没有提供将值读入的指针(导致未定义的行为)。

我建议这样改变:

while (scanf("%lf", &d) == 1)
{
    printf("You have read %f\n", d);
}

只要输入是浮点,上述循环就会循环。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM