C语言中的ncurses简介

The ncurses library provides a range of functionalities for writing console applications which go beyond simply printing text, but without the complexity of writing a full GUI application. To me the most useful things ncurses provides is moving the cursor (and therefore print position) around the console, and printing with various text and background colours.

ncurses库提供了用于编写控制台应用程序的一系列功能,这些功能不仅可以简单地打印文本,还可以编写完整的GUI应用程序。 对我来说,ncurses提供的最有用的功能是在控制台上移动光标(并因此移动打印位置),并使用各种文本和背景色进行打印。

In this post I will introduce those two abilities but ncurses can do a lot more. If you want to look into the topic further I recommend Dan Gookin’s book on the subject.

在这篇文章中,我将介绍这两种功能,但是ncurses可以做更多的事情。 如果您想进一步研究该主题,我建议您选择Dan Gookin关于该主题的书

安装ncurses (Installing ncurses)

ncurses is a Posix library and can be used with Linux, OS/X or, if you use Windows, with Cygwin. There are various ways of actually installing the library so I recommend you search for “installing ncurses on . . .” to find the best way for your particular OS. Once installed you can just #include the header file and you are ready to go.

ncurses是Posix库,可以与Linux,OS / X或(如果您使用Windows)与Cygwin一起使用。 有多种实际安装库的方法,因此我建议您搜索“在上安装ncurses”。 。 。” 找到适合您特定操作系统的最佳方法。 安装完成后,您只需#include头文件就可以了。

该项目 (The Project)

For this project I will write three simple functions to demonstrate the following features of ncurses.

对于这个项目,我将编写三个简单的函数来演示ncurses的以下功能。

  • Printing characters, strings and numbers

    打印字符,字符串和数字
  • Moving around the terminal

    在终端周围移动
  • Printing in colour

    彩色印刷

Create a new folder and within it create a single empty file called ncursesdemo.c. You can grab the source code from Github if you prefer.

创建一个新文件夹,并在其中创建一个名为ncursesdemo.c的空文件。 如果愿意,可以从Github中获取源代码。

This is the first part of the source code.

这是源代码的第一部分。

#include<ncurses.h>
#include<stdlib.h>


//--------------------------------------------------------
// FUNCTION PROTOTYPES
//--------------------------------------------------------
void printing();
void moving_and_sleeping();
void colouring();


//--------------------------------------------------------
// FUNCTION main
//--------------------------------------------------------
int main(void)
{
    initscr();


    addstr("-----------------\n| codedrome.com |\n| ncurses Demo  |\n-----------------\n\n");
    refresh();


    //printing();


    //moving_and_sleeping();


    //colouring();


    addstr("\npress any key to exit...");
    refresh();


    getch();


    endwin();


    return EXIT_SUCCESS;
}

The first line in main is initscr(); which starts ncurses. The next line just writes a heading, but note that it uses addstr, one of a few ncurses functions for printing. ncurses actually outputs to a buffer so to flush the buffer to the screen we then need to call refresh.

main的第一行是initscr(); 这开始ncurses 。 下一行只是写一个标题,但请注意,它使用了addstr ,这是一些用于打印的ncurses函数之一。 ncurses实际上输出到缓冲区,因此要将缓冲区刷新到屏幕,然后需要调用refresh

Leave the three function calls commented out for the moment, after which there is a message to hit any key and a call to getch to pick up a key press. Without this the program would terminate immediately and we probably wouldn’t see a thing!

暂时将三个函数的调用注释掉,之后会出现一条消息,提示您按下任意键,并调用getch来获取按键。 没有此程序,程序将立即终止,我们可能看不到任何东西!

Finally comes the all-important endwin to end ncurses before the program exits.

最后是所有重要的endwin到结束的ncurses在程序退出之前。

The program doesn’t do much so far, just displays a couple of bits of text and waits for you to bash the keyboard. However, let’s compile and run it anyway just to ensure ncurses is working properly. You’ll need to include -lncurses in the compiler command to link in the ncurses library.

该程序到目前为止并没有做太多事情,仅显示了几段文字并等待您重击键盘。 但是,让我们编译并运行它只是为了确保ncurses正常工作。 您需要在编译器命令中包含-Incurses才能链接到ncurses库。

