嵌入式学习笔记总结Day23----minshell项目总结

今天进行了linux系统高级编程io阶段学习的结尾,完成了一个minshell的小项目。

一、项目介绍

利用Linux中IO接口实现MiniShell,实现常用的shell指令的实现。
项目想要实现需要思考的地方有:
1.如何打印终端命令
2.如何接受终端命令
3.实现对应的命令
要求:采用多文件编程,并实现按时间将输入的指令记录到日志文件中。

二、项目实现

初步思考整个项目的大致流程图如下:
在这里插入图片描述
接下来介绍项目实现中的一些关键部分:

2.1 打印终端提示符

在这里插入图片描述

要实现如上图的终端命令提示符,我们可以发现该提示符主要分为两部分:
1.前面的linux@ubuntu是固定不变的,直接printf输出即可,后面的路径则是一直改变的,这时我们可以通过getcwd函数来实现获取当前的绝对路径:
int Terminal(void)
{char buf[1024] = {0};char *p = NULL;getcwd(buf,sizeof(buf));p = buf;while(*p != '\0')   //主要打印当前的一级路径即可,则可以通过指针分割出我们想要的路径{p++;}while(*p != '/'){p--;}p++;printf("\033[1;31m");   //这里主要采用vt100打印出想要的字符颜色printf("linux@Ubuntu:");printf("\033[0m");printf("\033[1;35m");printf("%s",p);printf("\033[0m");printf("$ ");return 0;
}

实现效果如下:
在这里插入图片描述

2.2用户指令的获取

这里采用fgets获取用户键盘输入的指令

int Gets(char *tmbuff,int maxlen)
{fgets(tmbuff,maxlen,stdin);tmbuff[strlen(tmbuff)-1] = '\0';  //将fgets获取到的字符串末尾的换行符删掉return 0;
}

2.3用户指令的分割

我们在输入shell指令时有些指令并不是一个单独的指令,另外还包括了参数以及操作对象等,用上面的方法获取的字符串往往是一整串,每个指令之间还包括了空格,这时我们就需要去分割出来每个部分。
有两种实现方法:

第一种直接采用strtok函数对字符串进行分割。
以下是strtok函数的功能介绍:

char *strtok(char *str, const char *delim);
将字符串分解为一个由零个或多个非空记号组成的序列。在第一次调用strtok()
时,要解析的字符串应该在str中指定。在每个应该解析相同字符串的后续调用中,
str必须为NULL。
以下是实现代码:
#include <string.h>
#include <stdio.h>int main(void)
{char cmdbuf[1024] = {0};char *pret = NULL;char *parg[10] = {NULL};int cnt = 0;//ln -s file.txt a.txtgets(cmdbuf);parg[cnt] = strtok(cmdbuf, " ");//以空格进行分割cnt++;while (1){parg[cnt] = strtok(NULL, " "); //后续分割第一个参数传入NULLif (NULL == parg[cnt]){break;}cnt++;}int i = 0;for (i = 0; i < cnt; i++){printf("parg[%d] = %s\n", i, parg[i]);}return 0;
}

第二种是编写函数,采用一个可移动指针去移动到空格出,并置‘\0’,从而实现对字符串的分割:

int SplitCommand(char *pcmdbuf, char **parg, int maxlen)
{char *ptmp = NULL;int cnt = 0;ptmp = pcmdbuf;while (1){parg[cnt] = ptmp;cnt++;while (*ptmp != '\0' && *ptmp != ' '){ptmp++;}if ('\0' == *ptmp){break;}*ptmp = '\0';ptmp++;while (*ptmp == ' '){ptmp++;}}return cnt;
}

2.4 日志文件的创建

这里直接用标准io的相关接口函数进行即可

#include "record.h"
#include <stdio.h>
#include <time.h>FILE *fp = NULL;/*********************************************************函数名:InitRecord*参  数:*		缺省 void *返回值:*		成功返回0 *		失败返回-1 *******************************************************/
int InitRecord(void)
{fp = fopen(RECORD_PATH, "a");if (NULL == fp){return -1;}return 0;
}/*********************************************************函数名:RecordCommand*参  数:*		pcmdbuf 命令字符串首地址		*返回值:*		成功返回0 *		失败返回-1 *******************************************************/
int RecordCommand(char *pcmdbuf)
{time_t t;struct tm *ptm = NULL;time(&t);ptm = localtime(&t);fprintf(fp, "[%04d-%02d-%02d %02d:%02d:%02d]%s\n", ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, pcmdbuf);fflush(fp);return 0;
}/*********************************************************函数名:DeInitRecord*参  数:*		缺省 void *返回值:*		成功返回0 *		失败返回-1 *******************************************************/
int DeInitRecord(void)
{if (fp != NULL){fclose(fp);fp = NULL;}return 0;
}

