C语言中scanf函数与空格回车

  1. scanf()函数有返回值,且返回值是正确读取的个数
    scanf("%d%d", &x, &y);

    • 若是x,y都被正确读取了,则返回值是2;
    • 若只有x被正确读取了,则返回值是1;(不存在x没有被正确读取,但是y被正确读取的情况)
    • 若x,y都没有被读取,则返回值为0;
    • 若是遇到错误或者文件末尾,则返回-1,这个-1就是常见的E0F(end of file),他俩等价;
  2. scanf是从缓存区读取数据的

    • 每成功读取就会把缓存区的该数据删掉;
    • 若是需要读取但是缓存区还没有值,scanf就会一直等待用户输入(阻塞)直到用户输入;
    • 若是读到不是scanf需要的值,scanf不会清空缓存,会继续接着读,除非缓存里面是scanf需要的值。
  3. scanf对不同类型输入的处理方式
    前提:空格、回车、制表符Table都是空白字符;

    • 对于%d类型的输入,scanf默认的分割符是所有的空白字符。也就是说如果一个scanf函数中出现scanf("%d%d",&a,&b),那么用任何一个空白字符来分隔两个整数a,b的值,变量a,b都可以接收到正确的输入。且scanf会忽略输入数据项前面的空白字符。

    • 对于%c类型的输入,scanf默认所有字符都是需要接收的字符,包括所有的空白字符也会被接收。也就是说如果一个scanf函数中出现scanf("%c%c",&a,&b),那么输入c t,最后a是c,b是,t是接收不了的;

    • 对于%s类型的输入,scanf默认的分割符是所有的空白字符。scanf对于字符串输入的处理和对整数类似,会忽略前导的空白字符,而且默认的分隔符是所有的空白字符。
      - 这里需要详细讲一下
      - 比如scanf("%[^\n]",s);这句代码的意思是除了回车键,其余都接收放进s字符串里面。如果你打了回车,回车不会被接收进字符串s里面,回车之前的所有字符包括空格都会被放进字符串s里面。
      - 那么,这个回车呢?它会一直被留在缓存里面,只要不动这个缓存,他会一直在。此时scanf的返回值是1(如输入:abc\n)或者0(如输入:\n)
      - 上面的代码不会有任何问题,但是一旦写了写了下面的代码,就会出错。

      	while(scanf("%[^\n]", s) != EOF){
      		printf("%s", s);
      	}
      

    原因是:scanf("%[^\n]", s)接收非回车符,一旦碰到回车就停止,然后进入循环里面执行。但是缓冲区里面的\n一直在,没有被读取之后删除,scanf("%[^\n]", s)的返回值一直是0或者1,while循环里面一直成立,scanf一直在尝试读取非回车符,但是一直遇到缓存里面的回车符,每遇到一次刚刚的回车符就printf("%s", s)以下之前输入的值,就会出现无限循环输出…

  4. 缓冲区数据的读取
    像第3点那样,出现回车一直呆在缓冲区消不掉怎么办?

    • 第一种方法:使用fflush(stdin);主动清空缓冲区
      	while(scanf("%[^\n]", s) != EOF){
      		fflush(stdin);
      		printf("%s", s);
      	}
      
    • 第二种方法:使用getchar()函数,主动吞掉缓冲区的第一个字符,也就是卡住的那个回车字符
      	while(scanf("%[^\n]", s) != EOF){
      		getchar();
      		printf("%s", s);
      	}
      
    • 第三种方法:不使用scanf("%[^\n]", s)使用gets()函数,gets()函数会把回车和EOF当成分隔符,但是不具备对缓冲区的一些操作,所以用来处理字符串好,但是改成其他的分隔符就不太好用了,但是不具有通用性。

可以用以下代码做测试。

附录1:

#include<stdio.h>

int main(){
	char s[100];

	while(scanf("%[^\n]", s) != EOF){
		//fflush(stdin);
		//getchar();
		printf("%s", s);
	}

	return 0;
} 

附录2:
可以参考这位博主的博客理解。https://blog.csdn.net/xia7139/article/details/14522493

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值