2020-2021-1 20209326 《Linux内核原理与分析》第二周作业 MyOD(选作)
任务详情
复习c文件处理内容
编写myod.c 用myod XXX实现Linux下od -tx -tc XXX的功能
main与其他分开,制作静态库和动态库
编写Makefile
提交测试代码和运行结果截图, 提交调试过程截图,要全屏,包含自己的学号信息
在博客园发表一篇博客,重点写遇到的问题和解决过程
Linux od命令
Linux od命令用于输出文件内容。
od指令会读取所给予的文件的内容,并将其内容以八进制字码呈现出来。
语法
od [-abcdfhilovx][-A <字码基数>][-j <字符数目>][-N <字符数目>][-s <字符串字符数>][-t <输出格式>][-w <每列字符数>][--help][--version][文件...]
其中od -tx -tc分别显示对应文件的十六进制和ASCII编码字符
实验代码
参照往届学长的程序设计改进代码如下:
问题与改进
1.od命令输出行前有序号,7位,填充0:
解决方法:定义一个计数变量,以printf("%07d ",k);
输出。
2.od可以输出'\n'、'\r'、'\t'等转义字符:
解决方法:if判断后再转义输出
if(str[j]=='\n'){
printf(" \\n ");
}else if(str[j]=='\t'){
printf(" \\t ");
}else if(str[j]=='\r'){
printf(" \\r ");
}else{
printf("%4c",str[j]);
}
3.linux中od命令输出4个的16进制数与ASCII码值相反:
解决办法:逆序输出
for(j=0;j<16;j++){
if((j+1)%4==0){
printf("%02x%02x%02x%02x ",str[j],str[j-1],str[j-2],str[j-3]);
}
}
4.最后一行输出的格式与od有差异:
解决办法:逐层输出
printf("%07d ",k);
for(j=0;j<i;j++){
if((j+1)%4==0){
printf("%02x%02x%02x%02x ",str[j],str[j-1],str[j-2],str[j-3]);
}
}
if((j+1)%4==0){
printf("00%02x%02x%02x ",str[j],str[j-1],str[j-2]);
}else if((j+2)%4==0){
printf("0000%02x%02x ",str[j],str[j-1]);
}else if(j%3==0){
printf("000000%02x ",str[j]);
}
printf("\n");
printf(" ");
for(j=0;j<i;j++){
if(str[j]=='\n'){
printf(" \\n ");
}else if(str[j]=='\t'){
printf(" \\t ");
}else if(str[j]=='\r'){
printf(" \\r ");
}else{
printf("%4c",str[j]);
}
}
printf("\n%07d \n",k+i%16);
makefile
makefile文件
make过程
实验结果
修改后分模块代码
20209326_myod.c
#include "od.h"
int main(int argc,char *argv[])
{
od(argv);
return 0;
}
od.c
#include "od.h"
void od(char *argv[]){ //od函数
FILE *fp;
char ch;
char str[16];
int i=0;
int k=0;
if((fp = fopen(argv[1],"r"))==NULL)
{
printf("Failure to open %s !\n",argv[0]);
exit(0);
}
while((ch=fgetc(fp))!=EOF)
{
str[i]=ch;
i++;
if(i==16)
{
i=0;
printf("%07d ",k);
k+=20;
pm16(str);
}
}
printf("%07d ",k);
pml(str,i);
printf("\n%07d \n",k+i%16);
fclose(fp);
}
void pm16(char str[16]){ //处理字符个数能整除16的行的输出
int j;
for(j=0;j<16;j++){
if((j+1)%4==0){
printf("%02x%02x%02x%02x ",str[j],str[j-1],str[j-2],str[j-3]);
}
}
printf("\n");
printf(" ");
for(j=0;j<16;j++){
prc(str[j]);
}
printf("\n");
}
void pml(char str[16],int i){ //处理最后一行的输出
int j;
for(j=0;j<i;j++){
if((j+1)%4==0){
printf("%02x%02x%02x%02x ",str[j],str[j-1],str[j-2],str[j-3]);
}
}
if((j+1)%4==0){
printf("00%02x%02x%02x ",str[j],str[j-1],str[j-2]);
}else if((j+2)%4==0){
printf("0000%02x%02x ",str[j],str[j-1]);
}else if((j+3)%4==0){
printf("000000%02x ",str[j]);
}
printf("\n");
printf(" ");
for(j=0;j<i;j++){
prc(str[j]);
}
}
void prc(char ch){ //处理输出字符串
if(ch=='\n'){
printf(" \\n ");
}else if(ch=='\t'){
printf(" \\t ");
}else if(ch=='\r'){
printf(" \\r ");
}else{
printf("%4c",ch);
}
}
od.h
#ifndef OD_H
#define OD_H
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
void prc(char ch);
void od(char *argv[]);
void pm16(char str[16]);
void pml(char str[16],int i);
#endif
makefile
#变量定义
TARGET=myod
CC=gcc
#把不同的路径赋给相应的变量
DIR_BIN=./bin
DIR_SRC=./src
DIR_INC=./include
DIR_LIB=./lib
#把./src中的所有.c文件拿出来赋给变量SRC_PATH,包括.c文件的路径
SRC_PATH=$(wildcard ${DIR_SRC}/*.c)
#去掉SRC的路径,然后把所有.c文件后缀名,改为.o,最后把这些.o文件赋给变量
OBJ = $(patsubst %.c,%.o,$(notdir ${SRC_PATH}))
#把bin文件夹下的所有.o文件赋给变量
OBJ_PATH=$(wildcard ${DIR_BIN}/*.o)
${TARGET}:${OBJ}
${CC} -o ${TARGET} ${OBJ_PATH}
mv ${TARGET} ${DIR_BIN}/
${OBJ}:
${CC} -c ${SRC_PATH} -I ${DIR_INC}
mv ${OBJ} ${DIR_BIN}/
ar rcvs libmyod.a ${DIR_BIN}/*.o
${CC} -shared -o libmyod.so ${DIR_BIN}/*.o
mv libmyod.a ${DIR_LIB}/
mv libmyod.so ${DIR_LIB}/
编译与结果如下图所示