鱼C论坛

 找回密码
 立即注册
查看: 1091|回复: 16

[已解决]关于scanf函数的问题

[复制链接]
发表于 2023-6-30 20:08:32 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
没有看懂这串代码,在第三次调用scanf函数的时候,我输入了2.5q加上好几个回车,按道理应该是不满足第二个do while的条件了,但是却一直没有结束循环,直到输入了2.5再按回车才结束
#include <stdio.h>
#include <stdlib.h>
int main()
{
    float num = 0;
    double sum = 0;
    int status;

    do
    {
        printf("请输入合法的数字:");
        do
        {
            sum = sum + num;
            status = scanf("%f", &num);
        } while (getchar() != '\n' && status == 1);
    } while (status == 1);

    printf("结果是:%.2lf\n", sum);
    system("pause");
    return 0;
}
最佳答案
2023-6-30 20:10:18
你好,这段代码的逻辑是:用户需要不断输入数字,这些数字将会被累加到  sum  中。程序会一直等待用户的输入,直到用户输入了非数字。

程序使用了  scanf  函数来获取用户的输入,并用一个浮点数来存储这个输入。 scanf  会返回成功读取的数据项数量,如果成功读取了一个浮点数, scanf  就会返回 1。

在内层的  do-while  循环中, getchar() != '\n'  和  status == 1  必须同时满足才能继续循环。 getchar()  函数会读取下一个可用的字符,如果这个字符不是换行符,并且  scanf  成功读取了一个浮点数,那么就继续循环。否则,退出循环。

然后在外层的  do-while  循环中,如果  status == 1 ,即  scanf  成功读取了一个浮点数,那么就继续循环,否则退出循环。

但是你的问题是在第三次调用  scanf  时输入了 "2.5q",这在  scanf  函数看来是一个不合法的输入,所以它只会读取 "2.5",并将 "q" 留在输入流中。此时, scanf  依然会返回 1,表示成功读取了一个浮点数。然后  getchar()  函数会读取 "q",因为 "q" 不等于换行符,所以内层的  do-while  循环会继续。这就造成了你的问题,即使你输入的不是一个合法的浮点数,程序也会继续运行,直到读取到一个合法的浮点数为止。

如果你想让程序在用户输入非数字时就立即退出,你需要修改你的程序,使其能够处理非数字的输入。有很多方法可以实现这个功能,比如使用  strtol  或  strtod  函数,它们能够报告非数字的位置。你还可以使用  fgets  函数来获取一整行的输入,然后使用  sscanf  或  strtol / strtod  来解析这个输入。

图一

图一

图二

图二
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-6-30 20:10:18 | 显示全部楼层    本楼为最佳答案   
你好,这段代码的逻辑是:用户需要不断输入数字,这些数字将会被累加到  sum  中。程序会一直等待用户的输入,直到用户输入了非数字。

程序使用了  scanf  函数来获取用户的输入,并用一个浮点数来存储这个输入。 scanf  会返回成功读取的数据项数量,如果成功读取了一个浮点数, scanf  就会返回 1。

在内层的  do-while  循环中, getchar() != '\n'  和  status == 1  必须同时满足才能继续循环。 getchar()  函数会读取下一个可用的字符,如果这个字符不是换行符,并且  scanf  成功读取了一个浮点数,那么就继续循环。否则,退出循环。

然后在外层的  do-while  循环中,如果  status == 1 ,即  scanf  成功读取了一个浮点数,那么就继续循环,否则退出循环。

但是你的问题是在第三次调用  scanf  时输入了 "2.5q",这在  scanf  函数看来是一个不合法的输入,所以它只会读取 "2.5",并将 "q" 留在输入流中。此时, scanf  依然会返回 1,表示成功读取了一个浮点数。然后  getchar()  函数会读取 "q",因为 "q" 不等于换行符,所以内层的  do-while  循环会继续。这就造成了你的问题,即使你输入的不是一个合法的浮点数,程序也会继续运行,直到读取到一个合法的浮点数为止。

