【问题标题】:scanf() causing strange resultsscanf() 导致奇怪的结果
【发布时间】:2010-11-14 00:06:29
【问题描述】:

我有一段代码提出了一个有趣的问题(在我看来)。

/*power.c raises numbers to integer powers*/
#include <stdio.h>

double power(double n, int p);

int main(void)
{
    double x, xpow; /*x is the orginal number and xpow is the result*/
    int exp;/*exp is the exponent that x is being raised to */

    printf("Enter a number and the positive integer power to which\n the first number will be raised.\n enter q to quit\n");

    while(scanf("%lf %d", &x, &exp) ==2)
    {
        xpow = power(x, exp);
        printf("%.3g to the power %d is %.5g\n", x, exp, xpow);
        printf("enter the next pair of numbers or q to quit.\n");
    }

    printf("Hope you enjoyed your power trip -- bye!\n");
    return 0;
}

double power(double n, int p)
{
    double pow = 1;
    int i;

    for(i = 1; i <= p; i++)
    {
        pow *= n;
    }
    return pow;
}

如果您注意到输入数字的顺序是浮点数,然后是十进制数(基数,然后是指数)。但是当我使用整数基数和浮点指数输入输入时,它会产生一个奇怪的结果。

[mike@mike ~/code/powerCode]$ ./power
Enter a number and the positive integer power to which
 the first number will be raised.
 enter q to quit
1 2.3
1 to the power 2 is 1
enter the next pair of numbers or q to quit.
2 3.4
0.3 to the power 2 is 0.09
enter the next pair of numbers or q to quit.

似乎将浮点指数的第二个数字推回下一个输入。我希望有人能解释幕后发生的事情。我知道这是 scanf() 不检查其数组边界的工作,但如果有人能给我一些更深入的理解,我将非常感激。 感谢堆栈溢出。 -M.I.

编辑。 只是想感谢大家的意见。任何其他答案都更受欢迎。 再次感谢,S.O.

【问题讨论】:

    标签: c++ c scanf


    【解决方案1】:

    这是因为当您使用 scanf 读取“2.3”时,扫描会停止,但不会消耗“.”。在“.3”中。因此,当您下一次调用 scanf 时,它会从读取“.3”开始。

    详细地说,scanf 调用不限于一行文本。 scanf() 会跳过空格,包括制表符、空格和换行符。

    【讨论】:

      【解决方案2】:

      读取第一个“2.3”时scanf读取到“.”意识到它不再是一个有效的整数并停止。所以“.3”留在缓冲区中,然后输入“2 3.4”,所以“.3\n2 3.4”在缓冲区中。当 scanf 解析得到“.3”和“2”时,就像您的示例所示。

      【讨论】:

        【解决方案3】:

        在 C 语言中,scanf() 对于来自人类用户的真实世界输入基本上是无用的——它旨在从数据文件中读取固定格式的文本。如果您使用的是 C++,则应该使用 iostream 输入,无论哪种情况,您都应该为您的特定输入要求编写自己的解析例程。

        【讨论】:

          【解决方案4】:

          其他人已经回答了您的具体问题,但我想提供一条建议。 永远不要使用scanf()fscanf()。曾经。认真的。

          [f]scanf() 操作期间的失败总是会使您的文件指针处于不确定的位置。由于用户的大多数输入通常基于行(GUI 除外),因此在我看来,使用 fgets()sscanf() 的选项总是更好。

          它的优点是将输入指针留在已知点(下一行的开头)并且允许您以多种不同的方式操作刚刚读入的行,而不仅仅是由scanf() 家族决定。

          换句话说,如果sscanf() 失败,您仍然可以将该行用于其他目的(使用不同格式的字符串重新扫描,甚至只是简单地输出错误)而无需通过stdio 体操来获得回到文件中的行首(文件很难,终端的标准输入不可能)。

          【讨论】:

          • scanf/fscanf 当然可用于读取可以检测到解析错误并中止的文件。例如,如果我是一个必须读取整数文件的 C 程序员,我可能会使用它们。
          • 如果不是因为我正在阅读的书,我会使用 fgets。我已经知道 scanf 有一段时间不好了,我永远不会在生产环境中使用 scanf (如果我有一个生产环境来编写软件)。我只是在寻找更多的背景信息。谢谢!
          【解决方案5】:

          我会读取其中的行并使用 sscanf 来解析每一行。我同意其他人的观点,尽管有比 sscanf 更好的方法。

          【讨论】:

            猜你喜欢
            • 2018-01-24
            • 2013-12-16
            • 1970-01-01
            • 2012-10-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-11-25
            • 2018-06-28
            相关资源
            最近更新 更多