GNU-ncurses库简介

2023-09-20 22:30:39


前言

ncurses是一个管理应用程序在字符终端显示的函数库。它提供了移动光标,建立窗口,产生颜色,处理鼠标操作等功能。
ncurses提供的是字符用户界面,而非图形用户界面。


一、安装与使用

在Ubuntu下执行如下命令

sudo apt-get install libncurses5-dev

在编译时需要加上-lncurses选项

在运行编译好的二进制文件时也要安装ncurses库

二、ncurses库基本用法

#include <ncurses.h>

int main()
{
    initscr();  // 初始化,进入ncurses模式,创建虚拟屏幕
    printw("hello world");  // 在虚拟屏幕上光标位置打印 hello world
    refresh();  // 将虚拟屏幕上的内容写到显示器上,并刷新
    getchar();  // libc
    endwin();   // 推出ncurses模式
}

2.1 initscr()

将终端屏幕初始化为curses模式,该函数初始化了curses系统并且为当前屏幕(“stdscr”)和相关的数据结构分配内存。

2.2 refresh()

printw函数用于向stdscr虚拟屏幕缓冲区写入数据,refresh函数负责将stdscr缓冲区中的数据显示在屏幕上。refresh只核查窗口和数据中变动的部分。

2.3 endwin()

释放了curses子系统和相关数据结构占用的内存,使得能够正常返回控制台模式,否则程序推出后终端显示会变得异常。

三、初始化

初始化后curses session的模式及功能包括:terminal mode, color mode, mouse mode 等

3.1 raw(), cbreak()

一般而言,终端驱动程序会缓冲用户输入的字符,直到遇到换行符或者回车符后,这些字符才可以被使用。raw和cbreak可以禁止行缓冲(line buffering):row可以处理ctrl+z, ctrl+c等控制字符,将其传送至程序而不产生终端信号;cbreak则不会这样处理.

3.2 echo() noecho()

noecho() 禁止输入的字符出现在屏幕上

3.3 keypad()

为stdscr激活功能键 keypad(stdscr, true)

3.4 int halfdelay(int)

以 0.1 s 为单位等待用户输入,若在规定的时间内没有输入则返回#define ERR -1

#include <unistd.h>
#include <stdio.h>
#include <ncurses.h>

int main()
{
    initscr();   // 开始curses模式
    int ch;
    curs_set(false);  // 关闭光标显示
    raw();  // 禁用输入缓冲
    keypad(stdscr, TRUE);  // 没有它当按下Fn时程序似乎不正常
    noecho();   // 当执行getch函数时关闭键盘回显
    // 向缓冲区stdscr中写数据
    printw("Type any character to seee it in bold\n");
    // 用法同getchar,但又有区别,可尝试换成getchar会怎样
    // curses库中getch与getchar用法相似,但如果用getchar函数会出现的显示上的问题
    // 这个问题有待进一步探究
    ch = getch();  // 如果没有raw()函数必须按下enter时才将字符传给程序
    for (int i = 1; i<=12; ++i) {
    	// 如果没有keypad将不会执行这条语句
        if (ch == KEY_F(i)) {
            printw("F%d Key pressed", i);
            // 如果没有noecho一些控制字符将被打印到屏幕上
            goto conti_exe;
        }
    }
    printw("The pressed key is ");
    attron(A_BOLD);  // 看名知意
    printw("%c", ch);
    attroff(A_BOLD);
    conti_exe:
    refresh();  // 将stdscr的内容显示到屏幕
    getch();    // 等待用户输入
    endwin();  // 结束curses模式

}

四、窗口机制简介

printw(string);  // 在窗口stdscr的当前坐标输出string
refresh();

// w+  指定窗口显示
wprintw(win, string);  // 在win上写string
wrefresh(win);  // 刷新窗口win

// mv+ 在指定位置打印
mvprintw(y, x, string);  在stdscr的(y, x)处写string
mvwprintw(win, y, x, string);  // 在win的(y, x)处写string 

五、输出函数

addch()系列:将单一的字符打印到屏幕上,可以附加字符修饰参数的一类函数
printw()系列:类似printf格式化输出
addstr()系列:打印字符串

addch( ch | A_BOLD | A_UNDERLINE);

attrset(), 不可叠加文本属性
attron(), attroff() 可叠加文本属性

ACS_ 开头的宏可用于绘制一些简单的表格、线条等

vwprintw()和vprintf()相似,用于打印变量表中所对应的变量(没用过)

指定窗口指定位置指定窗口+位置
addchwaddchmvaddchmvwaddch
addstrwaddstrmvaddstrmvwaddstr
printwwprintwmvprintwmvwprintw

