1.无ncurses的非阻塞用户输入循环

无ncurses的非阻塞用户输入循环。

 

标题听起来有点尴尬,让我简要解释一下这是关于什么的。

在我的程序中,我想等待用户输入,但同时,我希望我的其他操作继续处理。我将其定义为非阻塞用户输入。我希望我的程序在循环中等待用户输入,如果接收到用户输入处理它并继续等待下一个用户输入,否则继续处理其他循环操作。

通常,人们会考虑使用ncurses库。通过使用ncurses,可以使用timeout(0)和getch()轻松执行非阻塞用户输入。引用ncurses矩阵作为参考。

如果我不想使用ncurses怎么办?有其他选择吗?有时我只是想在一个大程序中添加一个需要非阻塞的函数,我不想使用ncurses,因为它使我的打印行行为不同,或者其他原因。

多亏了##c@irc.freenode.net上的程序员,我找到了一种方法。它可能看起来很凌乱,但它的工作方式是我想要的。我使用termios的函数并选择,让我们一个一个的来看函数。

 

01

02

03

04

05

06

07

08

09

10

11

int kbhit()

{

    struct timeval tv;

    fd_set fds;

    tv.tv_sec = 0;

    tv.tv_usec = 0;

    FD_ZERO(&fds);

    FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0

    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);

    return FD_ISSET(STDIN_FILENO, &fds);

}

此函数在没有超时0、tv的情况下对标准输入(stdin)执行非阻塞检查。tv_sec和电视。tv_usec都设置为零。select通常用于需要处理多个I/O的情况,或者同时进行检查。但是在本例中,我只对标准输入感兴趣,因此只有一个FD_SET(STDIN_FILENO, &fds)是触发器。有关选择参数的详细信息,请参阅手册。似乎我们只对输入感兴趣,所以我们将fd set放在第二个参数select()处,第3个参数用于输出,第4个参数用于异常。

重要部分,选择if user input is trigger后,FD_ISSET将返回非零值,否则返回0。现在我们可以这样用

1

2

3

4

5

while(!kbhit())

{

      //do certain operation..

}

//user hits enter.

由于终端的规范模式,您需要按enter来确认用户输入。规范模式意味着它总是等待enter来确认用户输入。如果这不是你的情况,bellow是另一个功能来迎合这一点。

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

void nonblock(int state)

{

    struct termios ttystate;

 

    //get the terminal state

    tcgetattr(STDIN_FILENO, &ttystate);

 

    if (state==NB_ENABLE)

    {

        //turn off canonical mode

        ttystate.c_lflag &= ~ICANON;

        //minimum of number input read.

        ttystate.c_cc[VMIN] = 1;

    }

    else if (state==NB_DISABLE)

    {

        //turn on canonical mode

        ttystate.c_lflag |= ICANON;

    }

    //set the terminal attributes.

    tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);

 

}

函数名可能有误导作用,函数实际上做的是关闭stdin的规范模式。首先,获取term的状态。接下来,通过将0设置为位,关闭正则表达式。ttystate的行。c_cc[VMIN]是设置要接受的用户输入的最小数量。如果将其设置为2,select将等待,直到给出2个字符,然后它将捕获作为输入。最后设置术语状态。这个函数实际上允许您打开和关闭规范模式。

好的,让我们看看它是如何工作的

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

int main()

{

    char c;

    int i=0;

 

    nonblock(NB_ENABLE);

    while(!i)

    {

        usleep(1);

        i=kbhit();

        if (i!=0)

        {

            c=fgetc(stdin);

            if (c=='q')

                i=1;

            else

                i=0;

        }

 

        fprintf(stderr,"%d ",i);

    }

    printf("\n you hit %c. \n",c);

    nonblock(NB_DISABLE);

 

    return 0;

}

按“q”键会导致程序退出,否则你会看到“0”的打印在屏幕上。观察到我在循环中使用的是usleep(1),在不使用usleep的情况下,程序的响应性更强,但是它使用了高CPU资源。另一方面,使用usleep(1)会减少CPU资源,也会降低程序的响应性。根据你的需要,你可以选择是否把它放进去。

 

我已经比较了这个应用程序和一个简单的ncurses程序,这个程序似乎使用较少的内存。无法测量CPU资源,因为ps和top都显示0.0%。

Curses sample shows as bellow:

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

#include<stdio.h>

#include<curses.h>

#include<unistd.h>

 

int main ()

{

    int i=0;

 

    initscr();     //in ncurses

    timeout(0);

    while(!i)

    {

        usleep(1);

        i=getch();

        printw("%d ",i);

        if(i>0)

            i=1;

        else

            i=0;

    }

    endwin();

    printf("\nhitkb end\n");

    return 0;

}

Download the source code:
Non-blocking kbhit sample source code.(失效)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值