文章一览
- 写在前面
- 一、scanf、getchar与gets函数的爱恨情仇
- 1.1 scanf函数
- 1.1.1 %c输入单个字符
- 2. %s 输入字符串
- 1.1.3 %d输入数字
- 1.2 getchar函数
- 1.3 gets函数
- 二、不同输入情况下的使用
- 三、回顾C语言的输入函数
- 总结
写在前面
在之前的文章中,笔者详细介绍了scanf
函数的使用(scanf函数从入门到精通),但是在后续的使用中发现,还是有一些细节的地方没有很好的处理,容易导致系统奔溃。
那么接下来的部分就让大家跟随笔者的思路一起探讨一下这部分的处理。(以下观点仅为笔者观点,如有不当之处欢迎大家指出。)
一、scanf、getchar与gets函数的爱恨情仇
这三个函数都是C语言中的输入流函数,但是各自的使用有所不同。从名字上来看,scanf
函数是格式化输入函数,所以理论上来说它可以输入各种数据;getchar
函数是字符输入函数,它只能以字符形式输入且每次输入一个;gets
函数是一个字符串输入函数,它每一次可以将一行字符输入到某地址。
1.1 scanf函数
scanf函数在遇到“空白字符”时会结束掉,并且该空白字符依然在缓冲区中。
这里的空白字符指:空格、换行符(\n)、制表符(\t)等。
1.1.1 %c输入单个字符
使用%c
格式化输入时,与getchar作用一致,也可以接收到'\n'
这种空白字符。
2. %s 输入字符串
可以看到在使用%s
格式化输入时,scanf函数会输入'\n'
之前的字符,并且在输入完成后默认为字符串末尾加上一个'\0'
,这时末尾的'\n'
依然留在缓冲区。
当标准输入有**“空白字符”**时scanf函数会结束掉,把之前的字符串放到字符串中,同样在末尾加上一个'\0'
,后面的空格' '
也依然在缓冲区中。
1.1.3 %d输入数字
正常输入时,同样的情况,缓冲区中依然会留着'\n'
输入完两个数字之后,空格再加回车,后面的空格依然留在缓冲区中。
输入一堆空格然后再输入数字,对数字的输入是没有任何影响的,可以参考前言中的文章,%d的格式输入符会让%d 去寻找到数字才开始输入。
在scanf函数中接收最后一个数字(%d)后打上一个空格(也就是去接收一个空格)时,在输入第二个数字之后不管输入多少个空格都不会留到缓冲区,并且连\n
都会被处理掉,不留在缓冲区。
1.2 getchar函数
getchar函数的使用比较简单,每次都会吸收一个字符,不管任何字符都可以被吸收。
这里的任何字符包括了空格等字符,没有被接收的字符依然在缓冲区,也包括'\n'
。
1.3 gets函数
gets函数的使用也比较简单,它只在遇到\n
才会停止,也就是说只能读取一行。
下面由于VS不支持gets了,对gets进行了安全保护改造为gets_s函数,但是原理是一样的。
如图可见,gets函数在遇到换行符(\n
)时停止,往写入的字符串末尾加上'\0'
(这里类似scanf函数的%s输入),接下来会处理掉末尾的'\n'
(这里与scanf函数不同)。
在遇到空格等任何字符都会正常接收。
当在标准输入流中手动输入'\n'
时,编译会认为你只是想输入\
和n
两个字符,而不是'\n'
, 编译器会自动改造\
为\\
也就是加入了一个转义字符。
二、不同输入情况下的使用
那么有了理论我们做几个题来巩固一下,实现下列输入:
- 输入三个数字
- 输入两个数字之后,下一行输入一个字符(数字之后无空格等符号)
- 输入两个数字之后,下一行输入一个字符(数字之后可能带有或不带空格字符)
- 第一行输入一个字符串(字符串中可能包含空格),第二行输入一个数字(考虑分别使用gets和scanf函数)
- 第一行输入一个字符串(字符串中可能包含空格),第二行再输入一个字符串
- 第一行输入一个字符串(字符串中可能包含空格),第二行输入一个字符
做出来之后可以发到评论区晒晒哟,看看你自己会做了没有!!!
三、回顾C语言的输入函数
scanf、getchar、gets函数的对比:
函数 | 输入格式 | 是否可以输入空格字符 | 是否自动处理’\n’ | 是否自动加入’\0’ |
---|---|---|---|---|
scanf(“%c”) | 字符 | 是 | 否 | ------ |
getchar() | 字符 | 是 | 否 | ------ |
scanf(“%s”) | 字符串 | 否 | 否 | 是 |
gets() | 字符串 | 是 | 是 | 是 |
scanf(“%d”) | 十进制整数 | ------ | 否 | ------ |
总结
在使用这些函数时,需要关注错误处理。例如,scanf函数在读取失败时会返回EOF,而getchar也会在遇到文件末尾或读取错误时返回EOF。正确处理这些错误情况可以提高程序的健壮性。
- 安全性:gets函数因其缓冲区溢出风险而被弃用,这强调了在处理输入数据时考虑安全性的重要性。使用fgets等更安全的函数可以减少潜在的安全漏洞。
- 跨平台兼容性:
跨平台编程:尽管这些函数的行为在不同操作系统上可能略有差异(特别是在处理换行符时),但它们通常都是跨平台兼容的,使得编写能够在多种操作系统上运行的程序成为可能。
scanf、gets(及其更安全的替代fgets)和getchar函数在C语言中的应用广泛且重要,它们不仅用于读取用户输入和处理数据,还涉及到用户交互、文本处理、错误处理和安全性等多个方面。在编写C语言程序时,合理利用这些函数可以大大提高程序的灵活性和实用性。