计算机及其程序的交互性是信息技术改变人类世界的重要原因之一
C语言也存在强大的I/O功能,在很多需要人机交互的场合,输入(Input)操作很重要
在刚开始学习C语言的时候,我们最经常见到的输入和输出形式是:输入数据 -> 输出打印,这个过程最有特征的地方在于需要按回车
其实对于计算机,我们按下键盘按键的时候,就已经输入了数据,但以上的I/O交互方式需要按ENTER表示输入处理
而有时候我们需要按下按键即刻输入,比如某种游戏中,这种情况应该怎么做呢?
我们首先需要了解一下C语言的缓冲区的概念(不难,编程时看不出,原理了解即可)
通常我们把输入字符立即有所显示的情况叫做立即回显,需要按下回车再输入处理显示的情况叫延迟回显
这两种情况除了形式上的区别,本质区别在于一个叫缓冲区的东西
1、对于立即回显,不需要缓冲区,即非缓冲输入,输入的内容程序立即可用
2、对于延迟回显,会有一个缓冲区存放输入的若干个字符,并在按下回车的时候将字符串交给程序使用,并清空缓存
为啥会有缓冲区这种东西呢?两个原因:
1、将若干个字符作为一个块发送给程序比把字符逐个发送要来得更快,这是输入长字符串时缓冲输入的优势
2、容错性,主要是容用户的错,比如输入hello却输入成了jello,用户发现后还来得及修改,但非缓冲输入就没有机会了
不过非缓冲输入也有自己的优势,比如其在游戏中的应用,游戏控制几乎不能忍受缓冲输入的形式,否则回车键会很快坏掉了
另外,缓冲输入的缓存也分为两类:
1、完全缓冲I/O:缓冲区满的时候被清空,缓冲内容发送到目的地,常见于文件输入
2、行缓冲I/O:典型的就是键盘输入,回车换行的时候清空缓存,内容发送到目的地
【程序演示】
1、缓冲输入:输入内容,按回车,显示内容,检测到#字符时退出
#include <stdio.h>
int main()
{
char ch;
while ((ch = getchar()) != '#') // getchar()是缓冲输入
putchar(ch);
return 0;
}
程序效果:(这也是个很好的验证getchar()和putchar()是单字符I/O的demo)
2、非缓冲输入:WASD控制游戏角色移动,其他输入跳过
#include <stdio.h>
int main()
{
char ch; // 输入的字符
int col = 0; // 换行控制
while (1)
{
ch = getch(); // 这个就是非缓冲输入用的输入函数,不同的平台可能不一样
// getche()也是非缓冲输入,但这个函数会实时回显,getch()不回显
switch (ch)
{
case 'w':
case 'W':
printf("上");
break;
case 'a':
case 'A':
printf("左");
break;
case 's':
case 'S':
printf("下");
break;
case 'd':
case 'D':
printf("右");
break;
default:
continue;
}
col++;
if(col == 20)
{
printf("\n");
col = 0;
}
}
return 0;
}
程序效果:每按下一个WASD,就会显示对应的动作
注意:
非缓冲输入没有统一标准,不同平台上的方式可能不同
比如上述的getche()和getch()函数其实是IBM PC兼容机的编译器中提供的一个专门用于非缓冲输入的函数系列,由conio.h支持
而UNIX中不同,UNIX自己控制缓冲,缓冲输入和非缓冲输入都是getchar()函数,但需要ioctl()函数指定(非标准C中的函数)
《C Primer Plus中文版》中的原话是:“简言之,不存在调用非缓冲输入的标准ANSI方式;使用方法取决于计算机系统。”
有空我再补充Linux下非缓冲输入的形式