gcc ncursesdemo.c -std=c99 -lncurses -o ncursesdemo ./ncursesdemo

g cc ncursesdemo.c -std=c99 -lncurses -o ncursesdemo ./ncursesdemo

Image for post

Not very impressive so far as we haven’t done anything you can’t do more easily without ncurses. But before we get to the more interesting stuff let’s look at three functions for printing in ncurses.

就我们尚未做的任何事情而言,并不是令人印象深刻的,如果没有ncurses的话,您会更容易做。 但是在开始更有趣的事情之前,让我们看一下ncurses中的三个打印功能。

//--------------------------------------------------------
// FUNCTION printing
//--------------------------------------------------------
void printing()
{
    addstr("This was printed using addstr\n\n");
    refresh();


    addstr("The following letter was printed using addch:- ");
    addch('a');
    refresh();


    printw("\n\nThese numbers were printed using printw\n%d\n%f\n", 123, 456.789);
    refresh();
}

The three functions are

这三个功能是

  • addstr — prints the specified string

    addstr —打印指定的字符串
  • addch — prints a single char

    addch —打印单个字符
  • printw — the ncurses equivalent of printf

    printw — ncurses等效于printf

These work in the same way as the stdio.h puts, putchar and printf except that you need to call refresh after to copy from the buffer to the screen.

它们的工作方式与stdio.h putsputcharprintf相同,除了在从缓冲区复制到屏幕之后需要调用refresh之外。

Uncomment printing(); in main, then compile and run again: you should see this.

取消注释print printing();main ,然后编译并再次运行:您应该看到此内容。

Image for post

Now for the moving_and_sleeping function.

现在使用moving_and_sleeping函数。

//--------------------------------------------------------
// FUNCTION moving_and_sleeping
//--------------------------------------------------------
void moving_and_sleeping()
{
    int row = 5;
    int col = 0;


    curs_set(0);


    for(char c = 65; c <= 90; c++)
    {
        move(row++, col++);
        addch(c);
        refresh();
        napms(100);
    }


    row = 5;
    col = 3;


    for(char c = 97; c <= 122; c++)
    {
        mvaddch(row++, col++, c);
        refresh();
        napms(100);
    }


    curs_set(1);


    addch('\n');
}

This prints the alphabet in upper and lower case, moving one space down and across for each letter. The row and column variables are initialised to 5 (to allow for the heading) and 0, and the ncurses curs_set function is used to hide the cursor.

这将以大写和小写字母打印,每个字母向下和向下移动一个空格。 行和列变量被初始化为5(允许标题)和0,并且ncurses curs_set函数用于隐藏光标。

The for loop iterates the upper case letters, moving to the current position with move, printing the character with addch, calling refresh and then using the napms (“nap for milliseconds”) function to pause for a tenth of a second.

for循环迭代大写字母,使用move当前位置,使用addch打印字符,调用refresh ,然后使用napms (“小睡毫秒”)功能暂停十分之一秒。

Moving and then printing is so common that the three printing functions shown in the printing function have equivalents that move and print in one function call. They have the same names prefixed with mv, and I have used mvaddch for the second loop which prints lower case letters.

移动然后进行打印非常普遍,以至于打印功能中显示的三个打印功能具有在一个函数调用中进行移动和打印的等效功能。 它们具有以mv开头的相同名称,并且我在第二个循环中使用了mvaddch,该循环显示小写字母。

Finally, don’t forget to show the cursor again. Uncomment moving_and_sleeping, then compile and run.

最后,不要忘记再次显示光标。 取消注释moving_and_sleeping ,然后编译并运行。

Image for post

This is the output after the program has run, but what you don’t see here is that each character appeared one at a time with a tenth of a second delay.

这是程序运行后的输出,但是您在这里看不到的是每个字符每次出现一个字符,延迟十分之一秒。

Now we get to the last part of the program, printing in Glorious Technicolor.

现在我们进入程序的最后部分,以Glorious Technicolor打印。

