前言

因为Mac上面一些windows做游戏的第三方库用不了,比如curses.h,还有那个EasyX,烦死了.被迫学习一个新Ncurses库.而这个库配置在Mac上我完全不会,而且用Xcode非常难受全英文,太难受了,受不了,而且好不容易设置好other flag 啥的还是寄的,所以Xcode就是垃圾傻逼软件.,在Clion上也不会配置.经过几天的学习,调试,配置.打算将我弄好的经验分享一下.顺便记录📝一下关于Ncurses库的学习.好了,废话不多说,我们开始吧!


安装

Mac貌似默认就有这个库.不太清楚

不过为了完整性,我们还是安装一下.

1
brew install ncurses

Linux下的命令是:

1
sudo apt-get install libncurses5-dev

配置

编辑CMakeLists.txt文件.例如你的项目名为test,在末尾这样改写.cmakelists文件我现在都还搞啥不懂,所以是改写了.

1
2
3
4
5
find_package(Curses REQUIRED)
include_directories(${CURSES_INCLUDE_DIR})

add_executable(test test.c)
target_link_libraries(test ${CURSES_LIBRARY})

配置完,稍微介绍一下.Ncurses是什么?

介绍

Ncurses是一个能提供功能键定义(快捷键),屏幕绘制以及基于文本终端的图形互动功能的动态库。

例子

举个C语言的例子叭.先随手写一个简单的例子.文件名为test.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <ncurses.h>
#include <stdlib.h>
#include <string.h>

int main(void){
initscr();
raw();
noecho();
curs_set(0);

char* c = "My First Window";

mvprintw(LINES/2,(COLS-strlen(c))/2,c);
printw("\nHello World!");
refresh();

getch();
endwin();

return EXIT_SUCCESS;
}

编译

1
gcc test.c -o test -lncurses

运行

1
./test

如动图所示.

2022-05-01 17.28.35

代码解释

代码 解释
initscr(); 初始化curses窗口,进入NCURSES模式
raw(); 这个函数会阻止字符缓冲,令程序即时处理键盘输入
一些终端命令(中断[Ctrl-c],挂起[Ctrl-z])也会被交给程序处理
noecho(); 屏蔽输入字符显示,键盘输入的字符将不被显示
curs_set(0); 调用会屏蔽掉物理指针
mvprintw(LINES/2,(COLS-strlen(c))/2,c); 输出字符串,三个参数分别为y位置,x位置和字符指针
printw(); 和printf()一样的具有格式化输出的一类函数
refresh(); 刷新屏幕
getch(); 读取键盘输入
endwin(); 关闭窗口,退出NCURSES模式

用法

略.略略略~

参考:官方手册

杂记

以下内容截取互联网.

关于initscr() 函数
initscr()函数将终端屏幕初始化为curses模式。它用来清除屏幕上所有的字符,并等待下一步处理。
所以在调用其它的 curses 函数前,要先调用initscr()函数初始化屏幕。
这个函数初始化了curses系统并且为当前屏幕(也就是“stdscr”)和相关的数据结构分配内存。
在以前的计算机上曾经出现过一个极端的例子:因为系统中的可用内存太小,以至于initscr()
函数无法分配足够的内存给相关的数据结构,从而导致curses 系统初始化失败

关于refresh() 函数
在我们使用printw函数打印“Hello World!”时,实际上这个消息打印到了一个叫作“stdscr”的虚拟窗口上.
没有被直接输出到屏幕上。printw()函数的作用是不断将一些显示标记和相关的数据结构写在虚拟显示器上,
并将这些数据写入 stdscr 的缓冲区内。为了显示这些缓冲区中的数据我们必须使用 refresh()函数告诉curses系统将缓冲区的内容输出到屏幕上。
通过这种机制程序员能够不断在虚拟屏幕上写数据。然后调用refresh()函数让输出的操作看起来是一次完成的。
因为refresh()函数只核查窗口和数据中变动的部分,这种富有弹性的设计提供了一个高效的反馈机制。
但是这有时很打击初学者的积极性。因为对于初学者来说忘记在输出后调用refresh()函数是很恼人的错误。
不过不用担心,很多人都会犯这样的错误。

关于endwin()函数
最后,别忘了退出curses 模式。否则,在程序结束后你的终端可能会运转得不正常。endwin()函数释放了curses子系统和相关数据结构占用的内存,
使你能够正常返回控制台模式。这个函数必须是在你完成所有的curses 操作以后才可以调用。
(译者注:如果你在endwin()函数后再调用其它的curses 的函数。很显然,那些语句不会执行。)
说到这里,顺便提醒一下。如果你的程序不能正常地显示东西了。
请务必看看initscr()函数和endwin()函数是不是在不该被调用的地方调用了。