getchar()函数的详解以及使用时需要注意的一些细节-C语言基础

这篇文章要探讨的是“getchar()函数的详解以及使用时需要注意的一些细节”。涉及getchar()函数的应用和需要注意的问题。属于C语言基础篇(持续更新)。
在C语言的学习过程中,我们常常需要接收键盘的输入,在接收键盘输入的过程中涉及到的函数通常有三个
getchar()、scanf()、fgets()。这三个函数各自的功能各不相同,需要我们根据不同的需求条件来选择不同的输入接收函数。而在这三个函数的使用过程中,有一些细节需要我们注意一下。所以接下来的三篇文章就是分别介绍这三个函数的。
getchar()(函数原型:int getchar(void))
一般用法:
char c = getchar();
getchar()函数的作用很简单,从输入缓存区中读取一个字符,读取到的字符储存在返回值里面。
getchar()函数注意事项1:
对于你输入的任何数据,getchar() 都会把它们当作是字符来处理,而且每次只获取一个字符。例如你输入“11”,getchar() 并不会把它当做“11”来处理,而是把它当做两个‘1’来处理。同理,你输入“3.14”它也不会当成“3.14”来处理而是当做‘3’、‘.’、‘1’、‘4’来处理,需要特别说明的是,像是换行符(\n)、回车符\归位符(\r)、缩进符(\t)之类的转义字符,它们虽然在代码中的表示和我们平时说明中用的是两个字符。但实际上它们在机器中存储和还是以一个字符来存储。所以别想着你敲个回车它能给你输入‘/’和‘n’。我们表示是这么表示,但在机器内部它就还是一个字符而已。
对于换行符(\n)和回车符(\r)的区别我在这里简单说一下。
换行符(\n)的作用是换一行输出。回车符(\r)的作用是把光标回到该行的行首。这两者的概念之所以有很多人会疑惑,这是由于我们平时的习惯称呼导致的。我们习惯性的把键盘上面那个换行回车键称为回车键,事实上它应该是两个键的混合(\r\n)。
同时也因为我们现在的开发环境便捷导致的,在一般的开发环境下面换行符(\n)就已经相当于同时具备换行回车(\r\n)的功能了,所以我们平时对于(\n)用的就比较多,(\r)就比较少用了。
但是如果在一些不那么高级的开发环境(例如小型嵌入式系统)下面的话,情况就不一样了,换行符(\n)就仅仅只是换行而已,你原本的光标在一行的哪个位置,就还在新行的哪个位置。你若想要光标回到行首,你就得手动输出回车符(\r)。
getchar()函数注意事项2:
getchar()函数是会阻塞等待的。在程序调用getchar()函数的时候如果缓存区中没有数据的话,getchar()函数便会阻塞等待用户的输入。
getchar()函数注意事项3:
用getchar()的返回值做判断的时候,需要考虑到是否存储保留的问题。无论你是否接收getchar()的返回值,只要你调用了getchar(),那么缓存区中就会被读取走一个字符。
这里用一个我曾经犯错误的例子来说明一下:
#include <stdio.h>
int main(void)
{
char c[100] = {0};//创建一个数组来存储输入
int i = 0;//记录一共输入了几个字符,方便后面输出。
while(1)
{
if(getchar() == ‘\n’)//先判断输入的是否是回车键
break;
c[i] = getchar();//再把判断好的输入值存储起来
i++;
}
for(int k = 0;k < i;k++)
printf("%c", c[k]);//把存储的值输出
printf("\n");
return 0;
}
这个程序所要实现的功能是“程序运行之后,持续的读取键盘的输入一直到用户输入换行符为止,然后退出循环输出读取到的内容”。
先看一下这个程序出现的问题吧:
运行的时候如果你输入数据的字符个数为单数的时候,你需要输入两次回车才能结束程序,而且程序读取到的输入总是用户输入的一半,而且是隔一个读取一个那种,最后面还多输出一个回车。

运行的时候如果你输入数据的字符个数为双数的时候,就还算正常,仅仅只是输入少一半而已。

