scanf() 导致奇怪的结果

发布于 2024-07-29 14:03:06 字数 1465 浏览 2 评论 0原文

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

/*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

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

I have a piece of code that presents an interesting question (in my opinion).

/*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;
}

If you'll notice the order of numbers to be entered is the floating point number and then the decimal number (base number and then the exponent). But when I enter the input with an integer base and floating point exponent it produces a strange result.

[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.

It seems to push the second number of the floating point exponent back onto the next input. I was hoping some one could explain what was going on behind the scenes. I know that this is the work of scanf() not checking its array boundaries but if some one could give me some deeper understanding I'd really appreciate it.
Thanks Stack Overflow.
-M.I.

Edit.
Just wanted to thank everyone for their input. Any other answers are more then welcome.
Thanks again, S.O.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

勿挽旧人 2024-08-05 14:03:06

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

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

This is because when you're using scanf to read "2.3", the scan is stopping at, but not consuming the "." in ".3". Thus, when you make the next call to scanf, it starts by reading in ".3".

To elaborate, scanf calls are not restricted to one line of text. scanf() skips over whitespace, including tabs, spaces and newlines.

巨坚强 2024-08-05 14:03:06

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

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

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

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

Others have answered your specific question but I'd like to offer one piece of advice. Never use scanf() or fscanf(). Ever. Seriously.

Failure during a [f]scanf() operation invariably leaves your file pointer at an indeterminate location. Since most input from users is generally based on lines (except in GUIs), the option of using fgets() and sscanf() is always better, in my opinion.

It has the advantage of leaving the input pointer at a known point (the start of the next line) and allowing you to manipulate the line that you just read in in many different ways, not just that dictated by the scanf() family.

In other words, if the sscanf() fails, you still have the line available for other purposes (rescan with a different format string or even simply output it with an error) without having to go through stdio gymnastics to get back to the start of the line in the file (hard with a file, impossible with stdin from a terminal).

尐偏执 2024-08-05 14:03:06

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

When reading the first "2.3" scanf read up to the "." realizes it is no longer a valid integer and stops. So ".3" is left in the buffer, then you type "2 3.4" so ".3\n2 3.4" is in the buffer. When scanf parses that it gets ".3" and "2" just like your example shows.

我不在是我 2024-08-05 14:03:06

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

In C, scanf() is basically useless for real world input from human users - it is intended for reading fixed format text from data files. If you are using C++, you should be using iostream input, and in either case you should really be writing your own parsing routines for your specific input requirements.

喜你已久 2024-08-05 14:03:06

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

I would read the lines in and use sscanf for parsing each line. I agree with others, there are better methods than sscanf though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文