getmaxyx

    initscr();
    curs_set(false);
    raw();
    keypad(stdscr, TRUE);
    noecho();
    
    char mesg[] = "Just a string";
    int row, col;
    getmaxyx(stdscr, row, col);
    mvprintw(row/2, (col-strlen(mesg))/2, "%s", mesg);
    mvprintw(row-2, 0, "This screen has %d rows and %d columns\n", row, col);
    printw("Try resizing your window(if possible and then run this prog)");

    refresh();
    getch();
    endwin();

六、输入函数

getch() 系列:读取一个字符
scanw()系列:按照格式化读取输入
getstr() 系列:读取字符串

scanwwscanwmvscanwmvwscanw
    char mesg[] = "Just a string";
    char str[80];
    int row, col;
    getmaxyx(stdscr, row, col);
    mvprintw(LINES/2, (COLS-strlen(mesg))/2, "%s", mesg);
    getstr(str);
    mvprintw(LINES-2, 0, "You ENtered:%s\n", str);

    printw("row:%d, col:%d, LINES:%d", row, col, LINES);

七、输出修饰

#include <unistd.h>
#include <stdio.h>
#include <ncurses.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{

    
//
    int ch, prev;
    FILE *fp;
    int goto_prev = false, y, x; /* sdfg*/
    if (argc != 2)
    {
        printf("error");
        exit(1);
    }
    fp = fopen(argv[1], "r");
    if (fp == NULL)
    {
        perror("Connot open inputfile");
        exit(1);
    }

    initscr();
    curs_set(false);
    raw();
    keypad(stdscr, TRUE);
    noecho();


    prev = EOF;
    while ((ch = fgetc(fp)) != EOF)
    {
        if (prev == '/' && ch == '*')
        {
            attron(A_BOLD);
            goto_prev = true;
        }
        if (goto_prev == true)
        {
            getyx(stdscr, y, x);
            move(y, x -1);
            printw("%c%c", '/', ch);
            ch = 'a';
            goto_prev = false;
        }
        else
        {
            printw("%c", ch);
        }
        refresh();
        if (prev == '*' && ch == '/')
        {
            attroff(A_BOLD);
        }
        prev = ch;
    }
    
    
///
    refresh();
    getch();
    endwin();

}
说明
A_NORMAL普通字符
说明
attrset会覆盖之前的设置
attron会追加
attroff只会关闭特定修饰
standend()等价于attrset(A_NORMAL)
attr_get()获得当前窗口修饰属性设置及背景、文字颜色
需要在设置的修饰之后才能使用
attr_类函数
wattr_类函数
chgat()
wchgat()
mvchgat()
mvwchgat()
    start_color();
    init_pair(1, COLOR_CYAN, COLOR_BLACK);
    printw("A Big string which i didn't care to type fully");
    mvchgat(0, 10, 4, A_BLINK, 1, NULL);
    //  第三个参数表示从光标开始的向后几个字符,-1代表整行, 

八、窗口机制

声明说明
WINDOW * newwin (int,int,int,int);创建窗口结构体
int delwin(WINDOW*);释放窗口资源
int wborder(win, L, R, U, D, 左上, 右上,左下,右下)绘制边框

假象stdscr有个二维数组存储窗口中的内容,newwin是在这个二维数组中划分
在原有的stdscr窗口中创建新的窗口,

#include <unistd.h>
#include <stdio.h>
#include <ncurses.h>
#include <string.h>
#include <stdlib.h>

WINDOW* create_nwin(int h, int w, int y, int x)
{
    WINDOW* local_win;
    local_win = newwin(h, w, y, x);
    // box(local_win, 0, 0);
    wborder(local_win,'*','*','*','*','#','#','#','#');
    wrefresh(local_win);
    return local_win;
}

void del_win(WINDOW* local)
{
    wborder(local,' ',' ',' ',' ',' ',' ',' ',' ');
    wrefresh(local);
    delwin(local);
}

int main(int argc, char* argv[])
{
    initscr();
    curs_set(false);
    raw();
    keypad(stdscr, TRUE);
    noecho();
    
//
    
    WINDOW* myw;
    int w = 10, h = 7, x = (COLS-w)/2, y = (LINES-h)/2;
    int ch;
    printw("Press F1 to exit");
    refresh();
    myw = create_nwin(h, w, y, x);
    while ((ch = getch()) != KEY_F(1))
    {
        switch (ch)
        {
        case KEY_LEFT:
            del_win(myw);
            myw = create_nwin(h, w, y, --x);
            break;
        case KEY_RIGHT:
            del_win(myw);
            myw = create_nwin(h, w, y, ++x);
            break;
        case KEY_UP:
            del_win(myw);
            myw = create_nwin(h, w, --y, x);
            break;
        case KEY_DOWN:
            del_win(myw);
            myw = create_nwin(h, w, ++y, x);
            break;
        
        default:
            break;
        }
    }
    
///
    // getch();
    endwin();

}

