22.Linux:getch(){isatty(),tcgetattr(),tcsetattr()}(转载)

转载地址:http://blog.csdn.net/sdkhy0808/article/details/36172009

<termios.h>

<unistd.h>
int tcgetattr(int fd, struct termios *termios_p);

int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);

getch的代码如下:

static int getch(void)

{
struct termios oldt,newt;
int ch;
if (!isatty(STDIN_FILENO)) {
fprintf(stderr, "this problem should be run at a terminal\n");
exit(1);
}
// save terminal setting
if(tcgetattr(STDIN_FILENO, &oldt) < 0) {
perror("save the terminal setting");
exit(1);
}
// set terminal as need
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
if(tcsetattr(STDIN_FILENO,TCSANOW, &newt) < 0) {
perror("set terminal");
exit(1);

}

ch = getchar();

// restore termial setting
if(tcsetattr(STDIN_FILENO,TCSANOW,&oldt) < 0) {
perror("restore the termial setting");
exit(1);
}
return ch;

}

刚开始不明白,这个函数最终返回的是ch,而ch=getchar(),与getch函数中的其他均无关系,为何不只用getchar,其他的到底什么作用?后来我逐个实验了一下,才知道其中的区别。

如果只用getchar的话,运行程序时,按下一个按键,比如 ESC,那么界面上会显示一个乱码,并且不会立即起作用,只有按下Enter键才会起作用。而用getch中的几个函数,可以设置终端输入的属性,比如不让字符在界面上显示,输入字符立即起作用。下面就对其中的3个函数的作用进行分析。

1、isatty(STDIN_FILENO) 判断是否为终端输入,如果是,则返回1,否则返回0。

当然也可以判断输出,那么函数写为isatty(STDOUT_FILENO) 。

关于isatty的参数,详解:

对一个进程预定义了三个流,并且这三个流可以自动地被进程使用,它们是:标准输入、标准输出和标准出错,即TDIN_FILENO、STDOUT_FILENO和STDERR_FILENO。

2、tcgetattr(STDIN_FILENO, &oldt) 用来获取终端输入的属性,并保存在结构体oldt中。

分析:获取终端输入属性的目的在于后面的恢复。

3、tcsetattr(STDIN_FILENO,TCSANOW, &newt) 用来设置终端输入的属性,通过结构体newt。

1)第二个参数可以取以下3个值:

TCSANOW:不等数据传输完毕就立即改变属性。
TCSADRAIN:等待所有数据传输结束才改变属性。
TCSAFLUSH:清空输入输出缓冲区才改变属性。

可以按照自己的需要进行设置。

2)结构体 termios newt有以下几个成员

{c_iflag:输入模式标志,控制终端输入方式

c_oflag:输出模式标志,控制终端输出方式

c_cflag:控制模式标志,指定终端硬件控制信息

c_lflag:本地模式标志,控制终端编辑功能}

这里只用到了c_lflag,c_lflag的参数如下:
ISIG:当输入INTR、QUIT、SUSP或DSUSP时,产生相应的信号
ICANON:使用标准输入模式
XCASE:在ICANON和XCASE同时设置的情况下,终端只使用大写。
ECHO :显示输入字符
ECHOE:如果ICANON同时设置,ERASE将删除输入的字符
ECHOK:如果ICANON同时设置,KILL将删除当前行
ECHONL:如果ICANON同时设置,即使ECHO没有设置依然显示换行符
ECHOPRT:如果ECHO和ICANON同时设置,将删除打印出的字符(非POSIX)
TOSTOP:向后台输出发送SIGTTOU信号

上述代码中,用的是newt &= ~(ICANON | ECHO);那么,就不使用标准输入模式,不显示输入字符。

如果想采用标准输入模式,显示输入字符,那么newt = ICANON | ECHO。

4、tcsetattr(STDIN_FILENO,TCSANOW,&oldt) 恢复终端输入属性。

刚开始不明白这句的意义,于是实验了一下。如果去掉这句的话,发现当我程序退出后,输入命令输入不进去,其实已经输入进去了,只是没有显示。因为现在的输入属性是newt新设置的,而不是原来的oldt,所以必须得恢复。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值