初识Linux —— 第一个程序(进度条)

初识Linux —— 第一个程序(进度条)

前言

已经学习了linux下基本工具的使用,现在来实践练习一下。

1.回车和换行

Windows下,我们认为回车换行是一个概念;但事实上,换行就是换到下一行的当前位置,而回车是回到当前行的开头位置。

我们之所以会认为回车和换行是一个概念,那是因为在我们使用\n的时候,它做了回车和换行两个操作。

现在来看linux下这样两段代码

#include<stdio.h>intmain(){printf("迟来的grown\n");return0;}
#include<stdio.h>intmain(){printf("迟来的grown\r");return0;}
在这里插入图片描述

可以看到\n\r的不同,但运行结果就不一样,其中\r就是表示回车;

那为什么\r回车就没有显示出来结果呢?

这里就要了解缓冲区这个东西了。

缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。

我们可以大致理解为在输入输出时,并不是一个一个字符来进行的(部分特殊除外),这里是行缓冲区。

行缓冲:当输入和输出时,遇到换行符,才执行真正的I/O操作。这时我们输入的字符就会先存放在缓冲区,当按下回车键才进行实际的I/O操作。典型的就是stdinstdout

行缓冲,输出时要遇到换行符才执行真正的输出;所以\r回车,输出的内容就存放在了缓冲区,在程序结束时才清空缓冲区。

这里看两段代码
#include<stdio.h>intmain(){printf("迟来的grown\n");sleep(3);return0;}
intmain(){printf("迟来的grown");sleep(3);return0;}

这里运行结果:(看到的)

第一段代码先输出了迟来的grown,然后再休眠了3秒第二段代码休眠了3秒,在程序结束时才输出了迟来的grown

这两段代码的差别就是\n,这也证明行缓冲区,遇到换行刷新缓冲区的内容。(在程序结束时,也会刷新缓冲区内容)

看到这里可能有疑问,既然程序结束后也会刷新缓冲区的内容,那为什么使用\r在程序结束后也没有输出结果啊?

这是因为linux中它要输出命令行信息,在程序执行完之后,光标是在行开头的,命令行信息就覆盖了要输出的内容。

那我们能不能进行一些操作来看到要输出的内容呢?

当然是有的,我们可以使用fflush来刷新缓冲区(stdout)的内容。

intmain(){printf("迟来的grown");fflush(stdout);sleep(3);return0;}

以上代码运行结果

输出了迟来的grown,再休眠了3秒,最后程序结束;命令行信息将输出内容覆盖了。

2.倒计时程序

了解了回车换行,现在我们来简单些一个倒计时程序。
#include<stdio.h>intmain(){int count =10;while(count){printf("%-2d\r",count);fflush(stdout); count--;sleep(1);}}

代码如上,这里可能出现的一些问题

输出时只覆盖了第一个数字:使用%2d/%-2d,我们要让数字占两个数字(字符)的位置。程序运行不显示倒计时:使用fflush刷新缓冲区内容。

3.进度条程序

在进行编写第一个linux程序——进度条之前,我们先重温一下makefile

BIN=progress SRC=$(shell ls *.c) OBJ=$(SRC:.c=.o) CC=gcc RM= rm -rf $(BIN):$(OBJ) $(CC) -o $@ $^ %.o:%.c $(CC) -c $< .PHONY: clean: $(RM) $(OBJ) $(BIN) 
首先shell ls *.c,获得当前目录下所有的.c文件,可以使用wildcard *.cSRC:.c=.o,将SRC中所以的.c后缀改为.o$@$^$@是获取依赖文件列表,$^获取目标文件。$<,是将依赖文件列表拿出来逐个执行。

更加详细的make/makefile深入了解Linux —— make和makefile自动化构建工具_linux makeself-ZEEKLOG博客

好现在,我们正式开始写linux下的第一个程序——进度条

先来看一下我们要实现的进度条是什么样的:

进度条程序

在这里插入图片描述

我们想要看到的进度条是,进度一直在增加,百分比一直在上涨,最后的方框内一直在转圈。

