当前位置: 首页 > news >正文

C语言中输入函数(scanf()、fgets()和gets())的区别详解

在c语言中,有三种主要的输入函数:scanf(),fgets()以及gets()

scanf:

以 space enter tab 作为结束, 且不接收 space, 回车符会残留在缓存区

它是一种格式化的输入方式,可一次性按照规定的格式输入多个数据域。

scanf函数是一个标准库函数,它的函数原型在头文件“stdio.h”中。与printf函数相同,C语言也允许在使用scanf函数之前不必包含stdio.h文件。

scanf函数的一般形式为:

scanf(“格式控制字符串”, 地址表列);

其中,格式控制字符串的作用与printf函数相同,但不能显示非格式字符串,也就是不能显示提示字符串。地址表列中给出各变量的地址。地址是由地址运算符“&”后跟变量名组成的。

例如:&a、&b分别表示变量a和变量b的地址。

下面以输入规定的长度的字符串为例,来说说它的使用方法和容易产生的bug。

要求:定义一个长度为10的个字符数组,由用户通过键盘为其赋值。

char name[10];
scanf("%9s",name);

说明:之所以使用%9s是因为我们还需要预留一个位置给字符串结束标志'\0',所以用户输入的名字最长只能为9,且其中不能包含空格类字符(空格,回车,首行缩进符),因为scanf函数认为它们是字符串的结尾。

危险:当用户输入的名字超过9个衣服时,系统将会产生段错误(segment fault),如果运气好程序可能不会提示错误,如果不好,可能内存中重要的数据被覆盖!

gets:

以 enter 作为结束, 接收 space, 替换回车符为 '\0', 不会保存回车符在缓存区

它通过键盘获得字符串输入,并且没有任何字符串长度上的限制和检测,建议应该避免在我们的代码中使用该函数!

要求:定义一个长度为10的个字符数组,由用户通过键盘为其赋值。

char name[10];
gets(name);

注意:本函数可以无限读取,不会判断上限,所以程序员应该确保buffer的空间足够大,以便在执行读操作时不发生溢出。为了避免这种情况,我们可以用fgets()来替换gets()。

危险:任何时候均要避免使用该函数,虽然它存在已经有很长一段时间了。

fgets(char *name, int length, fd)

头文件:include<stdio.h>

该函数从文件描述符fd指定的文件获得length个字符存入从name开始的length个内存单元中。由于其形参中规定了最大接受字符数,故不会发生像scanf函数那样的缓存溢出的问题。

要求:定义一个长度为10的个字符数组,由用户通过键盘为其赋值。

char name[10];
fget(name,sizeof(name),stdin);

说明:因为此处name是一个数组名,虽然它本质上是一个指针,但聪明的sizeof函数会把他区别于一般的指针变量,从而根据之前的定义求出数组的长度。但若是一般的指针变量,sizeof函数求出的值就是4或是8了。

getchar:

enter 结束, 不会舍弃回车符

区别:

1.是否对用户输入的字符个数有所限制?

两者均有所限制,但scanf函数需要你在格式化说明符中显示注明,若不注明则无限制,可能会导致溢出事故;fgets函数则将其作为一个形参予以强制规定。

2.用户是否可以同时输入多个域的数据?

scanf函数可以通过添加多个格式化输入说明符来实现多域输入,而fgets函数每次仅能对一个域赋值。

3.用户输入的字符串中可以包含空格类字符吗?

 scanf函数会把空格符当做字符串的结束符,故不可以在一个字符串中含有空格。而否则可以。

 

相关文章:

  • c语言中getchar()
  • C语言-static的作用
  • C语言-2019年九1
  • C语言-2019年九题2
  • C语言-2018年第九题1
  • C语言比Java、Python高效
  • C语言-比较字符串是否相等
  • C语言里指针和引用的区别
  • 大数据平台数据集市
  • 认证SQL基础知识
  • Caused by: java.lang.IllegalArgumentException:LoggerFactory is not a Logback LoggerContext but Logba
  • C语言-快速排序
  • JAVA实现-URL短网址生成算法
  • JAVA-字符串连续出现字母进行压缩
  • C语言-字符串连续出现字母进行压缩
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • 【comparator, comparable】小总结
  • 3.7、@ResponseBody 和 @RestController
  • JDK9: 集成 Jshell 和 Maven 项目.
  • mongo索引构建
  • nfs客户端进程变D,延伸linux的lock
  • node 版本过低
  • redis学习笔记(三):列表、集合、有序集合
  • vagrant 添加本地 box 安装 laravel homestead
  • 安装python包到指定虚拟环境
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 从0实现一个tiny react(三)生命周期
  • 关于字符编码你应该知道的事情
  • 缓存与缓冲
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 驱动程序原理
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 使用SAX解析XML
  • 手写一个CommonJS打包工具(一)
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • ​如何防止网络攻击?
  • #微信小程序(布局、渲染层基础知识)
  • $jQuery 重写Alert样式方法
  • (¥1011)-(一千零一拾一元整)输出
  • (1) caustics\
  • (16)UiBot:智能化软件机器人(以头歌抓取课程数据为例)
  • (Java)【深基9.例1】选举学生会
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (二)Linux——Linux常用指令
  • (附源码)php投票系统 毕业设计 121500
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (学习日记)2024.02.29:UCOSIII第二节
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (转)视频码率,帧率和分辨率的联系与区别
  • ***利用Ms05002溢出找“肉鸡
  • .cfg\.dat\.mak(持续补充)
  • .Mobi域名介绍
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .NET下ASPX编程的几个小问题
  • .NET学习全景图