为什么在这种情况下会显示printw?

时间:2019-05-21 20:33:27

标签: c ncurses

在这种情况下,printw为什么显示“ Blah”?我使用nocbreak。因此printw不应正常产生输出,因为输出是行缓冲的。

int main(int ac, char **av)
{
    initscr();
    nocbreak();
    printw("Blah");
    refresh();
    while (1);
}

2 个答案:

答案 0 :(得分:3)

实际上,printw 不是 行缓冲的。 ncurses将终端初始化为原始模式,并根据需要模拟熟化模式。但这仅适用于 输入 。对于输出,ncurses将立即按照manual page中所述将相关更新写入屏幕:

  

refresh wrefresh 例程(或 wnoutrefresh 和doupdate)必须   被调用以获取到终端的实际输出,因为其他例程仅操纵数据结构。 例程 wrefresh 复制命名的   窗口,进入物理屏幕,并考虑到已经存在的内容   在那里做优化。 refresh 例程是相同的,使用 stdscr 作为默认窗口。除非 leaveok < / strong>已启用,终端的物理光标留在光标所在的位置   那个窗口。

物理屏幕 是您的终端。 ncurses通过将其记录在curscr中来记住那里的内容:

  

此诅咒的实现使用特殊的窗口 curscr 进行记录          其更新到终端屏幕。

     

这在curs_refresh(3x)中称为 “物理屏幕”   和curs_outopts(3x)手册页。

从ncurses的角度来看,终端(您看到)和 curscr 是同一件事。

对于printw,手册页说它的行为就像调用waddstr,然后依次调用 waddch

  

这些函数将(以空字符结尾的)字符串str写入到   给定的窗口。这类似于为每个字符调用一次waddch   在字符串中。

答案 1 :(得分:1)

这是因为调用了refresh

refresh man page并未明确声明它,但似乎也应用了缓冲的输出。

如果没有调用refresh,则不会显示任何输出。

如果将呼叫添加到getch而不是refresh,也会得到输出,因为getch进行了wrefreshMan page

  

如果窗口不是填充板,并且自上次调用wrefresh以来已对其进行了移动或修改,则会在读取另一个字符之前调用wrefresh。

要查看cbreak / nocbreak模式下输入的不同行为,可以使用以下程序:

int main(int ac, char **av)
{
    char c, i;
    initscr();
    noecho();  // switch off display of typed characters by the tty

    printw("cbreak\n");
    cbreak();
    for (i = 0; i < 5; ++i) {
        c = getch();
        printw("%c", c);
    }

    printw("\nnocbreak\n");
    nocbreak();
    for (i = 0; i < 5; ++i) {
        c = getch();
        printw("%c", c);
    }

    return 0;
}

在cbreak模式下,程序会在您键入五个输入字符时看到它们(并由于getch而立即输出)。在nocbreak模式下,只有按回车键才能接收和输出它们。