对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]);
代码链接
一阵瞎逼逼
第一个版本我本来就实现了命令行调用,并且并未只写在一个main函数里,就只需要改两个函数就可以了。当时课上电脑不知道被我改了哪里,找不到网络的开关……慌慌地改了代码交了,觉得代码还是有点丑,想着怎么再改改,眼瞎也没看到还有展开项-提交代码……
看到老师对之前博客的评论,越看我的代码越觉得……好嫌弃,确实需要好好改一改。于是真的有不少地方可以改……就有了对二代版的优化版。
之所以单开一篇博客是为了方便我日后记不到了好查找资料。是的,作为一个暑假之后就忘了放在学校电脑的开机密码的人真的不能对自己的记忆力多有信心。以后可能会在自己的博客里记录一些非常简单的知识。反正最终都会忘掉的,不如让再次自学的时候能轻松高效一些。
对Linux命令od -tc -tx1的C语言程序实现myod-优化版的更多相关文章
- 课后练习:C语言实现Linux命令——od
课后练习:C语言实现Linux命令--od --------CONTENTS-------- 题目详情与分析 设计思路 遇到的问题及解决 待实现的设想与思考 学习反思与感悟 附1:myod.c「1.0 ...
- C语言实现Linux命令——od
C语言实现Linux命令--od 实现要求: 复习c文件处理内容 编写myod.c 用myod XXX实现Linux下od -tx -tc XXX的功能 main与其他分开,制作静态库和动态库 编写M ...
- Linux命令——od
参考:Linux OD Command Tutorial for Beginners (6 Examples) 简介 查看普通文本文件,可以使用cat.head.tail.tac.less.more等 ...
- Linux命令应用大词典-第12章 程序编译
12.1 gcc:GNU项目的C和C++编译器 12.2 gdberver:为GNU调试的远程服务器 12.3 cmake:跨平台的Makefile生成工具 12.4 indent:更改通过插入或删除 ...
- linux命令中的“<”和“|”是什么意思?
”<” 表示的是输入重定向的意思,就是把<后面跟的文件取代键盘作为新的输入设备.”| ”则表示一个管道的意思,可以理解为东西从管道的一边流向另外一边. cat file.json | ...
- 学号20175313 《实现Linux下od -tx -tc XXX的功能》第九周
目录 MyOD 一.题目要求 二.题目理解 三.需求分析 四.设计思路 五.代码链接 六.代码实现过程中遇到的问题 七.运行结果截图 八.参考资料 MyOD 一.题目要求 编写MyOD.java 用j ...
- 实现Linux下od -tx -tc XXX的功能
实现Linux下od -tx -tc XXX的功能 一.od命令 (1)功能 od命令用于将指定文件内容以八进制.十进制.十六进制.浮点格式或ASCII编码字符方式显示,通常用于显示或查看文件中不能直 ...
- 以二进制的形式查看文件 Linux之od命令详解
od命令 以二进制的形式查看文件 od -t x1 /usr/local/FT/config/hsm_create.utf8.sql ef bb bf 4c 5f 0d 0a 5f 4e 4e 4f ...
- [转]Linux之od命令
转自:http://os.51cto.com/art/200912/173136.htm 随着计算机飞速的发展,很多人开始学习Linux,怎样才能学好Linux,一定要学好Linux的命令.学习Lin ...
随机推荐
- 自学PHP有哪些书籍和教程值得推荐?
知乎上看到一题主询问:"自学PHP有哪些书籍和教程值得推荐?",互联网深度屌丝秦风给出了不错的答案,希望能够帮助自学PHP的朋友们. 以下仅供参考: 尤其不认可W3school之类 ...
- fill & stroke
- (void)stroke Draws a line along the receiver’s path using the current drawing properties. - (void) ...
- C++ —— 小操作
判断一个浮点数是否是整数: #include <iostream> using namespace std; int main() { ); if (l == (int)l) { //.. ...
- HTML 5中的文件处理之FileAPI
在众多HTML5规范中,有一部分规范是跟文件处理有关的,在早期的浏览器技术中,处理小量字符串是js最擅 长的处理之一.但文件处理,尤其是二进制文件处理,一直是个空白.在一些情况下,我们不得不通过Fla ...
- 关于numpy mean函数的axis参数
import numpy as np X = np.array([[1, 2], [4, 5], [7, 8]]) print np.mean(X, axis=0, keepdims=True) pr ...
- Spring Cloud Consul 之Greenwich版本全攻略
什么是Consul Consul是HashiCorp公司推出的开源软件,使用GO语言编写,提供了分布式系统的服务注册和发现.配置等功能,这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全 ...
- 清理 Xcode 10 记录
1,清理 ~/Library/Developer/CoreSimulator/Devices 说明:该目录存放当前的所有模拟器,每个标识符代表一台机器,清理掉避免存在旧版本的模拟器缓存 执行: 关闭模 ...
- Java并发编程(三)什么是线程池
什么是线程池 学习编程的小伙伴们会经常听到“线程池”.“连接池”这类的词语,可是到底“池”是什么意思呢?我讲个故事大家就理解了:在很久很久以前有一家银行,一年之中只有一个客户来办理业务,随着时间的推移 ...
- $(document).ready(function(){})与window.load
$(document).ready(function(){ //to do something}) 是当文档全部加载完全的时候触发,包括img也加载完成但是相关的文件没有下载下来,能同时编写多个 wi ...
- MySQL 基础小技巧
把MySQL软件制作成系统服务 .把mysqld软件做成系统服务 注意:制作之前先把mysqld关掉 C:\Windows\system32>tasklist |findstr mysqld m ...