clrscr()不工作,getch()工作.为什么?

Edu*_*era 1 c gcc conio

我正在制作一个小C程序,要求输入密钥并在switch语句中执行一些代码.

#include <stdio.h>
#include <conio.h>

int main(int argc, char const *argv[]){
    /* code */
    printf("Hello, press a, b or c to continue");
    char key = getch();
    switch (key){
    case  'a':
        clrscr();
        //some code
        break;
    case  'b':
        //many lines of code
        break;
    case  'c':
        clrscr();
        //many lines of code
        break;
    default:
        printf("Ok saliendo\n");
        break;
    }
    printf("bye");
}
Run Code Online (Sandbox Code Playgroud)

getch()工作正常,但clrscr()不是,即使我包括在内<conio.h>.

为什么?

小智 6

conio.h 死了!

一些背景:conio.h定义曾经创建的API来控制IBM PC的(text!)屏幕.它最初只是MS-DOS函数的包装器,因此您不必编写自己的程序集来创建它int 21h来调用它们.确切的API conio.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
}
Run Code Online (Sandbox Code Playgroud)

您可以使用gcc编译它,例如ncurses:

gcc -std=c11 -Wall -Wextra -pedantic -ocursestest cursestest.c -lncurses
Run Code Online (Sandbox Code Playgroud)

或者pdcurses:

gcc -std=c11 -Wall -Wextra -pedantic -ocursestest cursestest.c -lpdcurses
Run Code Online (Sandbox Code Playgroud)

要了解更多信息curses,我推荐NCURSES Programming HOWTO.