• 编写myod.c 用myod XXX实现Linux下od -tx -tc XXX的功能


    题目要求:

    1.复习c文件处理内容

    2.编写myod.c 用myod XXX实现Linux下od -tx -tc XXX的功能

    3.main与其他分开,制作静态库和动态库

    4.编写Makefile

    完成思路:

    (一)在Linux下使用od -tx -tc XXX的效果为:

     

     

    (二)Od命令简析

    1、功能

    od命令用于将指定文件内容以八进制、十进制、十六进制、浮点格式或ASCII编码字符方式显示,通常用于显示或查看文件中不能直接显示在终端的字符。od命令系统默认的显示方式是八进制,名称源于Octal Dump。

    常见的文件为文本文件和二进制文件。od命令主要用来查看保存在二进制文件中的值,按照指定格式解释文件中的数据并输出,不管是IEEE754格式的浮点数还是ASCII码,od命令都能按照需求输出它们的值。

    2、格式

    od [<选项><参数>] [<文件名>]

    3、常用的命令选项

    -t,--format=TYPE:指定输出格式,格式包括a、c、d、f、o、u和x,各含义如下:

    a:具名字符;

    c:ASCII字符或者反斜杠;

    d[SIZE]:十进制,正负数都包含,SIZE字节组成一个十进制整数;

    f[SIZE]:浮点,SIZE字节组成一个浮点数;

    o[SIZE]:八进制,SIZE字节组成一个八进制数;

    u[SIZE]:无符号十进制,只包含正数,SIZE字节组成一个无符号十进制整数;

    x[SIZE]:十六进制,SIZE字节为单位以十六进制输出,即输出时一列包含SIZE字节。

    例如:od -tx testfile表示以十六进制输出,默认以四字节为一组(一列)显示;od -tx1 testfile表示以十六进制输出,每列输出一字节。

     

    (三)需求分析

    1支持在命令行中输入一个字符串该字符串代表要进行转化的文件名

    2每行开头为当前读取到的字符数的7位八进制表示

    3每行读取16个字符,每个字符转化为两位的十六进制数,每四个字符作为一组输出。每输出一行文件内容的十六进制表示,下一行紧接着输出对应的ASCII字符。

    4全部文本内容输出结束后,输出“ ”的十六进制表示以及对应的ASCII字符

     

    (四)遇到的问题

    问题一与Linux命令下的输出显示不完全对应:每一行输出的是16个字符或16个字符的十六进制表示;上一行的ASCII字符与下一行的进制对齐;缺少每行最前面的“0000020”等计数标识等。如何调整使得输出形式与Linux下相同?

    解决方法:通过观察发现,每行开头这串数字为八进制,数值为在本行之前的字符数。所以需要在tx.c函数中增加一行prinf()函数中格式化输出printf("%07o",参数),这里的参数设置成16*首字呼应一行显示16个字符。并在tc.c增加一个空格的输出,已达到格式统一的效果。另外,printf()的修饰符中,数字表示最小字段宽度。如果该字段不能容纳待打印的数字或字符串,系统会用更宽的字段。所以,例如printf("4d%",参数)即可打印宽度为4的十进制数。这里采用 printf("%4c",参数)和printf("%4x",参数)即可满足对齐的要求。

     

    问题二:发现程序无法显示“ ”的ASCII字符,但linux的od命令可以,如何显示出“ ”

    解决方法:对读取的字符进行判断,如遇到“ ”,手动输出,这里要注意使用转义字符,即printf("\n")。

    问题三:注意到Linux命令是一行ASCII字符,一行十六进制表达相间输出的,所以如果在传入-tc的同时也传入了–tx参数,如何做到间隔输出两种不一样的表达?

    解决方法1:通过查阅资料,在Windows下,可以引用<windows.h>头文件中定义的 SetConsoleCursorPosition() 来实现对光标的控制,即在输出字符后移动光标至(0,1),再调用输出进制的函数,将其全部输出。其具体方法为:

    ①定义一个COORD类型的结构体;

    ②设置结构体中x和y的值,即光标的位置;

    ③调用SetConsoleCursorPosition()函数,完成设置。

    //设置光标的位置  void gotoxy(int x,int y)   {  

        COORD c;  

        c.X=x-1;  

        c.Y=y-1;  

        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c);  

    }   

    解决方法2:但这种方式只在Windows下有效(Linux中没有windows.h),故采取的方式是每输出一行十六进制表达之后,输出 ,再调用输出字符的函数输出一行字符,再调用输出十六进制的函数,以此类推。这种方法需要在main函数中使用一个循环。

    while(fgets(args,17,fp))

        {

            tx(args,i++);

            tc(args);

        }

     

    问题四:发现Linux的od -tx命令默认以四字节为一组(一列)显示,而程序是以十六进制输出,每列输出一字节,如何与Linux中一致?

    解决方法:源代码以1字节为1组输出十六进制:

    for(i=0;args[i]!='';i++)

        {

            if(args[i]==' ')

                printf("%x",' ');

                printf("%4x",args[i]);

        }

    修改后:四字节为一组(一列)显示

    for(i=0;args[i]!='';i++)

        {

            if(args[i]==' ')

                output[i]=' ';

            else

                output[i]=args[i];

        }

        for(i=0;args[i]!='';i=i+4)

        {

            printf("        %x%x%x%x",output[i],output[i+1],output[i+2],output[i+3]);

        }

    问题五:程序输出的十六进制数顺序与Linux命令中的相反,如何调整顺序一致?

    解决方法:for(i=0;args[i]!='';i=i+4)

        {

            printf("        %x%x%x%x",output[i+3],output[i+2],output[i+1],output[i]);

        }

     

    (五)运行结果

    1、静态库的实现:

     

    2、动态库的实现:注意要将文件libod.so复制到目录/usr/lib中后,再输入“gcc src/main.c -o main -I/头文件所在路径 -Llib lod”才能生成可执行文件main。

     

    3、程序运行结果:

     

    4、Makefile编写:

     

     

    (六)代码实现

    Main.c:

    #include <stdio.h>

    #include <stdlib.h>

    #include "head.h"

    #define N 1000

    #define M 17

    int main(char argv[])

    {

        FILE *fp;

        char args[N],name[N],ch;

        int i=0;

        printf("please input file name:");

        scanf("%s",name);

        //name=argv;

        if((fp=fopen(name,"r"))==NULL)

        {

            printf("ERROR!");

            exit(0);

        }

        while(fgets(args,17,fp))

        {

            tx(args,i++);

            tc(args);

        }

        fclose(fp);

     }

    Tx.c

    void tx(char args[],int j)

    {

        int i;

        char output[N];

        printf("%07o",16*j);

        j++;

        for(i=0;args[i]!='';i++)

        {

            if(args[i]==' ')

                output[i]=' ';

            else

                output[i]=args[i];

        }

        for(i=0;args[i]!='';i=i+4)

        {

            printf("        %x%x%x%x",output[i+3],output[i+2],output[i+1],output[i]);

        }

        printf(" ");

    }

    Tc.c

    #include<stdio.h>

    #include "head.h"

    void tc(char args[])

    {

        int i;  

        printf("       ");

        for(i=0;args[i]!='';i++)

        {

            if(args[i]==' ')

                        printf("\n");

            else

                     printf("%4c",args[i]);

        }

       printf(" ");

    }

    Head.h

    #ifndef _HEAD_20181212_H_

    #define _HEAD_20181212_H_

    void tc(char args[]);

    void tx(char args[],int j);

    #endif

                         作者:20181212滕珠江

  • 相关阅读:
    msyql多个or,and,
    mysql中 where in 用法详解
    history.back(-1)和history.go(-1)的区别
    经典 mysql 28道题
    企业案例(二):增量恢复案例
    企业案例(一):由于mysql sleep线程过多小故障
    mysql数据库恢复
    binlog介绍
    mysql 数据库备份
    docker入门与实践
  • 原文地址:https://www.cnblogs.com/tzj-Lily/p/13796352.html
Copyright © 2020-2023  润新知