NCurses 标准输入重定向
NCurses stdin redirection
我不明白为什么 getch() 函数 returns 如果我有一个应用程序,它总是出错
以这种方式设置(剥离到骨头):
static char data[DATA_SIZE]; // Very big - covers all input for sure
int main(int argn, char ** argv)
{
// Slurp the file in
int length = read(0, &data[0], DATA_SIZE);
if (length == 0)
{
fprintf(stderr, "Nothing to read\n");
return 0;
}
initscr();
cbreak();
refresh();
WINDOW * woutput = newwin(LINES - 1, COLS, 0, 0);
WINDOW * winput = newwin(1, COLS, LINES - 1, 0);
wattron(winput, A_REVERSE);
keypad(winput, TRUE);
//print the data buffer into a window
int c;
while ((c = wgetch(winput)) != 'q')
{
}
}
我运行是这样申请的:
./application < path/to/file
但是wgetch的结果总是'ERR'
。
由于您已读取 stdin
直到文件末尾,因此 wgetch
在尝试读取时将立即接收到文件末尾。但是无论如何,您都不希望 ncurses 使用重定向的 stdin
;你想让它使用终端。
这样做的一种方法是在调用 initscr
:
之前简单地重新打开 stdin
作为终端
#include <stdio.h>
#include <ncurses.h>
int main(int argn, char ** argv)
{
// Just discard all of stdin for a minimal example
while (fgetc(stdin) != EOF) { }
// See note
if (!freopen("/dev/tty", "r", stdin)) {
perror("/dev/tty");
exit(1);
}
initscr();
cbreak();
refresh();
WINDOW * woutput = newwin(LINES - 1, COLS, 0, 0);
WINDOW * winput = newwin(1, COLS, LINES - 1, 0);
wattron(winput, A_REVERSE);
keypad(winput, TRUE);
// Echo input into full screen
int c;
while ((c = wgetch(winput)) != 'q') { wechochar(woutput, c); }
endwin();
return 0;
}
如果您发现 freopen
难以遵循,您可以将它和以下对 initscr
的调用替换为
FILE* tty = fopen("/dev/tty", "r");
if (!tty) { perror("/dev/tty"); exit(1); }
if (!newterm(NULL, stdout, tty) {
fprintf(stderr, "%s\n", "Unable to initialise ncurses");
exit(1);
}
注:
在上面的代码中,我只是使用 /dev/tty
作为控制台的名称,它可能会在任何适度 Posix 兼容的系统中工作。但是,Posix 还提供了一个接口,让您可以发现当前 "controlling terminal" 的路径名,重要的是让您知道是否没有适合您的进程的路径名。有关详细信息和使用示例,请参阅 man ctermid。
我不明白为什么 getch() 函数 returns 如果我有一个应用程序,它总是出错 以这种方式设置(剥离到骨头):
static char data[DATA_SIZE]; // Very big - covers all input for sure
int main(int argn, char ** argv)
{
// Slurp the file in
int length = read(0, &data[0], DATA_SIZE);
if (length == 0)
{
fprintf(stderr, "Nothing to read\n");
return 0;
}
initscr();
cbreak();
refresh();
WINDOW * woutput = newwin(LINES - 1, COLS, 0, 0);
WINDOW * winput = newwin(1, COLS, LINES - 1, 0);
wattron(winput, A_REVERSE);
keypad(winput, TRUE);
//print the data buffer into a window
int c;
while ((c = wgetch(winput)) != 'q')
{
}
}
我运行是这样申请的:
./application < path/to/file
但是wgetch的结果总是'ERR'
。
由于您已读取 stdin
直到文件末尾,因此 wgetch
在尝试读取时将立即接收到文件末尾。但是无论如何,您都不希望 ncurses 使用重定向的 stdin
;你想让它使用终端。
这样做的一种方法是在调用 initscr
:
stdin
作为终端
#include <stdio.h>
#include <ncurses.h>
int main(int argn, char ** argv)
{
// Just discard all of stdin for a minimal example
while (fgetc(stdin) != EOF) { }
// See note
if (!freopen("/dev/tty", "r", stdin)) {
perror("/dev/tty");
exit(1);
}
initscr();
cbreak();
refresh();
WINDOW * woutput = newwin(LINES - 1, COLS, 0, 0);
WINDOW * winput = newwin(1, COLS, LINES - 1, 0);
wattron(winput, A_REVERSE);
keypad(winput, TRUE);
// Echo input into full screen
int c;
while ((c = wgetch(winput)) != 'q') { wechochar(woutput, c); }
endwin();
return 0;
}
如果您发现 freopen
难以遵循,您可以将它和以下对 initscr
的调用替换为
FILE* tty = fopen("/dev/tty", "r");
if (!tty) { perror("/dev/tty"); exit(1); }
if (!newterm(NULL, stdout, tty) {
fprintf(stderr, "%s\n", "Unable to initialise ncurses");
exit(1);
}
注:
在上面的代码中,我只是使用 /dev/tty
作为控制台的名称,它可能会在任何适度 Posix 兼容的系统中工作。但是,Posix 还提供了一个接口,让您可以发现当前 "controlling terminal" 的路径名,重要的是让您知道是否没有适合您的进程的路径名。有关详细信息和使用示例,请参阅 man ctermid。