//--------------------------------------------------------
// FUNCTION colouring
//--------------------------------------------------------
void colouring()
{
    if(has_colors())
    {
        if(start_color() == OK)
        {
            init_pair(1, COLOR_YELLOW, COLOR_RED);
            init_pair(2, COLOR_GREEN, COLOR_GREEN);
            init_pair(3, COLOR_MAGENTA, COLOR_CYAN);


            attrset(COLOR_PAIR(1));
            addstr("Yellow and red\n\n");
            refresh();
            attroff(COLOR_PAIR(1));


            attrset(COLOR_PAIR(2) | A_BOLD);
            addstr("Green and green A_BOLD\n\n");
            refresh();
            attroff(COLOR_PAIR(2));
            attroff(A_BOLD);


            attrset(COLOR_PAIR(3));
            addstr("Magenta and cyan\n");
            refresh();
            attroff(COLOR_PAIR(3));
        }
        else
        {
            addstr("Cannot start colours\n");
            refresh();
        }
    }
    else
    {
        addstr("Not colour capable\n");
        refresh();
    }
}

Not all terminals can print in colour so first we need to check using the has_colors function. If so we then need to call the start_color(). Unlike has_colors this returns OK rather than true so we need to check for that.

并非所有终端都可以彩色打印,因此首先我们需要使用has_colors函数进行检查。 如果是这样,那么我们需要调用start_color() 。 与has_colors不同,此方法返回OK而不是true,因此我们需要进行检查。

(In this function if colour is not available a message is printed and the function ends. For production code it might be better to provide a non-coloured fallback.)

(在此功能中,如果颜色不可用,则会打印一条消息,然后该功能结束。对于生产代码,最好提供不带颜色的后备。)

Assuming you have 8 colours available then there are 8 * 8 = 64 possible combinations or pairs which can be used for backgrounds and foregrounds. Before using a pair it has to be set using the init_pair function which takes a number between 1 and 64 (not 0 to 63), the foreground colour and the background colour. Here I have set three pairs — no, the one with both set to green isn’t a mistake!

假设您有8种颜色,则有8 * 8 = 64种可能的组合或对,可用于背景和前景。 在使用一对之前,必须使用init_pair函数进行设置,该函数采用1到64(而不是0到63)之间的数字,前景色和背景色。 在这里,我设置了三对-不,两个都设置为绿色的对没有错!

This is a full list of ncurses colour constants:

这是ncurses颜色常量的完整列表:

  • COLOR_BLACK

    COLOR_BLACK
  • COLOR_RED

    红色
  • COLOR_GREEN

    COLOR_GREEN
  • COLOR_YELLOW

    COLOR_YELLOW
  • COLOR_BLUE

    COLOR_BLUE
  • COLOR_MAGENTA

    COLOR_MAGENTA
  • COLOR_CYAN

    COLOR_CYAN
  • COLOR_WHITE

    白颜色

Now that we have a few colour pairs we can use them to print with. Firstly call attrset to set the printing attributes to the required pair, then addstr plus refresh. The attribute can then be “switched off” with attroff. In the second output I have or’ed the colour pair with A_BOLD which makes the foreground brighter; this is why we can use the same colour constant for both background and foreground. Finally, just to make the screen more garish than it already is, I have printed a bit more text, this time with a tasteful magenta-on-cyan scheme.

现在我们有了一些颜色对,我们可以使用它们来进行打印。 首先调用attrset将打印属性设置为所需的对,然后添加addstrrefresh 。 然后可以使用attroff来“关闭” attroff 。 在第二个输出中,我用A_BOLD了颜色对,以使前景更明亮。 这就是为什么我们可以为背景和前景使用相同的颜色常量。 最后,只是为了使屏幕比以前更华丽,我打印了更多的文字,这次使用了品红色的洋红色/青色方案。

Uncomment colouring(); in main and compile/run again. You should see something like this.

取消注释colouring();main ,然后再次编译/运行。 您应该会看到类似这样的内容。

Image for post

This has been a very quick introduction to what I feel are the most useful features of ncurses but as I mentioned above the library is much more comprehensive than this and deserves further investigation.

这是对ncurses最有用的功能的快速介绍,但是正如我在上面提到的,该库比这更全面,值得进一步研究。

翻译自: https://medium.com/programming-in-c/an-introduction-to-ncurses-in-c-d977efd706f8

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值