对Linux命令od -tc -tx1的C语言程序实现myod-优化版
导语
自编od C语言实现版名为myod
上个星期有一个初代版,链接- myod原版
这星期的课上要求实现myod-系统调用版本,要求如下
1 参考教材第十章内容
2 用Linux IO相关系统调用编写myod.c 用myod XXX实现Linux下od -tx -tc XXX的功能,注意XXX是文件名,通过命令行传入,不要让用户输入文件名
3.不要把代码都写入main函数中
4.要分模块,不要把代码都写入一个.c中
5 提交测试代码和运行结果截图, 提交调试过程截图,要全屏,包含自己的学号信息
程序思路
结构
- 判定命令行输入是否正确,错误则报错退出。
对文件进行录入并存入字符数组str[]
相关函数及头文件
函数 | 头文件 |
---|---|
open() | #include <sys/types.h>;#include <sys/stat.h>;#include <fcntl.h> |
read() | #include <unistd.h> |
- 输出八位表示的累计字符
- 输出最多十六个为一组的文本
- 输出该组文本各字符的ASCII码
- 对于每行最多处理16个字符,我使用的是for循环和一个计数函数count共同把控
变量说明
char str[BUFFERSIZE];存整个文本的字符串
int LJ;已累计表示了多少各字符
int SY;还剩下多少字符没有表示
int tSY,Dan;tSY其实是SY,但是为了分模块处理便于我自己的理解便改了个名称,Dan是单次表示字符个数,和tSY组合使用
int tx[8];char tx2[8];用于表示八位十六进制累计数字和ASCII码十六进制表示
补充知识点
- read()在Linux C下,可以直接在终端用man查看,或者下载中文的man帮助文档,如果懒得翻可以打开该链接—— read()
- open()同理—— 打开文件open()函数的使用方法详解--C语言函数
perror()同理——perror; perror 的用法
codeblocks整理代码:Plugins->Source code formatter(Astyle)
优化过程
代码对比
嫌弃版
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void One(int LJ,int tx[],char tx2[]);
void TX(int H,int tx[]);
char Change(int t);
void main(int argc,char *argv[])
{FILE *fp;if((fp = fopen(argv[4],"r")) == NULL){printf(" ***文件打开失败***");exit(0);}if(strcmp(argv[1], "od")==0){if(strcmp(argv[2], "-tc")==0){if(strcmp(argv[3], "-tx")==0){char str[1000];int num,i,j,i2;for(num=0; num<strlen(str); num++)str[num] = '0';num = 0;int fd;fd = open(argv[4], O_RDONLY);num = read(fd, str, sizeof(str));close(fd);int LJ;int SY;for(LJ = 0,SY = num;;){int tx[8];char tx2[8];for(j=0; j<8; j++)tx[j] = 0;One(LJ,tx,tx2);for(j=0; j<8; j++){printf("%c",tx2[j]);}printf(" ");//累计字符输出完毕int tSY,Dan;tSY = SY;// do// {if(tSY>=16){Dan = 16;}else{Dan = tSY;}for(j=LJ; j<Dan+LJ; j++){// printf("j = %d,Dan=%d\n",j,Dan);if(str[j]=='\n'){printf("\\n ");}else{printf("%c \t",str[j]);}}// putchar(str[i]);printf("\n");int tt;
//输出文本printf(" ");for(j=LJ; j<Dan+LJ; j++){tt = str[j];One(tt,tx,tx2);for(i2=0; i2<8; i2++){if(tx2[i2]!='0')printf("%c",tx2[i2]);}printf(" \t");}printf("\n");tSY = tSY-Dan;// }// while(tSY>0);printf("\n");// printf("SY=%d,LJ=%d\n",SY,LJ);if(SY>=16){LJ = LJ+16;}else if((SY>0)&&(SY<16)){LJ = LJ+SY;}else if(SY==0){break;}SY = num-LJ;// printf("SY=%d,LJ=%d\n",SY,LJ);}}}}else{printf("指令输入错误\n");}
// printf("\nover\n");fclose(fp);
}
void One(int LJ,int tx[],char tx2[]){TX(LJ,tx);int i;// printf("\n分界线\n");for(i=0; i<8; i++){// printf("%d ",tx[i]);tx2[i] = Change(tx[i]);// printf("%c",tx2[i]);}
}
void TX(int H,int tx[])
{if(H>536870911){printf("字符数太大,超出限制\n");exit (0);}int i=7;// printf("LS = %d\n",H);for(; i>0;){tx[i] = H%16;H = H/16;i--;
// printf(" H = %d,tx[%d] = %d\n",H,i+1,tx[i+1]);}
}
char Change(int t)
{// printf("scs\n");if((t>=0)&&(t<10)){return t+48;}else{return t+87;}
}
优化版
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#define BUFFERSIZE 1000
void Change(int LJ,int tx[],char tx2[]);
void dToH(int H,int tx[]);
char intToChar(int t);
int count(int *tSY,int *Dan,int *LJ,int *SY,int *num);
void outputAscii(char tx2[],int Dan,int LJ,int tx[],char str[]);
void main(int argc,char *argv[])
{char str[BUFFERSIZE];int num,i,j,i2;int fd;if((strcmp(argv[1], "od")!=0)|(strcmp(argv[3], "-tc")!=0)|(strcmp(argv[2], "-tx")!=0)){printf("输入格式错误");exit(0);}for(num=0; num<strlen(str); num++)str[num] = '0';num = 0;if ( (fd = open(argv[4], O_RDONLY)) == -1 ){perror(argv[4]);exit(1);}num = read(fd, str, BUFFERSIZE);close(fd);int LJ;int SY;int tx[8];char tx2[8];int tSY,Dan;for(LJ = 0,SY = num;;){for(j=0; j<8; j++)tx[j] = 0;Change(LJ,tx,tx2);for(j=0; j<8; j++){printf("%c",tx2[j]);}printf(" ");//累计字符输出完毕tSY = SY;if(tSY>=16){Dan = 16;}else{Dan = tSY;}for(j=LJ; j<Dan+LJ; j++){if(str[j]=='\n'){printf("\\n ");}else{printf("%c \t",str[j]);}}printf("\n");//输出文本outputAscii(tx2,Dan,LJ,tx,str);if(2==count(&tSY,&Dan,&LJ,&SY,&num))exit(0);}
}
void Change(int LJ,int tx[],char tx2[]){dToH(LJ,tx);int i;for(i=0; i<8; i++){tx2[i] = intToChar(tx[i]);}
}
void dToH(int H,int tx[])//十进制转十六进制,但此时仍用int存储
{if(H>536870911){printf("字符数太大,超出限制\n");exit (0);}int i=7;for(; i>0;){tx[i] = H%16;H = H/16;i--;}
}
char intToChar(int t)//十六进制,把int[]转为char[]
{if((t>=0)&&(t<10)){return t+48;}else{return t+87;}
}
int count(int *tSY,int *Dan,int *LJ,int *SY,int *num)//计数并判定是否终止
{*tSY = *tSY-*Dan;printf("\n");if(*SY>=16){*LJ = *LJ+16;}else if((*SY>0)&&(*SY<16)){*LJ = *LJ+*SY;}else if(*SY==0){return 2;}*SY = *num-*LJ;return 1;
}
void outputAscii(char tx2[],int Dan,int LJ,int tx[],char str[])
{int tt,j,i2;printf(" ");for(j=LJ; j<Dan+LJ; j++){tt = str[j];Change(tt,tx,tx2);for(i2=0; i2<8; i2++){if(tx2[i2]!='0')break;}for(;i2<8;i2++)printf("%c",tx2[i2]);printf(" \t");}printf("\n");
}
改造过程
1.把没来得及删掉的用指针打开文件的那段fp = fopen(argv[4],"r"等删掉,有open就可以了
2.修改自编函数名称。当我回来再看代码时原先的名称确实无法提醒我到底它要做什么,(捂脸),所以组合型名称按照小驼峰式,单个词函数名用了首字母大写的方式,多谢老师指导与提醒~
3.判定命令行输入条件时取消那么多if,直接用“|”符号来限定选择条件
if((strcmp(argv[1], "od")!=0)|(strcmp(argv[3], "-tc")!=0)|(strcmp(argv[2], "-tx")!=0))
4.将存文本的字符大小用宏定义BUFFERSIZE,提高程序的可读性与可维护性。解释:比如我想存一个10000的文本,但是之前的str[]只有1000,所以我只需要把define那里的BUFFERSIZE改掉,后面的就不用改了,否则还得满篇找1000改10000,这个程序短,所以还不觉得有什么,但是程序如果很大很复杂,这种情况不仅维护的人不好读懂代码,而且容易改漏。
5.使用perror()函数,添加报错功能。
6.将计数和输出ASCII码的功能从主函数中分离出来成为自编函数,使主程序显得不那么臃肿,更好读懂。
7.修改了一个程序上的错误
for(i2=0; i2<8; i2++){if(tx2[i2]!='0')printf("%c",tx2[i2]);}
这个输出会把所有0给抹掉,也是优化的时候才发现这个错误(捂脸)
修改为:
for(i2=0; i2<8; i2++){if(tx2[i2]!='0')break;}for(;i2<8;i2++)printf("%c",tx2[i2]);
代码链接
myod嫌弃版(合体)
myod优化版(合体)
myod优化版(模块化)
一阵瞎逼逼
第一个版本我本来就实现了命令行调用,并且并未只写在一个main函数里,就只需要改两个函数就可以了。当时课上电脑不知道被我改了哪里,找不到网络的开关……慌慌地改了代码交了,觉得代码还是有点丑,想着怎么再改改,眼瞎也没看到还有展开项-提交代码……
看到老师对之前博客的评论,越看我的代码越觉得……好嫌弃,确实需要好好改一改。于是真的有不少地方可以改……就有了对二代版的优化版。
之所以单开一篇博客是为了方便我日后记不到了好查找资料。是的,作为一个暑假之后就忘了放在学校电脑的开机密码的人真的不能对自己的记忆力多有信心。以后可能会在自己的博客里记录一些非常简单的知识。反正最终都会忘掉的,不如让再次自学的时候能轻松高效一些。
转载于:https://www.cnblogs.com/GDDFZ/p/7656052.html
对Linux命令od -tc -tx1的C语言程序实现myod-优化版相关推荐
- linux八进制属性,解释八进制和linux命令od +理解0x00(Explain Octal and the linux command od + understanding 0x00)...
解释八进制和linux命令od +理解0x00(Explain Octal and the linux command od + understanding 0x00) 我试图了解这个linux命令的 ...
- Linux GCC简明教程(编写c语言程序)
市面上常见的 Linux 都是发行版本,典型的 Linux 发行版包含了 Linux 内核.桌面环境(例如 GNOME.KDE.Unity 等)和各种常用的必备工具(例如 Shell.gcc.VIM. ...
- 抓包分析,一条Linux命令实现路由器自动登录深大校园网认证(Drcom Pt版)
先说结论,通过抓包分析简化最后可以得出,其登录过程只是一个简单的向服务器发送HTTP GET请求或HTTP POST请求.只要在路由器启动之后自动发送一段 HTTP 请求,即可实现自动登录. 对于 G ...
- 《Linux命令行与shell脚本编程大全》(第三版)读书笔记
第一部分 Linux命令行 第三章.基本的bash shell命令 bash手册 man 命令 例子: man cat 空格翻页.回车下一行.左右键看右侧(左侧)内容.q退出 info info in ...
- linux命令宝典,Linux命令行完全技术宝典(张栋) PDF扫描版[85MB]
Linux命令行完全技术宝典 内容简介: <linux命令行完全技术宝典>基于red hat enterprise as操作系统,汇集了绝大部分命令的功能介绍.参数说明和注意事项,并针对具 ...
- linux编译OCC,Linux命令 od -t oCc 选项是什么意思?
满意答案 ashinxx 2016.03.05 采纳率:40% 等级:7 已帮助:109人 od命令用于输出文件的八进制.十六进制或其它格式编码的字节,通常用于显示或查看文件中不能直接显示在终端 ...
- Linux 命令 - od
转载地址: http://hi.baidu.com/whs08/blog/item/8e82fa553cb264c1b645ae02.html od(octal dump) 功能说明:输出文件内容. ...
- 黑客进阶必读书《Linux命令行与Shell脚本编程大全》(第2版)
欢迎来到命令行和shell脚本编程的世界!厚厚的一本小样书,拿在手上,厚厚的一本,六百多页.不只是掂在手上的重量,更是一本优秀的初学者入门指南,又会是你的Linux书库中非常不错的参考书.如果你想从整 ...
- Linux 命令之 sftp -- 交互式的文件传输程序
文章目录 一.命令介绍 二.常用选项 三.参考示例 (一)使用 sftp 连接远程主机 (二)使用 sftp 上传文件到远程主机 (三)使用 sftp 从远程主机下载文件 (四)查看远程主机的当前目录 ...
最新文章
- 设计一个函数能够取出字符串中指定的字符
- STM32F407的硬件I2C
- Ubuntu16.04.2安装KDE
- zabbix增加手机端4个url地址的返回值
- 动态规划 —— 概率 DP 与期望 DP
- 无法用php smtp发送邮件. 您的服务器可能没有配置用此方法_补充:Web自动化邮件发送...
- 如何退出控屏软件(以极域为例)
- Markdown编辑器 - 字体颜色表(颜色名、十六进制颜色值、颜色)
- leetcode题解日练--2016.8.6
- QTcreator Label控件显示乱码问题解决办法
- 31个全网最常用python实现(体系学习,学完显著提高代码复用能力)
- 【异常处理】解决Windows下access denied for user ‘root‘@‘localhost‘(using password:YES)的mysql启动问题
- 阿里巴巴高级技术专家 至简 聊工程师思维(配音版)
- 河南大学计算机学院夏令营,河南大学数学与统计学院2020年优秀大学生国际夏令营...
- Java--第1天--日期(一)
- 数据库安装mysql失败解决方案
- Android开发 TextView
- 微信 H5 页面前端开发,大多数人都会遇到的几个兼容性坑
- 马丁福勒《UML精粹》读书笔记_第三章
- 【运维探讨】RPA落地实践,提升IT运维工作效能!
热门文章
- 什么函数是回调函数?
- ROS配置分布式通信
- (DFS or BFS)Find The Multiple(poj1426)
- java 读取 excel poi_Java中读取Excel功能实现_POI
- jsp源码oracle数据库,JSP与oracle数据库交互案例
- HTML+CSS+JS实现 ❤️酷炫3D瀑布流动画特效❤️
- js文件夹上传到服务器,js 上传img到服务器
- 选择排序--Java
- 内部类-----Java
- 2012 安装mysql 5.6_如何安装mysql server 5.6