`scanf`读为零,即使我输入100

时间:2014-12-23 23:51:03

标签: c scanf

在我写的一个程序中,有一个scanf()的调用,它读取一个存储金钱的长十进制数字。

 do {
     fflush(stdin);
     printf("What is the number?\n");
 } while (scanf("%Lf", &n.amt) == 0);

然而,在调试时,我看到n.amt等于0.如果我输入100,为什么它显示它读为零?起初,我使用的是float,我将其更改为long double,但此问题仍然存在。

这一点也很明显,因为这些数据后来被写入文件,0也被写入那里。

2 个答案:

答案 0 :(得分:1)

代码有几个问题。

首先,正如已经指出的那样,fflush(stdin)是未定义的行为。虽然可以为特定实现记录其输入流的行为(使用glibc,fflush(stdin)刷新未读输入),但这不是可移植行为。

删除fflush()不够。如果scanf()获得类似'%lF'的格式规范,并且在跳过输入流中的任何空格后,下一个字符将无法转换为请求的格式规范(它不是数字,例如,小数点或+/-符号表示'%lF'格式规范)下一个字符实际上仍未读取,如果没有其他格式规范已成功转换,则scanf()将返回0.如果再次循环,未读的字符仍然无法转换,所以最终会出现无限循环。

我从不喜欢使用scanf(),因为处理这种错误情况总是很尴尬。

我更喜欢使用fgets()来将整行输入读入缓冲区,如果你坚持,使用sscanf()来解析它。使用这种方法,错误恢复语义将很容易实现。

答案 1 :(得分:1)

获取数字输入时,防止空字符串([enter])垃圾输入而不会导致有点棘手使用scanf时,在空白行上输入。以下内容将该值作为字符串读取,并在没有挂起的情况下防止无输入垃圾输入。只有在使用strtod转换为双倍值时才会继续(您可以将strtold替换为long double):

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

int main () {

    char amount[50] = {0};
    char *ep = NULL;
    double n_amt = 0.0;

    do {
        /* protect against [enter] and garbage as input */
        while (printf ("\nEnter the amount of money in the transaction: $ ") &&
                scanf ("%49[^\n]%*c", amount) == 0 && getchar()) ;

        /* convert to double */
        n_amt = strtod (amount, &ep);

        /* loop if no valid conversion */
    } while ( &amount[0] == ep );


    printf ("\n n.amt = %lf\n\n", n_amt);

    return 0;
}

<强>输出:

$ ./bin/scanf_double

Enter the amount of money in the transaction: $

Enter the amount of money in the transaction: $ lsdkfj

Enter the amount of money in the transaction: $ 123.45

 n.amt = 123.450000

注意:您最好将钱作为整数值而不是浮点值处理。您最好使用fgetsgetline来阅读amount而不是scanf,但该示例的目的是提供scanf解决方案。< / p> 使用fgets

等效输入

do {
    printf ("\nEnter the amount of money in the transaction: $ ");
    fgets (amount, MAXL, stdin);
    n_amt = strtod (amount, &ep);
} while ( &amount[0] == ep );