getchar()和scanf()混合使用的坑

摘要:
最近,当我们混合getchar()和scanf()时,遇到了一个漏洞。现在记录它。在代码中,getchar()用于处理字符输入,scanf()用于数字输入。Getchar()读取每个字符,包括空格、制表符和换行符;而scanf()在读取数字时跳过空格、制表符和换行符。当程序运行到下一个循环的getchar()函数时,getchar(()函数将读取换行符,导致程序直接结束。=“”){if(scanf(“%d%d”,&rows,&cols)!=“”)continue;printf;printf,}printf;返回0;}无效显示{int row,col;for{for pushar;pushar(“”);/*结束一行并开始一行*/}}如果发现错误,请在评论区指出。

最近在混合使用 getchar()scanf() 的时候遇到一个坑,现在记录一下。

代码中使用 getchar() 处理字符输入,用 scanf() 处理数字输入。

getchar() 读取每个字符,包括空格、制表符和换行符; 而 scanf() 在读取数字时则会跳过空格、
制表符和换行符。

比如下面这个程序,读入一个字符和两个数字,然后根据输入的两个数字指定的行数和列数打印该字符。

#include <stdio.h>
void display(char cr, int lines, int width);
int main(void)
{
	int ch;        /* 待打印字符 */
	int rows, cols;    /* 行数和列数 */
	printf("Enter a character and two integers:
");
	while ((ch = getchar()) != '
')
	{
		scanf("%d %d", &rows, &cols);
		display(ch, rows, cols);
		printf("Enter another character and two integers;
");
		printf("Enter a newline to quit.
");
	}
	printf("Bye.
");
	return 0;
}

void display(char cr, int lines, int width)
{
	int row, col;
	for (row = 1; row <= lines; row++)
	{
		for (col = 1; col <= width; col++)
			putchar(cr);
		putchar('
');/* 结束一行并开始新的一行 */
	}
}

编译、运行程序,发现程序在输出 Enter a newline to quit. 之后就自动退出了。

原来,在输入了一个字符和两个数字之后,需要敲一个回车键,回车键产生了一个换行符。这个换行符不会被例程中的 scanf() 读取,但它会继续留在输入队列中。当程序运行到下一轮循环的 getchar() 函数时,换行符就会被 getchar() 函数读取,导致程序直接结束了。

解决方法:可以在循环内部添加如下代码来消耗输入队列中的换行符以及其他多余的字符:

while (getchar() != '
')
      continue;

完整代码如下:

#include <stdio.h>
void display(char cr, int lines, int width);

int main(void)
{
	int ch;        /* 待打印字符*/
	int rows, cols;    /* 行数和列数 */
	printf("Enter a character and two integers:
");
	while ((ch = getchar()) != '
')
	{
		if (scanf("%d %d", &rows, &cols) != 2)
			break;
		display(ch, rows, cols);
		while (getchar() != '
')
			continue;
		printf("Enter another character and two integers;
");
		printf("Enter a newline to quit.
");
	}
	printf("Bye.
");
	return 0;
}

void display(char cr, int lines, int width)
{
	int row, col;
	for (row = 1; row <= lines; row++)
	{
		for (col = 1; col <= width; col++)
			putchar(cr);
		putchar('
');  /* 结束一行并开始新的一行 */
	}
}

如发现有不对的地方,欢迎在评论区指出。

免责声明:文章转载自《getchar()和scanf()混合使用的坑》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇NFS服务器搭建——可用于共享文件或负载均衡文件共享服务器使用LSMTree (BigTable 的理论模型)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

数据对齐

许多计算机系统对数据类型的合法地址做了一些限制,要求某种数据类型对象的地址必须是某个值K(2,4,8)的倍数,这种堆积限制简化形成了处理器和存储器系统之间接口的硬件设计,总之就是为了方便高效的读取数据,于是就有了数据对齐。 struct S1 { char k; double i; char c; }; Sizeof(S1)的...

SQL Convert的用法

CONVERT 函数 [数据类型转换]-------------------------------------------------------------------------------- 功能  返回转换成提供的数据类型的表达式。 语法 CONVERT ( data type, expression [ , format-style ] )...

oracle语句,时分秒格式转成秒

select (hours+minutes+seconds) AS total_seconds from( selectto_char(sysdate,('HH24'))*60*60 AShours, to_char(sysdate,('mi'))*60 ASminutes, to_char(sysdate,'ss') ASseconds fromA );...

ThinkPHP第二十五天(自动完成、用户名密码PHP正则、移位或加密函数)

1、ThinkPHP自动完成功能   跟昨天的自动验证功能类似,也是需要在自定义的UserModel类,进行使用。   使用方法:定义$_auto属性   $_auto = array(     array(完成字段,完成规则,完成时间,附加条件),     ......   );   完成字段:需要自动完成的字段,   完成规则:对字段进行自动完成的规则...

Transfer-Encoding: chunked

Http1.1中 使用 chunked 编码传送时 没有CONTENT_LENGTH,下载之前无法确定要下载的大小. Wininet中已经内嵌该传输协议,要查看chunked块的大小只能socket底层编写获取报文. Wininet能不能直接访问原报文需走旁路. // socket_http.cpp : Defines the entry point...

C#中ASCII码与字符串的互换

主要代码: int a = (int)'a';// 把字符直接转换为int类型,即可得到ASCII码值 string A = ((char)65).ToString();// 将数字直接转换为char类型,即可得到ASCII码对应的字符 Console.WriteLine("a的ASC...