总结

更多推荐

Canal实现Mysql数据同步至Redis、Elasticsearch

文章目录1.Canal简介1.1MySQL主备复制原理1.2canal工作原理2.开启MySQLBinlog3.安装Canal3.1下载Canal3.2修改配置文件3.3启动和关闭4.SpringCloud集成Canal4.1Canal数据结构![在这里插入图片描述](https://img-blog.csdnimg.

CGI与FastCGI的区别在哪里,FastCGI的应用场景讲解

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月CSDN上海赛道top4。🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。🎉欢迎👍点赞✍评论⭐收藏文章目录1.CGI和FastCGI1.1CGI1.2FastCGI1.3对比2.Fas

MySQL的高级SQL语句

目录一、高级SQL语句1、select查询表中一个或多个字段的数据2、distinct不显示重复的数据记录3、where有条件查询4、and与or且与或5、in显示在某个范围值内的字段的信息6、between显示两个值范围内的数据记录7、orderby对字段进行排序8、groupby对字段进行分组汇总9、having用

【操作系统】聊聊磁盘IO是如何工作的

磁盘机械磁盘主要是由盘片和读写磁头组成。数据存储在盘片的的环状磁道上,读写数据前需要移动磁头,先找到对应的磁道,然后才可以访问数据。如果数据都在同一磁道上,不需要在进行切换磁道,这就是连续IO,可以获得更好的性能。而随机IO性能就比较差。固态磁盘固态磁盘不需要寻找磁道,所以随机IO和连续IO性能都不错。连续IO的性能其

【Linux】自制shell

本期我们利用之前学过的知识,写一个shell命令行程序目录一、初始代码二、使用户输入的ls指令带有颜色分类三、解决cd指令后用户所在路径不变化问题3.1chdir函数四、关于环境变量的问题一、初始代码#include<stdio.h>#include<unistd.h>#include<stdlib.h>#includ

模块化开发_php中使用redis

redis介绍和安装redis数据库,支持数据持久化,常用与分布式锁,支持事务,持久化,非关心型数据库区别:关系型数据库:硬盘,安全,结构简单,易于理解,浪费空间非关系型数据库:内存,断电丢失数据,读写速度快,内存的速度是硬盘的100倍redis:用于缓存压力,提升网站访问速度三种类型:持久化(将数据保存到硬盘中,再开

02. Springboot集成Flyway

目录1、前言2、什么是Flyway?3、为什么要使用Flyway?4、简单示例4.1、创建SpringBoot工程4.2、添加Flyway依赖4.3、Springboot添加Flyway配置4.4、创建执行SQL脚本4.5、启动测试4.6、Flyway版本管理5、SQL脚本文件命名规则6、使用注意事项1、前言在现代应用

kafka介绍

1.kafka概述消息中间件对比特性ActiveMQRabbitMQRocketMQKafka开发语言javaerlangjavascala单机吞吐量万级万级10万级100万级时效性msusmsms级以内可用性高(主从)高(主从)非常高(分布式)非常高(分布式)功能特性成熟的产品、较全的文档、各种协议支持好并发能力强、

SkyWalking快速上手(二)——架构剖析1

文章目录介绍架构概述一、Agent组件介绍Agent的配置配置参数详解service_namesample_n_per_3_secsnamespacecollector.backend_serviceAgent的工作原理二、Collector组件什么是Collector组件?Collector组件的配置配置Collec

List<HashMap<String,String>>实现自定义字符串排序(key排序、Value排序)

系列文章目录SpringBoot+Vue3实现登录验证码功能Java实现发送邮件(定时自动发送邮件)换个角度使用Redis去解决跨域存取Session问题Redis缓存穿透、击穿、雪崩问题及解决方法SpringCache的使用–快速上手篇更多该系列文章请查看我的主页哦文章目录系列文章目录前言一、根据Key值排序1.1.

【Spring Cloud系列】Feign详解与实战

Feign详解与实战文章目录Feign详解与实战一、概述二、什么是Feign三、Feign特性四、Feign简单使用3.1Feign使用步骤3.2Feign具体使用1.引入依赖2.启动类上添加注解3.编写FeignClient接口五、使用Feign发起http请求5.1Maven导入Feign配置,并集成Jackson

热文推荐