getch()会显示最近输入的字符并跳过输入的所有其他字符

时间:2017-07-10 15:32:00

标签: c sockets ncurses getch

为课堂作业而且现在已经和ncurses战斗了一段时间(这对我来说是新的)。创建一个能够通过网络与同一程序的另一个实例进行通信的程序。该程序的一部分是以交互方式从键盘获取字符并将它们发送到接收方。 (我们建议使用单线程方法并在ncurses中使用getch,使用getch的非阻塞输入)。

我遇到的问题是我的getch有一些我无法弄清楚的行为。在不同的变体中,它将显示我键入的每个其他字符,并且在它之后键入另一个字符之前它不会显示最近键入的字符。我已经使用nodelay()来获取实时输入,但是。

这是我的ncurses显示的设置。 (注意:我之后使用noecho()我不想显示输入的每个字符。)

/* initialize ncurses */
setlocale(LC_ALL,"");
initscr();
cbreak();
noecho();
nodelay(stdscr, TRUE);
nonl();
intrflush(stdscr, FALSE);
keypad(stdscr, TRUE);
clear();

这是我编写的代码,它与getch一起使用,并通过套接字发送/接收数据。

while(1) {
    rfdset = master;

    if (select(maxfd + 1, &rfdset, NULL, NULL, NULL) < 0) {
        perror("select");
        exit(EXIT_FAILURE);
    }

    ch = getch();

    if (ch != ERR) {
        printw("%c",ch);
        write(direct, &ch, 1); // direction to send data
    }

    for(i = 0; i <= maxfd; i++) {
        if (FD_ISSET(i, &rfdset)) {
            bzero(msgbuf, MSGSIZE);
            idx = read(i, msgbuf, MSGSIZE);
            if (i != STDIN)
                printw("%s",msgbuf); // display received msg
        }
    }
}

当我运行它并在应用程序的任何一端输入数据时,我得到如下结果:

Computer 1 keyboard input: testing123
Computer 1 screen display: tsig2

Computer 2 message recv'd: tsig2

正因为如此,我确信getch导致了我的大多数问题,而且我必须在实施过程中遗漏或做错事。任何建议都表示赞赏。

修改1:

我设法通过删除for循环并直接检查套接字输入来解决所有其他字符问题。我很困惑为什么要修复它。现在我唯一剩下的问题是为什么在之后输入字符之前不会显示字符。这是我在while循环中修改的代码:

while(1) {
    rfdset = master;

    if (select(maxfd + 1, &rfdset, NULL, NULL, NULL) < 0) {
        perror("select");
        exit(EXIT_FAILURE);
    }

    ch = getch();

    if (ch != ERR) {
        printw("%c",ch);
        write(direct, &ch, 1);
    }

    /* check for incoming data from left socket */
    if (!NOLEFT && FD_ISSET(lcsad, &rfdset)) {
        bzero(leftmsg, MSGSIZE);
        idx = read(lcsad, leftmsg, MSGSIZE);
        leftmsg[idx] = 0;
        printw("%s", leftmsg);
        lm = 1;
    }

    /* check for incoming data from right socket */
    if (!NORIGHT && FD_ISSET(rsd, &rfdset)) {
        bzero(rghtmsg, MSGSIZE);
        idx = read(rsd, rghtmsg, MSGSIZE);
        rghtmsg[idx] = 0;
        printw("%s", rghtmsg);
        rm = 1;
    }

    /* check and send left message onward */
    if (lm && !NORIGHT) {
        write(direct, leftmsg, MSGSIZE);
    }

    /* check and send right message onward */
    if (rm && !NOLEFT) {
        write(direct, rghtmsg, MSGSIZE);
    }
    lm, rm = 0;
}

2 个答案:

答案 0 :(得分:1)

问题在于,因为 select 调用指定没有超时(最后一个参数为NULL),所以它会阻塞,直到有一些待处理的I / O(例如你键入的下一个字符)。此时,该计划会继续进入getch来电,该refresh来电printw(与struct timeval myTimeout; myTimeout.tv_sec = 0; myTimeout.tv_usec = 10000; 来电中的字符相呼应)。

指定一个短暂的超时,例如10毫秒,可以改善一些事情,例如,

myTimeout

并将select中的import ast data_string = "['Alena Andrejovská'],[['Economic Annals-XXI', '2016-10-10'], ['Journal of Applied Economic Sciences', '2016-09-01'], ['Acta Universitatis Agriculturae et Silviculturae Mendelianae Brunensis', '2016-01-01'], ['Agris On-line Papers in Economics and Informatics', '2016-01-01'], ['Actual Problems of Economics', '2016-01-01'], ['Acta Universitatis Agriculturae et Silviculturae Mendelianae Brunensis', '2015-01-01'], ['Actual Problems of Economics', '2015-01-01'], ['Journal of Applied Economic Sciences', '2015-01-01'], ['Journal of Applied Economic Sciences', '2014-01-01'], ['Journal of Applied Economic Sciences', '2013-01-01']]" data = ast.literal_eval(data_string) 地址传递给quotechar='~' ...

答案 1 :(得分:0)

如果使用wgetch()而不是getch()解决您的问题,您可以尝试。