conio.h
死了!
一些背景知识:conio.h
定义了一个 API,它曾经被创建用于控制 IBM PC 的(文本!)屏幕。它最初只是 MS-DOS 函数的包装器,因此您不必编写自己的程序集来创建int 21h
调用它们。的确切 APIconio.h
从未标准化,并且因实现而异。
我假设您使用的是针对 Windows 的编译器,这些通常仍然提供一些conio.h
. 但正如您所看到的,无法保证真正可用并且可以按您期望的那样工作。
如今,你甚至不得不问什么是屏幕?您的控制台窗口的内容?但是,如果您的控制终端是远程 shell(telnet、ssh、...),该怎么办?甚至不同的控制台窗口实现在功能和控制方式上也会有所不同。C 只知道输入和输出流,它们可以与任何类型的终端/控制台一起使用,因为它们对屏幕一无所知,只知道字符的输入和输出。
为了实际控制“屏幕”,Windows 提供了Console API,您可以直接使用它,但是您的程序仅“硬连线”到 Windows。大多数其他控制台/终端理解某种转义码,通常是ANSI 转义码。从 Windows 10 开始的 Windows 也对它们提供可选支持。但是有各种各样的终端可以理解不同的代码(以及它们的不同子集),因此直接使用它们也不是一个好主意。
如今,控制终端/控制台的事实上的标准是Curses API,它起源于 BSD Unix,但存在用于各种系统和控制台的实现。最值得注意的是,ncurses可用于许多系统,甚至包括 Windows,但对于 Windows,您也有pdcurses。甚至还有一个用于 Windows 的扩展 pdcurses,它实现了自己的控制台窗口,因此您可以使用本机 Windows 控制台没有的功能。当然,您不会仅仅为了“清除屏幕”和从键盘读取一些输入而需要它。
当你使用 时curses
,你必须使用函数来完成所有控制台/终端输入和输出curses
(你不能使用stdio
这样的函数printf()
)。这是一个小示例程序:
#include <curses.h>
// don't include `ncurses.h` here, so this program works with
// different curses implementations
#include <ctype.h> // for `isalnum()`
int main(void)
{
initscr(); // initialize curses, this also "clears" the screen
cbreak(); // among other things, disable buffering
noecho(); // disable "echo" of characters from input
addstr("Hello, press a key!\n"); // output a constant string, like puts/fputs
refresh(); // output might be buffered, this forces copy to "screen"
int c;
do
{
c = getch(); // read a single character from keyboard
} while (!isalnum(c)); // ignore any input that's not alphanumeric
printw("You entered '%c'.\n", c); // formatted output, like printf
addstr("press key to exit.\n");
refresh();
c = getch();
endwin(); // exit curses
}
您可以使用 gcc 编译它,例如使用ncurses
:
gcc -std=c11 -Wall -Wextra -pedantic -ocursestest cursestest.c -lncurses
或与pdcurses
:
gcc -std=c11 -Wall -Wextra -pedantic -ocursestest cursestest.c -lpdcurses
要了解更多信息curses
,我推荐NCURSES Programming HOWTO。