如果你想让程序在用户输入非数字时就立即退出,你需要修改你的程序,使其能够处理非数字的输入。有很多方法可以实现这个功能,比如使用  strtol  或  strtod  函数,它们能够报告非数字的位置。你还可以使用  fgets  函数来获取一整行的输入,然后使用  sscanf  或  strtol / strtod  来解析这个输入。

评分

参与人数 1荣誉 +5 贡献 +3 收起 理由
1613551 + 5 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-30 20:16:36 | 显示全部楼层
isdkz 发表于 2023-6-30 20:10
你好,这段代码的逻辑是:用户需要不断输入数字,这些数字将会被累加到  sum  中。程序会一直等待用户的输 ...

但是为什么我输入了很多个回车,它也还是没有退出循环,然后再次输出printf呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-30 20:19:08 | 显示全部楼层
1613551 发表于 2023-6-30 20:16
但是为什么我输入了很多个回车,它也还是没有退出循环,然后再次输出printf呢

在你的代码中,当你输入了 "2.5q" 并按下回车后,这些字符被存储在输入流中。  scanf  会读取并解析 "2.5",然后将 "q" 以及之后的换行符留在输入流中。在这个状态下, scanf  会返回 1,表示它成功地读取了一个浮点数。这就导致了内层  do-while  循环的继续执行。

然后, getchar  会读取输入流中的下一个字符,也就是 "q"。因为 "q" 不等于换行符,所以内层  do-while  循环继续执行。

接下来, scanf  尝试从输入流中读取下一个浮点数,但是此时输入流中的下一个字符是换行符,所以  scanf  无法读取到浮点数,于是返回 0。

在这种情况下, getchar  会读取到输入流中的换行符,所以  getchar() != '\n'  的结果为  false ,于是内层的  do-while  循环终止。

然后,外层的  do-while  循环检查  status  的值。由于  status  是 0,所以外层的  do-while  循环也终止。

在这之后,由于你在程序中没有添加任何的退出条件,所以程序会继续运行,直到你关闭它。

当你输入多个回车的时候,因为没有输入任何的浮点数, scanf  会直接返回 0,但此时  getchar  仍然会读取到换行符,所以  getchar() != '\n'  的结果为  false ,于是内层的  do-while  循环终止。然后,由于  status  是 0,所以外层的  do-while  循环也终止。然后程序会再次开始执行,这就解释了为什么你看到了多次 "请输入合法的数字:" 的提示。

如果你希望在用户没有输入任何东西,只是按了回车的情况下,程序就退出,那么你需要在  do-while  循环中添加一个适当的退出条件。比如,你可以在调用  scanf  之前,先用  fgets  读取一行输入,然后再使用  sscanf  来解析这个输入。如果  fgets  返回  NULL ,说明用户没有输入任何东西,只是按了回车,此时你可以退出循环。

评分

参与人数 1荣誉 +5 贡献 +3 收起 理由
1613551 + 5 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-30 20:24:06 | 显示全部楼层
isdkz 发表于 2023-6-30 20:19
在你的代码中,当你输入了 "2.5q" 并按下回车后,这些字符被存储在输入流中。  scanf  会读取并解析 "2.5 ...

感觉还是没有完全懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-30 20:24:52 | 显示全部楼层
isdkz 发表于 2023-6-30 20:19
在你的代码中,当你输入了 "2.5q" 并按下回车后,这些字符被存储在输入流中。  scanf  会读取并解析 "2.5 ...

我的疑惑是,
为什么输入2.5q2.5【回车】可以退出循环
但是输入了2.5q【回车】【回车】【回车】却无法退出循环
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-30 20:27:07 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-6-30 20:31:19 | 显示全部楼层
1613551 发表于 2023-6-30 20:24
我的疑惑是,
为什么输入2.5q2.5【回车】可以退出循环
但是输入了2.5q【回车】【回车】【回车】却无法 ...

好的,我明白你的困惑了。这个问题的答案其实在于  scanf  函数和  getchar  函数如何处理输入流。

在你的代码中,当你输入 "2.5q" 并按下回车后,"2.5q\n" 被放入了输入流中。  scanf  会读取并解析 "2.5",然后将 "q\n" 留在输入流中。在这个状态下, scanf  会返回 1,表示它成功地读取了一个浮点数。这就导致了内层  do-while  循环的继续执行。