项目主函数代码展示:

#include <stdio.h>
#include <string.h>
#include "terminal.h"
#include "record.h"int main(void)
{char command[1024] = {0};char *parg[10] = {NULL};int curcmdlen = 0;InitRecord();while (1){ShowTerminal();GetCommand(command, 1024);if (!strcmp(command, "exit")){DeInitRecord();break;}RecordCommand(command);curcmdlen = SplitCommand(command, parg, 10);ExecCommand(parg, curcmdlen);}return 0;
}

三、项目总结

通过本次项目进一步加深了对文件io以及标准io相关函数的了解,进一步加强了在遇到问题时,解决问题的能力,项目过程中令我影响最深刻的就是在获取用户输入的指令时,一开始在另外一个文件中定义了一个数组用来存放获取的指令,导致之后运行时,指令数据莫名消失,通过排查才发现,对于这种程序一直都会到处使用的数据应该注意其的存在时间,因为如果将指令存放在一个函数中,就会导致这样一个局部变量在函数运行结束后这个数据就会消失,所以应该将其定义在主函数中或者定义为全局变量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2803739.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

windows前后端项目部署

装好windows虚拟机 1.远程连接 计算机右击属性&#xff0c;高级防火墙设置&#xff0c;远程连接服务允许 2.安装jdk,tomcat&#xff0c;解压工具 把安装包拖进去 双击安装解压软件 jdk安装 双击安装 配置环境变量&#xff08;复制jdk路径&#xff09; 计算机右击属性高级…

苹果分拣检测YOLOV8NANO

苹果分拣&#xff0c;可以检测成熟、切片、损坏、不成熟四种类型&#xff0c;YOLOV8NANO&#xff0c;训练得到PT模型&#xff0c;然后转换成ONNX&#xff0c;OPENCV的DNN调用&#xff0c;支持C,PYTHON 苹果分拣检测YOLOV8NANO&#xff0c;检测四种类型苹果

好用免费的项目管理工具

禅道 禅道 &#xff08; https://www.zentao.net/ &#xff09;是一款流行的项目管理和缺陷跟踪软件。它的主要功能包括项目管理、需求管理 、缺陷跟踪 、测试管理 、文档管理 、负载统计与报表 、自定义工作流 、访问控制与权限管理等。支持私有化部署&#xff0c;可完全控制…

代码随想录算法训练营第39天| Leetcode 62.不同路径、Leetcode 63. 不同路径 II

文章目录 Leetcode 62.不同路径Leetcode 63. 不同路径 II Leetcode 62.不同路径 题目链接&#xff1a;Leetcode 62.不同路径 题目描述&#xff1a; 一个机器人位于一个 m x n 网格的左上角 &#xff0c;机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角。问总…

数通HCIE学员心得:跨界、转行,我在誉天开启人生新篇章

大家好&#xff0c;我是来自誉天的田同学。 我和誉天的故事开始于22年的8月份。毕业之后&#xff0c;由于对自身专业的不喜欢&#xff0c;我对未来感到非常迷茫。也就是这个时候&#xff0c;我接触到了誉天&#xff0c;开启了我的人生新篇章。 一开始我就想着要转行&#xff…

Project_Euler-14 题解

Project_Euler-14 题解 题目 思路 从暴力枚举出发&#xff0c;枚举100万以内的所有数字&#xff0c;对于每一个数&#xff0c;维护一个长度&#xff0c;每根据公式执行一次运算就加一。 最后取最大值。 暴力枚举代码 #include <stdio.h> #include <stdlib.h> #…

大数据 - Spark系列《十一》- Spark累加器详解

Spark系列文章&#xff1a; 大数据 - Spark系列《一》- 从Hadoop到Spark&#xff1a;大数据计算引擎的演进-CSDN博客 大数据 - Spark系列《二》- 关于Spark在Idea中的一些常用配置-CSDN博客 大数据 - Spark系列《三》- 加载各种数据源创建RDD-CSDN博客 大数据 - Spark系列《…

大型语言模型的语义搜索(一):关键词搜索

关键词搜索(Keyword Search)是文本搜索种一种常用的技术&#xff0c;很多知名的应用app比如Spotify、YouTube 或 Google map等都会使用关键词搜索的算法来实现用户的搜索任务&#xff0c;关键词搜索是构建搜索系统最常用的方法&#xff0c;最常用的搜索算法是Okapi BM25&#x…