那该如何实现呢?

首先先来看一下需要写哪些文件

在这里插入图片描述
这里呢,写了四个文件makefile文件code.c:程序主函数main所在的文件progress.c:进度条程序的代码源文件progress.h:进度条程序的代码头文件

了解了这些,现在来看我们如何实现呢?

这里虽然我们看起来是进度条连续增加的,但是事实上就是一次一次输出的结果。

不知道你是否还记得在实现贪吃蛇小游戏的时候,我们就是一次次输出,来实现蛇的移动;这里也同理,我们依然一次次打印来达到我们预期的效果。

某一时刻进度条的输出

我们先来看某一时刻进度条是如何输出的;

假设现在我们正在下载一个软件,软件大小1024.00MB ,我们当前下载了512.00MB,那如何打印这一时刻的进度条呢?

voidprocess(){double total =1024.00;//下载总量double current =512.00;//当前下载量int rate =(int)(current*100)/total;//进度条百分比,也是要打印`=`的数量constchar* str ="|-/\\";//表示最后方框内旋转的字符,最后一个\\转义字符staticint cnt =0;//表示当前应该那个字符,来转圈char buff[101]={'\0'};int i=0;for(i=0;i<rate;i++){ buff[i]='=';}printf("[%-100s][%d%%][%c]\n",buff,rate,rate[cnt]);}
在这里插入图片描述

可以看到在一时刻的进度条就已经成型了;那我们根据先已经写好的代码,来实现完整的进度条。

进度条实现

我们知道了这一时刻的进度条如何打印,那我们之间让current当前进度累加即可(这就涉及到一个速度问题)。还有一点,最后方框内如何让它转动起来

为了控制速度,我们既可以控制current累加的值,当然也可以控制休眠时间usleep

为了控制方框内转动,我们定义一个静态常量,来决定应该输出哪一个字符。

具体代码如下

#include"progress.h"#include<unistd.h>#include<string.h>#defineNUM101#defineCH'='voidprocess(){char buff[NUM];memset(buff,0,sizeof(buff));constchar* str="|/-\\";int len =strlen(str);int cnt =0;while(cnt<=100){printf("[%-100s][%d%%][%c]\r",buff,cnt,str[cnt%len]);fflush(stdout); buff[cnt]=CH;usleep(10000); cnt++;}printf("\n");}

这里curremt增加量和usleep休眠时间可以自行修改。

对于这个版本,感觉还是差点意思如果我们需要下载内容,大小不一,下载网速也不同,那该如何?

这个进度条我们只有修改这个函数内的数值才能控制进度条的快慢,我们还可以进行修改,通过传参来控制总量。

这里提供修改后的版本,细节就不详细讲解了。

当然这个版本也存在一些不足之处,有待提高。

code.c

#include"progress.h"#definespeed1.0voidDownload(double total){double current=0;while(current<=total){Process(total,current);usleep(6000); current+=speed;}printf("\ndownload %lfMB Done\n",total);}intmain(){//process();Download(1024.00);return0;}

progress.h

#include<stdio.h>#include<unistd.h>voidProcess(double total,double current);

progress.c

voidProcess(double total,double current){char buff[NUM];memset(buff,0,sizeof(buff));constchar* str ="|/-\\";int len =strlen(str);//当前进度int num =(int)(current*100)/total;int i=0;for(i=0;i<num;i++){ buff[i]=CH;}staticint cnt =0; cnt%=len;printf("[%-100s][%d%%][%c]\r",buff,num,str[cnt]); cnt++;fflush(stdout);}

*到这里本篇内容就结束了,希望对你有所帮助。

制作不易,感谢大佬的支持。

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

Read more

NXOpen Python API二次开发环境配置

NXOpen Python API二次开发环境配置

NXOpen Python API二次开发环境配置 前言 最近在工作中遇到一些NX二次开发的工作,有一些深度学习与NX交互的工作内容,尝试使用使用python进行二次开发。在网上搜了几个环境配置的教程,都没有实现代码提示的功能,最近找到生成.pyi文件的方法才实现了代码提示功能,把完整的配置流程给大家分享。 1 安装NX和对应版本的python 1)在NX安装目录下D:\安装目录\NX1946\NXBIN\python找到python37.dll文件,查看文件属性。如安装的是 NX1946,可以查看到对应的python版本是3.7.5。 2)下载对应的python版本安装到将要用于项目开发的文件夹中,直接使用安装环境,避免虚拟环境的各种问题。如直接安装在D:\NXOpenPython中。 2 添加nxopen库 1)在D:\NXOpenPython\python37\Lib\site-packages目录中新建一个nxopen.pth的文件在文件中添加D:\安装目录\NX1946\NXBIN\python。 2)添加UGII目录到系统变量PATH下。 PATH =

