使用 ncurses 在你的 Linux 屏幕上定位文本
ncurses 终端

> 
> 使用 ncurses 在 Linux 屏幕上的特定位置放置文本，可以带来更友好的用户界面体验。
> 
> 
> 


![](/data/attachment/album/202109/06/085908qrdrrv5dru6pcucr.jpg "Person using a laptop")


大多数的 Linux 实用程序仅仅只在屏幕的底部滚动文本。如果你想在屏幕中放置你的文本，例如一个游戏或者一个数据展示，你可以试试 ncurses。


curses 是一个旧的 Unix 库，它可以在文本终端界面控制光标。curses 的名称就来自于术语 “<ruby> 光标控制 <rt>  cursor control </rt></ruby>”。多年以后，其他人编写了新的 curses 版本用来添加新的功能，新版本被叫做 “new curses” 或者 “ncurses”。你可以在每个流行的 Linux 发行版中找到 ncurses。尽管默认情况下可能未安装开发库、头文件和文档。例如，在 Fedora 上，你需要使用以下命令安装 `ncurses-devel` 包：



```
$ sudo dnf install ncurses-devel

```

### 在程序中使用 ncurses


要在屏幕上直接寻址，你首先需要初始化 `ncurses` 库。大部分程序会通过以下三行来做到这一点：


* `initscr()`：初始化窗口对象和 ncurses 代码，返回代表整个屏幕的窗口对象
* `cbreak()`：禁用缓冲并使键入的输入立即可用
* `noecho()`：关闭回显，因此用户输入不会显示在屏幕上


这些函数定义在 `curses.h` 头文件中，你需要在你的程序中通过以下方式将其包含进来：



```
#include <curses.h>

```

初始化终端后，你可以自由使用任何 ncurses 函数，我们将在示例程序中探讨其中的一些函数。


当你使用完 ncurses 并想返回到常规终端模式下时，使用 `endwin()` 重置一切。此命令可以重置任何屏幕颜色，将光标移动到屏幕的左下角，并使光标可见。通常在退出程序之前执行此操作。


### 在屏幕上寻址


关于 ncurses 首先需要知道的是屏幕的坐标分为行和列，左上角的是 `0,0` 点。ncurses 定义了两个全局变量来帮助你识别屏幕：`LINES` 是屏幕的行数，`COLS` 是屏幕的列数。屏幕右下角的位置是 `LINES-1,COLS-1`。


例如，如果你想要移动光标到第 10 行和第 30 列，你可以使用 `move()` 函数，移动到此坐标：



```
move(10, 30);

```

之后显示的任何文本都将从屏幕的该位置开始。要显示单个字符，请对单个字符使用 `addch(c)` 函数。要显示字符串，将对字符串使用 `addstr(s)` 函数。对于类似于 `printf` 的格式化输出，请使用带有常用选项的 `printw(fmt, ...)`。


移动到屏幕指定位置和显示文本是一件很常见的事情，ncurses 提供了同时执行这两项操作的快捷方式。`mvaddch(row, col, c)` 函数将在屏幕第 `row` 行，第 `col` 列的位置显示一个字符。而 `mvaddstr(row, col, s)` 函数将在屏幕第 `row` 行，第 `col` 列的位置显示一个字符串。举个更直接的例子，在程序中使用 `mvaddstr(10, 30, "Welcome to ncurses");` 函数将从屏幕的第 `10` 行和第 `30` 列开始显示文本 `Welcome to ncurses`。使用 `mvaddch(0, 0, '+')` 函数将在屏幕的左上角第 `0` 行和第 `0` 列处显示一个加号（`+`）。


在终端屏幕上绘制文本会对某些系统产生性能影响，尤其是在较旧的硬件终端上。因此 ncurses 允许你“堆叠”一堆文本以显示在屏幕上，然后使用 `refresh()` 函数使所有这些更改对用户可见。


让我们来看一个将以上所有内容整合在一起的简单示例：



```
#include <curses.h>

int
main()
{
  initscr();
  cbreak();
  noecho();

  mvaddch(0, 0, '+');
  mvaddch(LINES - 1, 0, '-');
  mvaddstr(10, 30, "press any key to quit");
  refresh();

  getch();

  endwin();
}

```

程序的开始初始化了一个终端窗口，然后在屏幕的左上角打印了一个加号，在左下角打印了一个减号，在第 `10` 行和第 `30` 列打印了 `press any key to quit` 文本。程序通过使用 `getch()` 函数接收了键盘输入的单个字符，接着，使用 `endwin()` 函数在程序完全退出前重置了终端。


`getch()` 是一个很有用的函数，你可以使用它来做很多事情。我经常使用它在我退出程序前用来暂停。与大多数 ncurses 函数一样，还有一个名为 `mvgetch(row, col)` 的 `getch()` 版本，用于在等待字符输入之前移动到屏幕位置的第 `row` 行，第 `col` 列。


### 使用 ncurses 编译


如果你尝试以通常的方式编译该示例程序，例如 `gcc pause.c`，你可能会从链接器中获得大量错误列表。那是因为 GNU C 编译器不会自动链接 `ncurses` 库。相反，你需要使用 `-l ncurses` 命令行选项加载它以进行链接。



```
$ gcc -o pause pause.c -lncurses

```

运行新程序将打印一条简单的 `press any key to quit`消息，该消息差不多位于屏幕中央：


![centered message in a program window](/data/attachment/album/202109/06/085925c09np4z6n54m1g4h.png)


*图 1：程序中居中的 “press any key to quit” 消息。*


### 使用 ncurses 构建更好的程序