【文件搜索项目】使用jdbc操作SQLite

一. 插入&#xff08;采用变量的方式插入&#xff09; 1.创建数据源.DateSource 2.建立连接 3.构造SQL语句 4.执行SQL语句 5.释放资源 public class TestSQLite {public static void main(String[] args) throws SQLException {textInsert();}public static void textInsert(…

超级抽象的前端2

vue3的调用方法失败的原因 function validateConfirm(rule, value, callback) {if (value ! form.password) {callback(new Error(两次输入的密码不一致))} else {callback()}function showAgreement() {dialogVisible.value true}function submitForm() {// 这里是提交表单的…

【RT-Thread基础教程】线程优先级、Tick与线程状态

文章目录 前言一、线程优先级1.1 线程优先级是什么1.2 设置优先级范围 二、时间片2.1 Tick是什么2.2 时间片是什么2.3 时间片轮转 三、线程状态3.1 线程有哪些状态3.2 完整的状态转换图 总结 前言 在 RT-Thread 操作系统中&#xff0c;线程的优先级、Tick 以及线程状态是非常重…

每日一练 | 华为认证真题练习Day187

1、关于BGP状态机描述错误的 A. IDIE状态下&#xff0c;BGP拒绝任何进入的连接请求&#xff0c;是BGP初始状态 B. ACTIVE状态下&#xff0c;BGP将尝试进行TCP连接的建立&#xff0c;是BGP的中间状态 C. ESTABLISHED状态下&#xff0c;BGP对等体间可以交换UPDATE报文&#xf…

算法--动态规划(背包问题)

这里写目录标题 总览dp问题的优化01背包问题概述算法思想算法思想中的注意点例题代码等效为一维数组 完全背包问题概述算法思想例题代码等效为二维数组等效为一维数组 多重背包问题概述算法思想例题代码优化&#xff08;采用二进制的方式&#xff09;基本思想时间复杂度例题代码…

开发Chrome插件,background.js中log打印未出现在控制台

不同于内容脚本&#xff08;通常命名content.js&#xff09;&#xff0c;在后台脚本&#xff08;通常命名background.js或service-worker.js&#xff09;中console.log并不会在控制台中直接显示。 要查看后台脚本上下文的正确控制台&#xff0c;执行如下步骤&#xff1a; 访问…

2024年2月17日~2月23日周报

文章目录 一、前言二、DDNet架构学习2.1 数据预处理2.2 网络模型构建 三、基于深度学习地震数据去噪处理3.1 深度学习在地震数据去噪中的研究方向3.2 深度学习地震数据去噪流程3.2.1 数据集准备3.2.2 模型构建3.2.3 训练网络 3.3 基于DnCNN的地震数据去噪实验 四、小结4.1 存在…

前端项目打包体积分析与优化

一、安装依赖分析工具 npm install webpack-bundle-analyz 二、修改webpack.config.js文件 1、导入上面下载的包 2、在plugins里创建实例 三、启动打包命令 npm run build 会弹出如下界面&#xff1a; 四、优化 1、通过CDN导入react-dom文件 修改webpack.config.js文件里…

【前端素材】推荐优质后台管理系统GramOs平台模板(附源码)

一、需求分析 后台管理系统是一种用于管理网站、应用程序或系统的工具&#xff0c;它通常作为一个独立的后台界面存在&#xff0c;供管理员或特定用户使用。下面详细分析后台管理系统的定义和功能&#xff1a; 1. 定义 后台管理系统是一个用于管理和控制网站、应用程序或系统…

Linux环境非root用户配置SSH免密登录,并解决登录仍提示输入密码

Linux环境非root用户配置SSH免密登录&#xff0c;并解决登录仍提示输入密码 ssh免密登录的简单理解 以A和B进行举例&#xff1a;A免密登录B &#xff08;即在A服务器输入命令&#xff1a;ssh 非root用户名B的IP地址&#xff09;可以直接免密码直接登录 A生成私钥和公钥&#…

QT基本组件

四、基本组件 Designer 设计师&#xff08;重点&#xff09; Qt包含了一个Designer程序&#xff0c;用于通过可视化界面设计开发界面&#xff0c;保存文件格式为.ui&#xff08;界面文件&#xff09;。界面文件内部使用xml语法的标签式语言。 在Qt Creator中创建文件时&#xf…

​分享87个Html企业模板,总有一款适合您

分享87个Html企业模板&#xff0c;总有一款适合您 87个Html企业模板下载链接&#xff1a;https://pan.baidu.com/s/1iBpfaBRgMJBv4pj07rZhOg?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集…