然后, getchar  会读取输入流中的下一个字符,也就是 "q"。因为 "q" 不等于换行符,所以内层  do-while  循环继续执行。

接下来, scanf  尝试从输入流中读取下一个浮点数,但是此时输入流中的下一个字符是换行符,所以  scanf  无法读取到浮点数,于是返回 0。

在这种情况下, getchar  会读取到输入流中的换行符,所以  getchar() != '\n'  的结果为  false ,于是内层的  do-while  循环终止。然后,外层的  do-while  循环检查  status  的值。由于  status  是 0,所以外层的  do-while  循环也终止。

然而,当你输入 "2.5q\n\n\n" 的时候,情况就有所不同。首先, scanf  会读取并解析 "2.5",然后将 "q\n\n\n" 留在输入流中。此时, scanf  返回 1, getchar  读取到 "q",于是内层  do-while  循环继续执行。

接下来, scanf  尝试从输入流中读取下一个浮点数,但是此时输入流中的下一个字符是换行符,所以  scanf  无法读取到浮点数,于是返回 0。此时, getchar  会读取到输入流中的换行符,所以  getchar() != '\n'  的结果为  false ,于是内层的  do-while  循环终止。

然后,外层的  do-while  循环检查  status  的值。由于  status  是 0,所以外层的  do-while  循环也终止,然后再次开始新一轮的外层循环。在这个新一轮的外层循环中, scanf  尝试从输入流中读取一个浮点数,但是输入流中的下一个字符还是换行符,所以  scanf  无法读取到浮点数,返回 0。此时, getchar  会读取到输入流中的换行符,于是内层的  do-while  循环又一次在第一次迭代中就终止了。

所以,当你输入 "2.5q\n\n\n" 的时候,程序其实是在不断地开始新的外层循环,但是每一次的内层循环都在第一次迭代中就终止了。

当你输入 "2.5q2.5\n" 的时候,"2.5q2.5\n" 被放入了输入流中。 scanf  会读取并解析前面的 "2.5",然后将 "q2.5\n" 留在输入流中。然后  getchar  读取到 "q",然后  scanf  尝试读取下一个浮点数,这次它会成功地读取到 "2.5",于是返回 1。然后  getchar  读取到 "\n",于是内层  do-while  循环终止。外层  do-while  循环检查  status  的值,由于  status  是 1,所以外层  do-while  循环继续执行。然后程序会再次询问你输入下一个数字。

评分

参与人数 1荣誉 +5 贡献 +3 收起 理由
1613551 + 5 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-30 20:39:51 | 显示全部楼层
本帖最后由 1613551 于 2023-6-30 20:41 编辑
isdkz 发表于 2023-6-30 20:31
好的,我明白你的困惑了。这个问题的答案其实在于  scanf  函数和  getchar  函数如何处理输入流。

在 ...


我还是没有理解,如果说是不断开始新的外层循环,为什么不会一直输出printf,而是卡在那里不动了呢,也就是图一第三段那里

所以,当你输入 "2.5q\n\n\n" 的时候,程序其实是在不断地开始新的外层循环,但是每一次的内层循环都在第一次迭代中就终止了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-30 21:19:52 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-6-30 21:26:48 | 显示全部楼层
是谁设置的最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-30 22:03:42 | 显示全部楼层
1613551 发表于 2023-6-30 21:26
是谁设置的最佳答案

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-30 22:04:29 | 显示全部楼层
你再发一个帖子吧,说说你的疑惑
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-30 22:21:28 | 显示全部楼层
sfqxx 发表于 2023-6-30 22:04
你再发一个帖子吧,说说你的疑惑

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-30 22:23:23 | 显示全部楼层

主要是我差1最佳答案就第2了呀,帮帮吧。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-12 23:28:47 | 显示全部楼层
”自找的“,给了最佳就别想了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-14 19:47:20 | 显示全部楼层
sfqxx 发表于 2023-7-12 23:28
”自找的“,给了最佳就别想了

噗,这个啊,真不好意思,我当时没看到
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-24 09:15

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表