新手必须知道的scanf()函数中使用\n‘会怎么样?以及从中知道scanf()函数使用的注意事项。

最近有朋友问了我一个代码,出现了一个bug我也是第一次见这样的写法,研究了半天,觉得有所收获,所以写篇文章分享一下scanf()函数中为什么不用使用\n,以及scanf()函数使用的注意事项。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int day;
    scanf("%d",&day);
     int sum1=0,sum2=0,sum3=0;
    while(day--)
    {
        int ydj,edj,sdj;
        scanf("%d %d %d\n",&ydj,&edj,&sdj);
        sum1=sum1+ydj;
        sum2=sum2+edj;
        sum3=sum3+sdj;
    }
    printf("%d %d %d %d",sum1,sum2,sum3,sum1+sum2+sum3);
    return 0;
}

可以看到 这段代码在scanf("%d %d %d\n",&ydj,&edj,&sdj);中多加了一个\n,那么这就会让代码出现bug,当我们输入3时,没有bug的情况应该输入3行3列数据,然后输出。但是出现bug以后代码就变成了要输入4列才会输出。

 如果这段代码不够直观,那我们再来看一段代码,这一段代码在scanf()函数里同样加入了\n;

​
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
    int a1, a2, a3;
    scanf("%d %d %d\n", &a1, &a2, &a3);
    printf("%d %d %d\n", a1, a2, a3);
}

​

运行会如下所示,会多出一行输入数据4 5 6

但实际上,最后一行即使输入一个数据也可以。

但,总而言之,无论输入几个数据,我们都会多输出一行。

那么我们来分析一下出现这种现象的原因,首先我们先看scanf函数的用法,scanf("非输入控制符 输入控制符",输入参数);

ps:输入控制符是形如%d这样的,非输入控制符是空格之类的,不懂的自行百度,在此我不多赘述。

scanf函数会将从键盘输入的字符转换为输入控制符所规定的数据,然后存入以为输入参数的值为地址的变量中,非输入控制符必须原样输入。比如scanf("%d %d %d",&a,&b,&c);在scanf()函数内我们使用了非输入控制符空格,那么我们在输入时也必须使用空格。

再比如scanf("m%d m%d m%d");这里的%d就是输入控制符,就是非输入控制符,注意%d后面还有一个空客,这是非输入控制符,但是这些非输入控制符要严格按照格式输入。

下面看一个例子。

可以看到我们没有按照输入格式输入,就会得到垃圾值,正确的输入应该为m1 m2 m3  

所以 scanf("%d %d %d\n", &a1, &a2, &a3);这段代码如果我们在输入时按照格式输入,正确输入的格式应该为1 2 3\n

可以看到这样输入的话就不会让我们多输出一行。所以回到最初的这个代码,scanf("%d %d %d\n",&ydj,&edj,&sdj);出现多输入一行的原因,是我们没有按照scanf()函数的标准用法去使用。此时,这里\n会被当做非输入字符处理,当我们输入数据时,如果没有从键盘上输入\n,而是直接回车,回车的字符就是\n,此时第一次输入数据之后的回车就是被当做非输入字符处理,scanf函数是在缓冲区\n前面拿值,此时缓冲区就没有\n了,当我们没有输入\n第一次按下回车之后,光标会移动到下一行,等着我们给他一个\n,但是直接按回车健是不行的,虽然回车键是\n,因为此时系统是等我们输入一个值,直接按回车是不行的,编译器会认为我们什么也没输入,编译器是想让我们输入一个数。所以此时我们要从键盘上输入\n,或随便输入一个与输入字符匹配值,这里是%d,按下回车之后就会正常进入下一个语句,但是此时我们多出了一个数据,他会被放到缓冲区,会被下一个scanf()函数使用,这里涉及到缓冲区的问题,不懂的可以去看我的另外一篇关于缓冲区的文章。

 下面详细解释一下最开始的那段代码,详细过程都在代码注释里面

#include <stdio.h>

int main()
{
    int day;
    scanf("%d", &day);
    int sum1 = 0, sum2 = 0, sum3 = 0;
    while (day--)
    {
        //1  2  3\n
        //4  5  6\n
        //7  8  9\n
        //10 11 12\n
        // scanf("%d %d %d\n")
        //第一次输入 1 2 3\n(这里的/n会按照非输入字符处理)所以换行之后会让我们继续输入,事实上这里第一次回车之后
        //我们输入\n,就会正常结束,但是这里我们继续输入4 5 6\n(这里的\n是scnaf()函数的结束标志);
        //拿走1 2 3,剩下4 5 6\n;因为前面是%d,所以会拿走3个%d的数字,并没有拿走\n。\n是被当作非输入字符串处理
        //第二次输入 7 8 9\n,缓冲区放的是4 5 6\n 7 8 9\n
        //拿走4 5 6\n ,剩下7 8 9\n
        //第三次输入10 11 12\n,缓冲区放的是 7 8 9\n 10 11 12\n
        //拿走7 8 9\n,剩下10 11 12\n
        int ydj, edj, sdj;
        scanf("%d %d %d\n", &ydj, &edj, &sdj);
        sum1 = sum1 + ydj;
        sum2 = sum2 + edj;
        sum3 = sum3 + sdj;
    }
    int a, b, c;
    //缓冲区剩下下10 11 12\n 在按一次回车,缓冲区是10 11 12\n\n
    //拿走10 11 12\n,缓冲区剩下\n
    scanf("%d %d %d", &a, &b, &c);
    printf("a= %d b = %d c = %d\n", a, b, c);
    printf("%d %d %d %d\n", sum1, sum2, sum3, sum1 + sum2 + sum3);
    //测试缓冲区剩下的数据
    char ch = getchar();
    if (ch == '\n')
    {
        printf("hhhhh\n");
    }
    //输入a
    printf("请继续输入");
    char hh = getchar();
    //输出97,说明之前的缓冲区没有数据了
    printf("hh =%d\n", hh);
    return 0;

}

运行截图

 总结&结语

1在使用scanf()函数之时最好提示用户怎么样输入

2在scanf()函数内尽量不要使用非输入控制符,尤其时\n,

好了以上是本次博客更新内容,如有错误欢迎批评指正。如有疑问欢迎在评论区留言,期待您的关注和点赞,我们一起学习共同进步。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值