By Ne0inhk
教程:将 Python Playwright 脚本打包为独立 Windows EXE (含浏览器内核)

教程:将 Python Playwright 脚本打包为独立 Windows EXE (含浏览器内核)

在开发自动化工具或定制化浏览器时,我们经常使用 Python 的 Playwright 库。但如果要将工具分发给非技术用户,要求对方安装 Python 环境、下载对应版本的浏览器内核是非常痛苦的。 本文介绍一种方案:将 Python 代码、Playwright 依赖库以及 Chromium 浏览器内核全部打包进一个独立的 .exe 文件中,实现真正的“零依赖”运行。 核心挑战 Playwright 默认将浏览器二进制文件下载到用户目录(如 %AppData%)。在打包时,我们需要解决两个核心问题: 1. 构建时包含:如何把浏览器文件“塞”进 exe 里? 2. 运行时定位:打包后的程序运行在临时目录,如何告诉 Playwright 去哪里找浏览器? 解决方案 1. Python 代码适配 (test-01.py)

By Ne0inhk

python-okx实战手册:从零构建加密货币交易系统

python-okx实战手册:从零构建加密货币交易系统 【免费下载链接】python-okx 项目地址: https://gitcode.com/GitHub_Trending/py/python-okx 还在为复杂的加密货币API集成而头疼吗?想用Python快速搭建自己的量化交易系统?今天带你深度解析python-okx库,这个官方推荐的OKX API v5封装工具,让你在5分钟内实现专业级交易功能!🚀 为什么python-okx是量化交易的首选? 在众多加密货币交易API中,python-okx凭什么脱颖而出?让我们通过对比表格来一探究竟: 核心指标python-okx其他第三方库接口完整性100%覆盖REST+WebSocket仅核心功能稳定性表现99.9%连接成功率频繁断连需手动处理开发效率极简API调用需编写大量底层代码 核心优势详解 完整的功能模块覆盖: * 账户管理:okx/Account.py * 现货交易:okx/Trade.py * 衍生品合约:okx/Trade.py * 实时行情:okx/MarketData.py * W

By Ne0inhk
机器学习:数据清洗与预处理 | Python

机器学习:数据清洗与预处理 | Python

个人主页-爱因斯晨 文章专栏-Python学习 文章目录 * 个人主页-爱因斯晨 * 文章专栏-Python学习 * 前言 * 了解数据清洗 * 数据清洗的步骤 * 1. 环境准备与库导入 * 2. 数据加载 * 3. 数据初探与理解 * 4. 缺失值处理 * 5. 重复值处理 * 6. 异常值处理 * 7. 数据类型转换 * 8. 数据标准化 / 归一化(预处理) * 实例实践 * 总结 前言 我们不论在学习机器学习还是数据分析中,都会涉及很多数据。但原数据不可避免有很多杂志,为了确保结果的准确性,我们需要首先进行数据清洗和预处理。 了解数据清洗 数据清洗就像是一场数据的“大扫除”。它是从原始数据中找出并修正那些错误、不完整、重复或不一致的数据。通过数据清洗,能显著提升数据质量,为后续数据分析、挖掘和建模等工作提供准确、可靠、干净的数据基础,从而让基于数据得出的结论更具可信度和价值。 数据清洗的步骤 1. 环境准备与库导入

By Ne0inhk