专栏首页nnngugetchar()和scanf()混合使用的坑

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

最近在混合使用 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:\n");
	while ((ch = getchar()) != '\n')
	{
		scanf("%d %d", &rows, &cols);
		display(ch, rows, cols);
		printf("Enter another character and two integers;\n");
		printf("Enter a newline to quit.\n");
	}
	printf("Bye.\n");
	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('\n');/* 结束一行并开始新的一行 */
	}
}

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

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

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

while (getchar() != '\n')
      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:\n");
	while ((ch = getchar()) != '\n')
	{
		if (scanf("%d %d", &rows, &cols) != 2)
			break;
		display(ch, rows, cols);
		while (getchar() != '\n')
			continue;
		printf("Enter another character and two integers;\n");
		printf("Enter a newline to quit.\n");
	}
	printf("Bye.\n");
	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('\n');  /* 结束一行并开始新的一行 */
	}
}

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 算法04 七大排序之:归并排序

    上一篇总结了直接插入排序和希尔排序,这一篇要总结的是归并排序,这也是七大排序的最后一种排序算法。 首先来看一下归并排序(Merge Sort) 的基本原理。它的...

    nnngu
  • 算法01 七大排序之:冒泡排序和快速排序

    排序是我们生活中经常会面对的问题。同学们做操时会按照从矮到高排列;老师查看上课出勤情况时,会按学生学号顺序点名;高考录取时,会按成绩总分降序依次录取等。排序是数...

    nnngu
  • 经典Java面试题收集

    2、访问修饰符public,private,protected,以及不写(默认)时的区别?

    nnngu
  • Python操作docx文档设置居中并创建表格

    功能描述:本文代码使用python-docx操作docx文档,添加一段文字并设置居中对齐,添加一个表格并为所有单元格设置文字。 from docx impor...

    Python小屋屋主
  • Educational Codeforces Round 59 (Rated for Div. 2) B. Digital root(思维)

    题目链接:http://codeforces.com/contest/1107/problem/B

    Ch_Zaqdt
  • VM技术(二)从CHIP8入手CPU的模拟(三)

    前面提到CHIP8的显示器是64x32黑白像素的显示器,所以我们在QT中定义一个OpenGL的Wedgit显示到窗口中,同时把keymap和游戏循环设置在主窗体...

    Pulsar-V
  • android bitmap的缓存策略

    不论是android还是ios设备,流量对于用户而言都是宝贵的。在没有wifi的场景下,如果加载批量的图片消耗用户过多流量,被其知晓,又要被念叨一波~ ? 如...

    MelonTeam
  • 基本数据类型及其包装类(一)

    我们都说,Java 是一门面向对象型程序设计语言,但是它设计出来的「基本数据类型」仿佛又打破了这一点,所以,只能说 Java 是非 100% 纯度的面向对象程序...

    Single
  • 消失的Java进程-Linux OOM Killer

    -Xmx和-Xms分别是用于指定该Java进程初使化的最小堆内存以及可以使用的最大堆内存的,这里设置为10M

    极客小智
  • linux系统编程之信号(五):实时信号与sigqueue函数

    一、sigqueue函数 功能:新的发送信号系统调用,主要是针对实时信号提出的支持信号带有参数,与函数sigaction()配合使用。 原型:int sigqu...

    s1mba

扫码关注云+社区

领取腾讯云代金券