1

I'm making a small C program that asks for a key and executes some code in a switch statement.

#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() is working properly, but clrscr() is not, even if I included <conio.h>.

Why?

KeLiuyue
  • 8,149
  • 4
  • 25
  • 42

2 Answers2

9

conio.h is dead!

Some background: conio.h defines an API that was once created to control the (text!) screen of an IBM PC. It was originally just a wrapper around MS-DOS functions, so you didn't have to write your own assembly creating an int 21h to call them. The exact API of conio.h was never standardized and varies from implementation to implementation.

I assume you're using a compiler targeting Windows, these typically still provide some variation of conio.h. But as you can see, there's no guarantee what's really available and works as you would expect.

Nowadays, you'd even have to ask what is a screen? The content of your console window? But what if your controlling terminal is e.g. a remote shell (telnet, ssh, ...)? And even different console window implementations will differ in features and how you control them. C only knows input and output streams, they will work with any kind of terminal / console because they don't know anything about a screen, just input and output of characters.

For actually controlling the "screen", Windows provides the Console API, you could use that directly, but then your program is "hard-wired" to Windows only. Most other consoles / terminals understand some sort of escape codes, often the ANSI escape codes. Windows starting with Windows 10 has optional support for them as well. But there's a wide variety of terminals understanding different codes (and different subsets of them), so using them directly isn't a good idea either.


Nowadays, the de facto standard for controlling a terminal/console is the Curses API which has its roots in BSD Unix, but implementations exist for a large variety of systems and consoles. Most notably, ncurses is available for many systems, even including Windows, but for Windows, you also have pdcurses. There's even an extended pdcurses for Windows that implements its own console window, so you can use features the native Windows console doesn't have. Of course, you won't need this for just "clearing the screen" and reading some input from the keyboard.

When you use curses, you have to do all console/terminal input and output using curses functions (you can't use stdio functions like printf() for that). Here's a tiny example program:

#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
}

You can compile it e.g. with gcc like this for using ncurses:

gcc -std=c11 -Wall -Wextra -pedantic -ocursestest cursestest.c -lncurses

Or with pdcurses:

gcc -std=c11 -Wall -Wextra -pedantic -ocursestest cursestest.c -lpdcurses

To learn more about curses, I recommend the NCURSES Programming HOWTO.

  • 1
    True that there are some hoops to jump through, such as using only `ncurses` I/O functions, etc. Maybe for "a small C program that asks for a key and executes some code in a switch statement" `ncurses` is a bit much, especially if just printing some newlines would do. +1 – ad absurdum Aug 22 '17 at 08:51
  • 1
    @DavidBowling this of course assumes the *real* program will have some more interesting requirements. If not, I'd just say *dump the screen clearing, you don't need it* :) –  Aug 22 '17 at 08:53
  • 1
    @DavidBowling but then, a simple *input stream* is never well suited for *interactive input*, so it might be worthwile to use `curses` (or, at least, something like `libreadline`) for an interactive console program. –  Aug 22 '17 at 08:55
  • @FelixPalmen `ncurses` will open a new screen in terminal not just work with current terminal windows, and not really clear the screen. Please add some `if` `else` in your code if user enter `c` character, do remove the ncurses screen with [`clear();`](https://www.mkssoftware.com/docs/man3/curs_clear.3.asp) function. – EsmaeelE Aug 22 '17 at 18:15
  • @FelixPalmen and thank you to answer my question, I suggest to expand this in separate topic `How to clear screen in standard, portable, secure way?` in above comment i express add `if` `clear()` to be an candidate answer to original question by Eduardo. – EsmaeelE Aug 22 '17 at 18:24
  • @FelixPalmen And `ncurses` that not do things in current terminal, open an new environment and do `print, clear`, etc on it(i don't know jargons) seems good, not a problem. we can add some output section to show how this work bot on Linux and windows. your link to ncurses on http://tldp.org is good but i want to know is tldp project is deprecated? because last edition on document you link is 2005. is there new update version to that? is there any source to show `ncurses` portability? – EsmaeelE Aug 22 '17 at 18:34
0

Based on my experience I just used #include<windows.h> in the head section with system("cls"); in the part to clear and it works for me. Please try it and let me know. I am using codeblocks IDE.

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77