其实仔细分析一下,就不难看出,这两种情况是可以归类为一种情况的。如果你把第一种情况中第一次输入的回车也看作一个字符的话,你就会发现,只有当你输入数据的字符个数为
双数的时候,你下一个输入的回车才能结束程序(也就是说如果我只在单数的时候输入回车,那么这个程序就会一直运行下去,直到一开始给的数组内存大小不够,程序访问到了非法内存才会结束)。也是因为第一次输入的回车被算进整体输入里面去了,才导致了第一种情况的时候结尾多了个换行。
再说一下原因吧:
出现这种情况的原因很简单,相信不少人也已经看出来了。在这个例子中我在判断输入是否是“\n”的时候就已经读取走一个字符了,后面再存储的时候已经是第二个字符了,所以就造成了“读取到的输入只有实际输入的一半这种情况”。
解决办法:
解决办法也不难,牺牲一个临时变量来存储输入的数据,再判断是否是回车键即可。
#include <stdio.h>
int main(void)
{
char c[100] = {0};//储存输入数据用的数组
int i = 0;//记录输入的字符个数方便输出
char z = 0;//解决方法就是加入临时变量来先储存再判断
while(1)
{
z = getchar();//先储存输入的数据
if(z == ‘\n’)//再判断
break;//如果是回车就退出循环
c[i] = z;//如果不是回车就存储
i++;//计数加一
}
for(int k = 0;k < i;k++)
printf("%c", c[k]);//把储存的数据输出
printf("\n");
return 0;
}
再附上这个例子的精简版代码:
#include <stdio.h>
int main(void)
{
int i = 0;
char c[100] = {0};
while((c[i++] = getchar()) != '\n');
for(int k = 0;k <= i;k++)
printf("%c", c[k]);
return 0;
}
getchar()函数注意事项4:
遇到再更新。。。
原博客始发于CSDN,在如今博客界的转载抄袭泛滥的环境下,原创不易,点个赞再走呗。以下是博客首页的链接。
getchar()函数的详解以及使用时需要注意的一些细节-C语言基础的更多相关文章
- C语言对文件的操作函数用法详解1
在ANSIC中,对文件的操作分为两种方式,即: 流式文件操作 I/O文件操作 一.流式文件操作 这种方式的文件操作有一个重要的结构FILE,FILE在stdio.h中定义如下: typedef str ...
- Go语言Slice作为函数参数详解
Go语言Slice作为函数参数详解 前言 首先要明确Go语言中实质只有值传递,引用传递和指针传递是相对于参数类型来说. 个人认为上诉的结论不对,把引用类型看做对指针的封装,一般封装为结构体,结构体是值 ...
- Scala进阶之路-Scala函数篇详解
Scala进阶之路-Scala函数篇详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.传值调用和传名调用 /* @author :yinzhengjie Blog:http: ...
- php中的PDO函数库详解
PHP中的PDO函数库详解 PDO是一个“数据库访问抽象层”,作用是统一各种数据库的访问接口,与mysql和mysqli的函数库相比,PDO让跨数据库的使用更具有亲和力:与ADODB和MDB2相比,P ...
- C语言对文件的操作函数用法详解2
fopen(打开文件) 相关函数 open,fclose 表头文件 #include<stdio.h> 定义函数 FILE * fopen(const char * path,const ...
- MySQL UUID函数的详解(转)
MySQL UUID函数的详解 MySQL中可以有二类用于生成唯一值性质的工具:UUID()函数和自增序列,那么二者有何区别呢?我们就此对比下各自的特性及异同点: l 都可以实现生成唯一值的功能: ...
- 自写函数VB6 STUFF函数 和 VB.net 2010 STUFF函数 详解
'*************************************************************************'**模 块 名:自写函数VB6 STUFF函数 和 ...
- SQL Server数据库ROW_NUMBER()函数使用详解
SQL Server数据库ROW_NUMBER()函数使用详解 摘自:http://database.51cto.com/art/201108/283399.htm SQL Server数据库ROW_ ...
- PHP函数篇详解十进制、二进制、八进制和十六进制转换函数说明
PHP函数篇详解十进制.二进制.八进制和十六进制转换函数说明 作者: 字体:[增加 减小] 类型:转载 中文字符编码研究系列第一期,PHP函数篇详解十进制.二进制.八进制和十六进制互相转换函数说明 ...
- PHP date函数参数详解
PHP date函数参数详解 作者: 字体:[增加 减小] 类型:转载 time()在PHP中是得到一个数字,这个数字表示从1970-01-01到现在共走了多少秒,很奇怪吧 不过这样方便计 ...
随机推荐
- SAP管理员SAP*和DDIC被锁定后如何解锁或重置密码
SAP*初始化密码是06071992或passDDIC默认密码为19920706 环境信息:win server2003,SQL Server2008 R2 账号信息存在于数据库usr02表中,1.删 ...
- vvv动态组件和keep-alive
<!DOCTYPE html><html> <head> <style> </style> <script src="a.j ...
- Linux下如何排查CPU及内存占用过多
CPU 使用top命令,然后按shift+p按照CPU排序,找到占用CPU过高的进程pid. 使用top -H -p pid命令,找到进程中消耗资源最高的线程ppid. 使用echo 'obase=1 ...
- HttpClient详细使用示例(转)
https://blog.csdn.net/justry_deng/article/details/81042379
- sqlserver存储过程学习
存储过程学习 一.定义变量 --简单赋值 declare @a int set @a=5 print @a --使用select语句赋值 declare @user1 nvarchar ...
- [CSS]使用JS改变元素位置,操作css比较困难时,可更换元素的类名
本人大菜鸟一枚,以此作为记录. 使用到技术栈jQuery. 开发中遇到某个元素需要在页面上切换 left: 0px 为 right: 0px 的需求,直接操作css会导致同时存在left和right属 ...
- Pytest Fixture(一)
Fixture 是一些函数,pytest 会在执行测试函数之前(或之后)加载运行它们.我们可以用它做一些事情,比如数据库的链接操作之类的 import pytest @pytest.fixture() ...
- linux(centos7)下部署jenkins
1.安装jdk yum install -y java 确保已经安装了jdk,查看是否安装jdk命令参考地址: 2.安装jenkins 2.0添加Jenkins库到yum库,Jenkins将从这里下载 ...
- Position Based Dynamics【译】
绝大部分机翻,少部分手动矫正,仅供参考.本人水平有限,如有误翻,概不负责... Position Based Dynamics Abstract The most popular approaches ...
- .Net 6.0服务器环境配置以及IIS发布部署心得
经过长达一个月的时间,对.Net 后端开发后的发布以及服务器域名等网站搭建全部过程留档,也帮助有需要的同志进行学习以及查看 https://www.cnblogs.com/xingmengcode/a ...
