1

我正在制作一个小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");
}

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

为什么?

4

1 回答 1

8

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

于 2017-08-22T08:02:34.330 回答