scanf和回车的关系:

  先看一个我们经常使用的代码:

  char c;scanf("%c", &c);

  scanf 的各种格式中,%d、%c、%s三种最常用,通常都是以回车作为一次输入的结束。由于对字符解析方式及字符特点不同(如数字中一般不会出现空格回车等特殊字符)不同,%d格式一般不会在连续输入时,遇到问题。而%s和%c却会出现各种各样的问题,比如回车问题,空格问题等。

我们已经习惯了上面的代码,再看下面存在连续输入时的情况

  int i;char c;scanf("%d", &i);scanf("%c", &c);

  如果我们为i赋值为3,并以回车的方式结束对i的赋值。再按常规思路为c赋值时,就会发现并不能为c赋值,并且c自动赋值为十进制的10,也就是回车键。why???

要回答这个问题,先看scanf函数的功能和工作原理

  scanf函数这个函数的作用是从标准输入设备获取输入值,并存储到参数列表中指针所指向的内存单元,如果读入成功,函数会返回读入成功的数据的个数;scanf函数的结束通常有3种,遇到空格、回车或者tab键为常用的结束方式;或者按照格式控制符的指定来控制结束,如%5d类的格式;遇到非法输入也会自动结束。

对常用的三种格式,结束符号分别如下:

%d格式输入,默认分隔符是所有的 white-spaces(空格、回车、制表);

%c格式输入,则按ASCII字符考虑,无分隔符。可能会受到之前输入的影响,必要时用fflush(stdin);清除缓冲区;

%s 是 字符串格式,默认分隔符是所有的 white-spaces,输入后自动加入结束符"\0"。

  继续上面的由于连续输入带来的问题,往深了说,就涉及到缓冲区了。scanf函数是以删除的方式从缓冲区读取数据(缓冲区中存储来自标准输入的数据)。如果缓冲区是空的,就阻塞之,等待从键盘输入;并且scanf还能对数字输入忽略先导的空白符,如\n\t和空格等(注意,对字符输入并不忽略先导字符,这个也是很自然的道理,因为\n\t和空格在字符中都是合法的字符)。

  scanf的缓冲机制和对字符的处理方式就造成了scanf对字符%c和字符串%s的读取时的各种意外。比如上面的例子,回头分析这段代码:

  输入了i的值为3然后按回车,当前缓冲区中数据为”3\n”,由回车的作用scanf开始从缓冲区中读取一个%d控制的数据,也就是3,此时缓冲区中还剩”\n”;对下一个scanf函数的格式控制是%c,这个情况下并不忽略先导的空白字符\n,而是直接赋给字符c了。想要查看缓冲区的内容,stdin[s1] ,如果想要查看当前stdin中的内容,一般方法都比较忤逆,可以尝试使用文件操作freopen将stdin中的数据重定向到另外一个file*中。这个另辟一文。

  如何解决这个缓冲区和字符解析的问题呢?既然缓冲区有我们不需要的东西,那就清除缓冲区。微软系统中是fflush(stdin)函数可以清除缓冲区,而有的编译系统并没有定义对stdin的fflush操作,就把stdin中的数据读出来:

1)  可以使用fgets()函数,这个函数没有编译器的限制;

2)  或者把缓冲区中多余的东西交给别的函数,如getchar(),具体代码为 while( (c = getchar() ) != '/n' && c != EOF );

3) 上面的方法基于原理,但有点麻烦,尤其是遇到字符%c和字符串%s对回车的处理时。C还提供了gets()函数解决了这个问题,gets()函数是不论中间有什么字符,一律读进来,直到遇到回车符;

4)  C++中,还可以操作stdin的指针,stdin是一个File*类型的数据结构,使stdin->_IO_read_ptr = stdin->_IO_read_end;。但是C中不可以。

scanf和空格键

  前面就有说,scanf函数,根据格式的不同,对空白字符的处理也不同。%d格式下,对空白字符不敏感,通常都是作为结束符的;对%c来说,对回车符比较敏感,空格的做为一个普通字符处理的;对%s来说,回车和空格都是当前函数的结束字符,由于缓冲区stdin机制,这里又要特别注意 空格和回车对%s的影响。

  %s默认分隔符是所有的 white-spaces,输入后自动加入结束符"\0",使其成为一个字符串(之所以加上\0,是和字符数组char[]的结束符有关的,C中是没有string这个类型的,是使用char[]结构实现字符串)。值得注意的是,即使输入字符的长度足够,%s是宁愿舍弃输入字符,也要把/0加上去的,作为字符串的结束。并且,scanf会忽略缓冲区开头的空格,知道遇到一个非空格字符,才开始向内存中读取数据。

  比如,我们想要输入”The C Programming Language.\n”,中间的空格怎么处理呢?

  其中一个解决方法是使用gets函数,这个函数是以回车符作为输入结束的标志的;还有一种解决方式是:scanf("%[^\n]", c)

  char c[15];scanf("%[^\n]", c[s2] );

  只是scanf("%[^\n]", c);和gets这两种处理方式都是不忽略所有的空格,包括缓冲区开头的空格;这一点和scanf("%s",c);的处理方式不同,%s的方式,忽略缓冲区开头的空格。

另:scanf的返回值

  scanf()函数返回的值为:正确按指定格式输入变量的个数;也即能正确接收到值的变量个数。在类型匹配错误的时候,以非正常的方式退出。可以利用scanf函数的返回值判断输入是否正确,并进行流程控制:

     int i = 0;char c1[15];while((scanf("%c", &c1[i])!=EOF) && i<14){i++;}


[s1]stdin是标准输入,一般针对键盘,是个FILE* 类型的数据。

[s2]这里注意使用c 还是 &c:

