C语言写一个终端进度条

news/2024/9/24 7:46:53/

C语言写一个终端进度条

这个功能挺简单的,主要有以下两点:

  • 如何获取终端宽度
  • 如何让字符在原地闪烁

如何获取终端宽度

这里用到了设备控制接口函数ioctl(),下面简单的介绍一下这个函数的用法:

ioctl是一个在Unix和类Unix系统中用于设备驱动程序的设备特定操作的系统调用。它的名称代表“输入/输出控制”,但实际上它可以用于任何设备,不仅仅是输入/输出设备。

在C语言中,ioctl函数的原型如下¹:

#include <sys/ioctl.h>
int ioctl(int fd, int cmd, ...);

这里,fd是一个打开的文件描述符,cmd是设备特定的操作命令,后面的可变参数...取决于cmd指定的操作。

ioctl函数执行成功时返回0,失败则返回-1并设置全局变量errno值。可能的错误包括:

  • EBADF: fd不是一个有效的描述符。
  • EFAULT: argp引用了一个无法访问的内存区域。
  • EINVAL: 请求或argp无效。
  • ENOTTY: fd没有与字符特殊设备关联。
  • ENOTTY: 指定的请求不适用于描述符d引用的对象类型。

更详细的内容可以查询man手册或者其他博客!!这个函数还是挺复杂的!

对于判断终端大小的需求,我们有以下的使用方式:

	struct winsize w;ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); // 获取终端大小并且存储到w中int barWidth = w.ws_col - 10; // 减去10是为了放置越界

winsize这个结构体位于termios.h头文件内

// /usr/include/asm-generic/termios.h
Struct winsize 
{unsigned short ws_row;    /* rows, in character */unsigned short ws_col;        /* columns, in characters */unsigned short ws_xpixel;    /* horizontal size, pixels (unused) */unsigned short ws_ypixel;    /* vertical size, pixels (unused) */
}

使用这个结构体记录窗口终端大小。

如何让字符在原地闪烁

要明白这一点,我们首先要知道两个前置知识:

  • printf的输出条件
  • 终端中的光标

printf的输出条件

没错,printf 也有输出条件,如下:

  • 遇到换行符\n
  • 进程终止
  • 遇到fflush函数

单纯的使用printf并不会直接输出到终端上,会先放在缓冲区,只有遇到换行符才会输出!!!

终端中的光标

我们可以通过'\r'来控制缓冲区中的光标,这样,当我们输出进度条之后,光标又会回到进度条最一开始的位置,这样就可以使得进度条看不见了。

如下:

// 光标置于开头
// progressPercent是进程百分比
printf("\r%3d%% [", progressPercent);

整个函数

// 用法,输入进度值(小数)
// 此函数用于输出一次进度条
void printProgress(float progress) {struct winsize w;ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);int barWidth = w.ws_col - 10; // -10 防止越界int progressPercent = (int) (progress * 100.0); // 计算出百分值printf("\r%3d%% [", progressPercent);int pos = barWidth * progress; // 包含隐式类型转换for (int i = 1; i < barWidth; ++i) {if (i < pos) {printf("#");} else {printf(" ");}fflush(stdout); // 输出完所有内容后刷新缓冲区,代码执行到这里才会有一次输出}printf("]"); // 最后补上后面的括号
}

这里再写一个main函数用于测试:

int main() {for (int i = 0; i <= 100; ++i) {printProgress(i / 100.0);sleep(1);}printf("\n");return 0;
}

因为作者在项目开发时使用的是自用的通用头文件,代码中并没有包含头文件,请读者自行添加。

执行效果

vscode执行效果:
执行效果1
ssh客户端执行效果:
执行效果2
读者可以给进度条加以改进,作为下层代码,方便在上层代码上调用(例如文件传输C/S)。

:wq 拜拜~~~~


http://www.ppmy.cn/news/1453999.html

相关文章

音视频开发之旅——实现录音器、音频格式转换器和播放器(PCM文件转换为WAV文件、使用LAME编码MP3文件)(Android)

本文主要讲解的是实现录音器、音频转换器和播放器&#xff0c;在实现过程中需要把PCM文件转换为WAV文件&#xff0c;同时需要使用上一篇文章交叉编译出来的LAME库编码MP3文件。本文基于Android平台&#xff0c;示例代码如下所示&#xff1a; AndroidAudioDemo Android系列&am…

HTTP常见面试题(一)

3.1 HTTP 常见面试题 HTTP基本概念 HTTP 是超文本传输协议&#xff0c;也就是HyperText Transfer Protocol。 HTTP 的名字「超文本协议传输」&#xff0c;它可以拆成三个部分&#xff1a; 超文本 传输 协议 HTTP 是一个用在计算机世界里的协议。它使用计算机能够理解的语…

流畅的Python阅读笔记

五一快乐的时光总是飞快了&#xff0c;不知多久没有拿起键盘写文章了&#xff0c;最近公司有Python的需求&#xff0c;想着复习下Python吧&#xff0c;然后就买了本Python的书籍 书名&#xff1a; 《流畅的Python》 下面是整理的一个阅读笔记&#xff0c;大家自行查阅&#xf…

Docker使用方法

Docker是一种容器化平台&#xff0c;它可以帮助开发人员将应用程序和其依赖项打包成一个独立的、可移植的容器&#xff0c;以便在不同的环境中运行。 以下是使用Docker的基本步骤&#xff1a; 安装Docker&#xff1a;首先&#xff0c;您需要在您的机器上安装Docker。您可以从D…

10G MAC层设计系列-(4)MAC TX模块

一、前言 MAC TX模块就是要将IP层传输过来的数据封装前导码、MAC地址、帧类型以及进行CRC校验&#xff0c;并与CRC值一块组成以太网帧。 二、模块设计 首先对输入的数据进行缓存&#xff0c;原因是在之后要进行封装MAC帧头&#xff0c;所以需要控制数据流的流动 FIFO_DATA_6…

1688详情,搜索,店铺,图搜

简要描述\n根据商品id获取详情数据\n请求URL\nhttp://xxx.xxx.xxx.xxx:xxxx/get_item\n请求方式\nget\n请求Query参数\n参数名 示例值 必选 类型 说明\nitemid 590347769363 是 string 商品id\ntoken admin.api 是 string 权限token\nsales_data 2 是 string 2\nchannel 0 否 s…

13_Qt中的快捷键

Qt Creator的一些快捷操作&#xff1a; 项目管理&#xff1a; Build&#xff1a;以增量方式构建项目。Rebuild&#xff1a;重新构建项目。Clearn&#xff1a;清除项目构建过程中产生的所有中间文件。Run qmake&#xff1a;使用qmake/cmake重新构建项目。会重新执行UIC、MOC、…

Typescript基础语法(四)

模块化 模块化是指将复杂的程序拆解为多个独⽴的⽂件单元&#xff0c;每个⽂件被称为⼀个模块。在 TypeScript 中&#xff0c;默认情况下&#xff0c;每个模块都拥有⾃⼰的作⽤域&#xff0c;这意味着在⼀个模块中声明的任何内容&#xff08;如变量、函数、类等&#xff09;在该…