在Linux系统下进行终端程序开发时,控制光标位置、显示状态是常见需求,不同的光标控制场景对应不同的头文件,开发者需要根据实际需求选择合适的头文件来实现功能。

基础终端光标控制:termios.h
如果只需要实现简单的光标隐藏、显示以及基于终端原生能力的光标移动,termios.h是最常用的头文件。它提供了对终端I/O属性的控制能力,通过修改终端的属性可以调整光标的显示状态。
使用termios.h控制光标的核心思路是获取当前终端属性,修改属性中的光标显示相关标志,再将修改后的属性设置回终端。下面是一个隐藏和显示光标的示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
// 隐藏光标函数
void hide_cursor() {
struct termios term;
// 获取当前终端属性
if (tcgetattr(STDIN_FILENO, &term) == -1) {
perror("tcgetattr failed");
return;
}
// 设置光标不可见标志
term.c_lflag &= ~ECHO;
// 将修改后的属性设置回终端
if (tcsetattr(STDIN_FILENO, TCSANOW, &term) == -1) {
perror("tcsetattr failed");
return;
}
// 输出隐藏光标的转义序列
printf(" 33[?25l");
fflush(stdout);
}
// 显示光标函数
void show_cursor() {
struct termios term;
if (tcgetattr(STDIN_FILENO, &term) == -1) {
perror("tcgetattr failed");
return;
}
term.c_lflag |= ECHO;
if (tcsetattr(STDIN_FILENO, TCSANOW, &term) == -1) {
perror("tcsetattr failed");
return;
}
printf(" 33[?25h");
fflush(stdout);
}
int main() {
printf("光标将在3秒后隐藏n");
sleep(3);
hide_cursor();
printf("光标已隐藏,3秒后恢复n");
sleep(3);
show_cursor();
printf("光标已恢复n");
return 0;
}
复杂光标控制:ncurses库头文件
如果需要实现更复杂的功能,比如精确控制光标移动到指定坐标、获取光标当前位置、结合键盘输入做交互式光标操作,就需要使用ncurses库,对应的头文件是ncurses.h(部分系统也叫curses.h)。
ncurses库封装了终端的底层操作,提供了更友好、更强大的光标控制接口,不需要开发者手动拼接转义序列。使用前需要先安装ncurses库,在Ubuntu系统下可以通过sudo apt install libncurses5-dev libncursesw5-dev命令安装。
下面是一个使用ncurses.h控制光标移动的示例:
#include <ncurses.h>
int main() {
// 初始化ncurses环境
initscr();
// 不回显输入的字符
noecho();
// 隐藏光标
curs_set(0);
// 移动光标到(5,10)位置,行和列都是从0开始计数
move(5, 10);
printw("光标移动到这里了");
refresh();
// 等待用户输入任意字符后退出
getch();
// 恢复光标显示
curs_set(1);
// 结束ncurses环境
endwin();
return 0;
}
两种方案的对比
可以将两种光标控制方案的特点整理成表格,方便开发者选择:
| 对比项 | termios.h | ncurses.h |
|---|---|---|
| 依赖情况 | 系统原生头文件,无需额外安装库 | 需要安装ncurses第三方库 |
| 功能丰富度 | 仅支持基础的光标显示隐藏,复杂移动需要手动拼接转义序列 | 支持光标移动、位置获取、样式调整等丰富功能 |
| 使用难度 | 需要了解终端属性和转义序列,使用门槛较高 | 接口封装完善,使用简单 |
| 适用场景 | 仅需简单光标显示控制的轻量程序 | 需要复杂终端交互、光标操作的中大型程序 |
注意事项
- 使用
termios.h修改终端属性后,程序退出前最好恢复原有属性,避免影响后续终端使用。 - ncurses库初始化后会接管终端的输入输出,普通
printf函数可能无法正常输出内容,需要使用ncurses提供的printw等函数。 - 不同终端对转义序列的支持可能存在差异,使用
termios.h拼接转义序列时如果出现兼容性问题,建议切换到ncurses方案。