getchar()详解

getchar()

从MSDN中查询getchar()会发现下面的描述

在这里插入图片描述getchar()的作用是从一个数据l流(stream是流的意思)中或者一个标准输入(stdin是标准输入的意思)读取一个字符。但是要注意的是,这个读取不仅仅是读,这个字符读完之后也会在这个数据流中删去。所以这个更应该理解为“取一个字符”

getchar()标准形式是
在这里插入图片描述
返回值类型是Int型,参数形式为viod形式

getchar()所需的头文件
所需要的头文件是
getchar()详解_第1张图片

getchar的返回值

在这里插入图片描述即:如果正常读取,返回的是读取的字符;而如果读取错误或者遇到文件结束的条件,则返回EOF;

所以,我们在使用getchar()函数时,基本模板如下:

int main()
{
	int getchar();
	return 0;
}

注意:这里返回值不要写成char型,因为定义里面的返回类型就是int型。当定义成char型时,在返回值是EOF时就有问题了。EOF实际就是负一(可以在vs2019中键入EOF,然后右击->转到定义,就可以看到如下代码)

#define EOF    (-1)

如果定义成char的话时是存不下-1的,因为一个是整型,一个是字符型,一个占32位,一个占8位。定义成int型后,实际上返回的就是读取字符的ASCII值,比如读取的是‘a’,那么返回值就是97.

应用举例
1.

int main()
{
	int ch = 0;
	while ((ch = getchar()) != EOF)
	{
		putchar(ch);
	}
	return 0;
}

这个代码执行结果就是输入一个字符,系统会自动打印一个相同的字符,输入EOF后,循环结束。
getchar()详解_第2张图片
注:EOF用键盘输入:ctrl+Z 。VS编译器bug会导致并不是每次一定摁ctrl+Z都会停下来,尤其是scanf函数的时候也是,scanf也是遇到END OF END时返回EOF,但是经常摁Ctrl+Z循环不停,要输入好几次Ctrl+Z才停。

2.运用getchar()函数来清理缓冲区

看下面这个例子

int  main()
{
	int arr[30] = { 0 };
	printf("请输入密码:>\n");
	scanf("%s", &arr);
	printf("密码是否输入正确?Y/N\n");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("输入正确!\n");
	}
	else if (ch == 'N')
	{
		printf("输出错误!\n");
	}
	return 0;
}

按道理,程序是没有错误的,先输入一个字符密码,然后输入Y,则输出密码正确,输入N,则输出密码错误。
但实际结果确是
getchar()详解_第3张图片
根本都没有第二个输入,程序就结束了

分析:
学过计算机组成的都知道,键盘是慢速的字符型设备,所以键入字符,系统读取键盘的键入字符实际是从键盘与系统之间的输入缓冲区中读入的。一开始没有输入时,缓冲区为空,然后执行到scanf的时候,用户输入123456,实际上缓冲区里输入的是123456\n,但是scanf取的数据是123456,所以scanf执行完,缓冲区里实际还留下了一个\n,然后getchar()取到的数据实际是\n,而\n的ASCII值与Y N的都不一样所以if elseif 都不会执行,直接执行 return 0 程序结束。

那么有什么解决办法呢?

第一反应是在输入Y N之前将\n拿掉,所以在scanf()后面再加一个getchar()

int  main()
{
	int arr[30] = { 0 };
	printf("请输入密码:>\n");
	scanf("%s", &arr);
	getchar();
	printf("密码是否输入正确?Y/N\n");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("输入正确!\n");
	}
	else if (ch == 'N')
	{
		printf("输出错误!\n");
	}
	return 0;
}

这样输出123456,就正确执行了
getchar()详解_第4张图片
但是如果输入123456 ABCDE就还是有问题
getchar()详解_第5张图片

这是因为scanf遇到空格的时候也会停止读取,这里涉及到的就是scanf()这个函数的特性详情请看下文。

scanf 中 %d 只识别“十进制整数”。对 %d 而言,空格、回车、Tab 键都是区分数据与数据的分隔符。当 scanf 进入缓冲区中取数据的时候,如果 %d 遇到空格、回车、Tab 键,那么它并不取用,而是跳过,继续往后取后面的数据,直到取到“十进制整数”为止。对于被跳过和取出的数据,系统会将它从缓冲区中释放掉。未被跳过或取出的数据,系统会将它一直放在缓冲区中,直到下一个 scanf 来获取。
但是如果 %d 遇到字母,那么它不会跳过也不会取用,而是直接从缓冲区跳出。所以上面这个程序,虽然 scanf 进入缓冲区了,但用户输入的是字母 a,所以它什么都没取到就出来了,而变量 i 没有值,即未初始化,所以输出就是 –858993460。
但如果将 %d 换成 %c,那么任何数据都会被当作一个字符,不管是数字还是空格、回车、Tab 键它都会取回。
————————————————
版权声明:本文为CSDN博主「沧州刺史」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_51574759/article/details/121054022

同样当scanf(“%s”),“”里面只有一个%s时,输入123
456 ABCDE,这样前面123456会当做第一个字符串被取出,到空格处系统就认为这个字符串结束了。

关于scanf()函数看
https://blog.csdn.net/zoe23333/article/details/122009836?ops_request_misc=&request_id=&biz_id=102&utm_term=scanf&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-122009836.nonecase&spm=1018.2226.3001.4187
这位博主和上面那位博主文章应该就可以理解。

那么还有没有其他解决办法呢?其实到这里就很好解决了,无非就是没有遇到‘\n’就一直取不就可以了,所以用一个while循环一下

int  main()
{
	int arr[30] = { 0 };
	printf("请输入密码:>\n");
	scanf("%s", &arr);
	int tmp = 0;
	while ((tmp = getchar()) != '\n');
	{
		;
	}
	printf("密码是否输入正确?Y/N\n");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("输入正确!\n");
	}
	else if (ch == 'N')
	{
		printf("输出错误!\n");
	}
	return 0;
}

getchar()详解_第6张图片

所以这个代码真正的使用场景时用来清理缓冲区

3.getchar()用于输入的很多字符,只打印数字字符。

int main()
{
	char ch = '\0';
	while ((ch = getchar()) != EOF)
	{
		if (ch < '0' || ch > '9')
		{
			continue;
		}
		else
		{
			putchar(ch);
			printf("\n");
		}
	}
}

getchar()详解_第7张图片

你可能感兴趣的:(c语言,基础,c语言,经验分享,笔记)