Ubuntu下编写终端界面交互式C++小程序的一些Trick(小技巧,gnome-terminal)

时间:2021-03-21 09:17:25

类getch()功能的实现

I

只要在Windows下用过C/C++就会很熟悉conio.h库中的一个函数getch(),它可以绕过终端输入缓冲区直接从键盘读取一个字符,并且不在界面上显示。

但如果想直接在Linux环境下用是不行的,因为没有conio.h库的支持。

博主翻了网上的一些资料,在这里给出一个比较简明的实现,使用起来与Windows下没什么差异。

#include<cstdio>
#include<cstdlib>
inline char getch(){
    static char ch;
    system("stty -icanon -echo");
    scanf("%c",&ch);
    system("stty icanon echo");
    return ch;
}

II

不知道大家有没有遇到这样的问题:平时所见的输入语句都需要等待我们输入完才会执行完成,什么都不做的话就会一直阻塞在那里。但我们有时想让程序在尝试接收读入失败的时候能够继续执行下去。这样要怎么实现呢?

我们需要一个函数fcntl,包含在fcntl.h中。使用它可以取消输入阻塞。关于它的更详细的内容可以百度。

我们还需要一个函数read,包含在unistd.h中,是一个底层的输入函数。

定义一个CustomGetch类,包含构造函数、析构函数和运算符()重载,再定义一个该类变量getch,用起来就像函数一样。

#include<cstdlib>
#include<fcntl.h>
#include<unistd.h>
class CustomGetch{
public:
    CustomGetch(){
        fcntl(0,F_SETFL,O_NONBLOCK);
        system("stty -icanon -echo");
    }
    ~CustomGetch(){
        fcntl(0,F_SETFL,0);
        system("stty icanon echo");
    }
    inline char operator()(){
        static char ch;
        return ~read(0,&ch,1)?ch:EOF;
    }
}getch;

这样写有一个局限性:在这个变量的生存周期内,不能和其它的输入方式兼容。因此有两种处理方案:

  1. 在需要getch()而不需要其它输入方式的语句块内定义临时变量。
  2. 直接像I中的那个getch()一样写成函数。但考虑到实际应用中要频繁调用这个函数对输入流进行检查,而system操作相当耗时,所以不推荐这样做。

清屏

因为system("clear")是个假的清屏,所以我们需要更好的实现。

printf("\033c");

对,没了,就一行。

程序示例

#include<cstdio>
#include<cstdlib>
int main(){
    for(int i=0;;++i){
        printf("\033c");
        for(int j=0;j<4;++j)puts(1&i?"abcdefg":"abcbefg");
        system("sleep 1");
    }
    return 0;
}

更改输出起始位置、输出字体颜色

Linux终端有专门的转义字符。看这个博客