探索 `ncurses` 库函数以了解在屏幕上显示文本的其它方法。你可以在 `ncurses` 的手册页中找到所有 `ncurses` 函数的列表。这给出了 ncurses 的一般概述，并提供了不同 `ncurses` 函数的类似表格的列表，并参考了包含完整详细信息的手册页。例如，在 `curs_printw(3X)` 手册页中描述了 `printw`，可以通过以下方式查看：



```
$ man 3x curs_printw

```

更简单点：



```
$ man curs_printw

```

使用 ncurses，你可以创建更多有趣的程序。通过在屏幕上的特定位置打印文本，你可以创建在终端中运行的游戏和高级实用程序。




---


via: <https://opensource.com/article/21/8/ncurses-linux>


作者：[Jim Hall](https://opensource.com/users/jim-hall) 选题：[lujun9972](https://github.com/lujun9972) 译者：[perfiffer](https://github.com/perfiffer) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
Most Linux utilities just scroll text from the bottom of the screen. But what if you wanted to position text on the screen, such as for a game or a data display? That's where **ncurses** comes in.

**curses** is an old Unix library that supports cursor control on a text terminal screen. The name *curses* comes from the term *cursor control*. Years later, others wrote an improved version of **curses** to add new features, called *new curses* or **ncurses**. You can find **ncurses** in every modern Linux distribution, although the development libraries, header files, and documentation may not be installed by default. For example, on Fedora, you will need to install the **ncurses-devel** package with this command:

`$ sudo dnf install ncurses-devel`


## Using ncurses in a program

To directly address the screen, you'll first need to initialize the **ncurses** library. Most programs will do that with these three lines:

- initscr(); Initialize the screen and the
**ncurses**code - cbreak(); Disable buffering and make typed input immediately available
- noecho(); Turn off echo, so user input is not displayed to the screen

These functions are defined in the **curses.h** header file, which you'll need to include in your program with:

`#include <curses.h>`


After initializing the terminal, you're free to use any of the **ncurses** functions, some of which we'll explore in a sample program.

When you're done with **ncurses** and want to go back to regular terminal mode, use **endwin();** to reset everything. This command resets any screen colors, moves the cursor to the lower-left of the screen, and makes the cursor visible. You usually do this right before exiting the program.

## Addressing the screen

The first thing to know about **ncurses** is that screen coordinates are *row,col*, and start in the upper-left at 0,0. **ncurses** defines two global variables to help you identify the screen size: LINES is the number of lines on the screen, and COLS is the number of columns. The bottom-right position is LINES-1,COLS-1.

For example, if you wanted to move the cursor to line 10 and column 30, you could use the move function with those coordinates:

`move(10, 30);`



Any text you display after that will start at that screen location. To display a single character, use the **addch(c)** function with a single character. To display a string, use **addstr(s)** with your string. For formatted output that's similar to **printf**, use **printw(fmt, …)** with the usual options.

Moving to a screen location and displaying text is such a common thing that **ncurses** provides a shortcut to do both at once. The **mvaddch(row, col, c)** function will display a character at screen location *row,col*. And the **mvaddstr(row, col, s)** function will display a string at that location. For a more direct example, using **mvaddstr(10, 30, "Welcome to ncurses");** in a program will display the text "Welcome to ncurses" starting at row 10 and column 30. And the line **mvaddch(0, 0, '+');** will display a single plus sign in the upper-left corner at row 0 and column 0.

Drawing text to the terminal screen can have a performance impact on certain systems, especially on older hardware terminals. So **ncurses** lets you "stack up" a bunch of text to display to the screen, then use the **refresh()** function to make all of those changes visible to the user.

Let's look at a simple example that pulls everything together:

```
#include <curses.h>
int
main()
{
initscr();
cbreak();
noecho();
mvaddch(0, 0, '+');
mvaddch(LINES - 1, 0, '-');
mvaddstr(10, 30, "press any key to quit");
refresh();
getch();
endwin();
}
```


The program starts by initializing the terminal, then prints a plus sign in the upper-left corner, a minus in the lower-left corner, and the text "press any key to quit" at row 10 and column 30. The program gets a single character from the keyboard using the getch() function, then uses **endwin()** to reset the terminal before the program exits completely.

**getch()** is a useful function that you could use for many things. I often use it as a way to pause before I quit the program. And as with most **ncurses** functions, there's also a version of **getch()** called **mvgetch(row, col)** to move to screen position *row,col* before waiting for a character.

## Compiling with ncurses

If you tried to compile that sample program in the usual way, such as `gcc pause.c`

, you'll probably get a huge list of errors from the linker. That's because the **ncurses** library is not linked automatically by the GNU C Compiler. Instead, you'll need to load it for linking using the `-l ncurses`

command-line option.

`$ gcc -o pause pause.c -lncurses`


Running the new program will print a simple "press any key to quit" message that's more or less centered on the screen:

![centered message in a program window](https://opensource.com/sites/default/files/press-key_0.png)

Figure 1: A centered "press any key to quit" message in a program.

## Building better programs with ncurses

Explore the **ncurses** library functions to learn about other ways to display text to the screen. You can find a list of all **ncurses** functions in the man ncurses manual page. This gives a general overview of **ncurses** and provides a table-like list of the different **ncurses** functions, with a reference to the manual page that has full details. For example, **printw** is described in the *curs_printw(3X)* manual page, which you can view with:

`$ man 3x curs_printw`


or just:

`$ man curs_printw`


With **ncurses**, you can create more interesting programs. By printing text at specific locations on the screen, you can create games and advanced utilities to run in the terminal.

## Comments are closed.