c是个数组,数组 即代表了数组的首地址,所以可以使用c;

&c,表示数组c的地址,也就是指首地址,所以也是可以的。但通常c更符合逻辑一点。这在读取%s类型的数据时可以说明这一点:

scanf(“%s”, c);

转载于:https://www.cnblogs.com/czl-sy/archive/2013/04/07/3006109.html

由scanf说起之1:scanf函数和回车、空格 及其返回值相关推荐

  1. 【函数的定义、调用(嵌套调用、递归调用)、声明、函数的分类(有无返回值、有无参数)、变量(自动变量与静态变量、局部变量与全局变量、只读变量)】(学习笔记7--函数)

    第一篇博文,打卡新星计划第三季3.4~4.4,希望能有质的飞跃,顶峰相见 一.自定义函数 1.函数的定义 函数在使用前也需要定义,定义的格式如下: 数据类型 函数名([数据类型 参数1],[数据类型 ...

  2. Go 学习笔记(61)— Go 高阶函数、函数作为一等公民(函数作为输入参数、返回值、变量)的写法

    函数在 Go 语言中属于"一等公民(First-Class Citizen)"拥有"一等公民"待遇的语法元素可以如下使用 可以存储在变量中: 可以作为参数传递给 ...

  3. API函数MessageBox的参数与返回值

    Win32汇编函数的参数,参数类型,返回值都是一个dword类型(4字节) 返回值永远放在EAX中,如超过4个字节则返回一个数据的指针(指向返回值存放的缓冲区地址) .data titleS db ' ...

  4. 如何引用传递参数从一个函数中得到多个返回值

    2019独角兽企业重金招聘Python工程师标准>>> 通过"引用"传递参数的方法从一个函数中得到多个返回值.就像三元运算符一样,大部分受过正式编程训练的程序员都 ...

  5. python函数定义参数类型和返回值类型

    python中我们也可以定义函数的参数类型和返回值类型,如下代码 #函数参数和返回值的类型声明,python函数类型的声明,更加有意义,更加实用一些 def add(a,b):''':param a: ...

  6. 实现 fizzBuzz 函数,参数 Thum 与返回值的关系如下: 1、如果 Thum 能同时被 3 和 5 整除,返回字符串 fizzbuzz 2、如果 Thum 能被 3 整除,返回字符串 fiz

    题目描述 实现 fizzBuzz 函数,参数 Thum 与返回值的关系如下: 1.如果 Thum 能同时被 3 和 5 整除,返回字符串 fizzbuzz 2.如果 Thum 能被 3 整除,返回字符 ...

  7. 函数中有多个return?C语言中,一个函数可以有几个返回值?

    在移植wifi的代码时,遇到了一些与下面类似的函数,这些函数中有不只一个return,这可是个新鲜的玩意儿: int func (int b) {int a=5;if (a>b)return a ...

  8. 以下是一个使用 VBA 的例子,演示了 ByVal 和 ByRef 的区别,以及如何在函数中传递参数和返回值。

    以下是一个使用 VBA 的例子,演示了 ByVal 和 ByRef 的区别,以及如何在函数中传递参数和返回值: Sub Example()Dim x As Integer, y As Integerx ...

  9. python 定义函数时,参数和返回值的数据类型注释

    """ a:int 表示添加a的数据类型注释,但事实上就算传入a的值不是int类型也不会报错,可以正常运行; 但编译器会警告. b:int = 5 表示添加b的数据类型注 ...

  10. smali语言详解之一般/构造方法(函数)的声明与返回值关键字

    smali语言详解之一般/构造方法(函数)的声明与返回值关键字 一. smali语言的方法声明格式 .method与.end method成对出现,类似于java中的花括号 1.1.非静态的一般方法 ...

最新文章

  1. 什么是整洁的代码?什么是肮脏的代码?
  2. java switch 应用
  3. 微软的Ajax库客户端Bug总结
  4. android怎么长按一张图片保存到相册_instagram怎么保存图片?
  5. Linux CentOS 7 YouCompleteMe相关配置。
  6. C语言/C++基础知识
  7. wordpress里mySql服务器的配置
  8. 1202此服务器的证书无效,ios - iOS:URLRequest错误域= NSURLErrorDomain代码= -1202“此服务器的证书无效 - 堆栈内存溢出...
  9. HTML5增加的几个新的标签
  10. Python使用递归法对整数进行因数分解
  11. 蓝桥杯 基础练习 FJ的字符串
  12. 利用SMTP虚拟服务器实现不同邮件系统之间的通讯
  13. 游戏开发之拷贝构造函数,即复制构造函数(explicit关键字及拷贝构造函数的调用时机)(C++基础)
  14. 五款好用的项目进度管理甘特图软件,总有一款能满足你的需求
  15. proteus单片机仿真入门攻略(含元器件名称及它的图形)
  16. GitHub上传代码及在线demo演示
  17. 培养学生计算机绘画水平,谈电脑绘画对高校绘画教学的作用
  18. Spring Cloud Alibaba Nacos 注册中心
  19. 放弃csv,拥抱feather文件
  20. esp01s作为ap,收发数据

热门文章

  1. 如何利用开源风控系统 TH-Nubula(星云)防止撞库?
  2. ​ [RHEL7.1]重新封装系统(制作模板)
  3. 日志打印,设置开关类【编程技巧】
  4. Windows 7 测试体验
  5. PyQt5-QComboBox控件使用实现省市级联效果
  6. 解读TIME_WAIT--你在网上看到的大多数帖子可能都是错误的
  7. C# 从服务器下载文件
  8. lintcode-76-最长上升子序列
  9. Hidden (NOIP模拟赛)(字符串模拟QAQ)
  10. sublime Text3下sass环境配置(windows)