1

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

/*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() 不检查其数组边界的工作,但如果有人能给我更深入的理解,我将不胜感激。感谢堆栈溢出。-MI

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

4

5 回答 5

7

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

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

于 2009-07-25T13:49:09.623 回答
5

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

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

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

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

于 2009-07-25T13:58:40.220 回答
2

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

于 2009-07-25T13:51:02.710 回答
2

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

于 2009-07-25T13:54:26.840 回答
0

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

于 2009-07-25T14:24:28.983 回答