• 2021-2022-diocs-MyOD


    20191218 2021-2022-diocs-MyOD

    一、任务详情

    1. 复习c文件处理内容
    2. 编写myod.c 用myod XXX实现Linux下od -tx -tc XXX的功能
    3. main与其他分开,制作静态库和动态库
    4. 编写Makefile
    5. 提交测试代码和运行结果截图, 提交调试过程截图,要全屏,包含自己的学号信息
    6. 在博客园发表一篇博客,重点写遇到的问题和解决过程

    二、实践过程

    1. C语言文件操作归纳整理

    C语言的文件处理功能设置缓冲区的文件处理方式:

    当使用标准I/O函数(包含在头文件stdio.h中)时,系统会自动设置缓冲区,并通过数据流来读写文件。当进行文件读取时,不会直接对磁盘进行读取,而是先打开数据流,将磁盘上的文件信息拷贝到缓冲区内,然后程序再从缓冲区中读取所需数据,

    当写入文件时,并不会马上写入磁盘中,而是先写入缓冲区,只有在缓冲区已满或“关闭文件”时,才会将数据写入磁盘

    其余有关内容可参考之前的博客20191218 2021-2022-1-diocs第二周学习笔记

    2. Linux下od命令

    (1)功能

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

    常见的文件为文本文件和二进制文件。od命令主要用来查看保存在二进制文件中的值,按照指定格式解释文件中的数据并输出。
    (2)命令格式

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

    (3)命令选项

    -t<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字节。在默认条件下,以四个字节为一组输出 
    

    3. myod的实现

    本次实践中所涉及代码已上传到码云:第三周代码
    od -tx -tc XXX是先在以十六进制输出XXX文件内容的同时,输出字节对应的ASCII值,它与 od -tx -tc XXX的区别在于输出的次序
    OpenEuler下od -tx -tc hello.c的效果

    代码实现
    我将main函数放在myod.c文件中,剩下需调用的函数放在了myod_func.c文件中,所需的头文件放在myod.h中。
    下面是各部分的代码:
    myod.c

    #include "myod.h"
    
    void main(int argc,char *argv[])
    {
        char str[BUFFERSIZE];
        int num,i,j,i2;
        int fd;
        if((strcmp(argv[1], "-tx")!=0)|(strcmp(argv[2], "-tc")!=0))
        {
            printf("输入格式错误");
            exit(0);
        }
        for(num=0; num<strlen(str); num++)
    		str[num] = '0';
        num = 0;
        if ((fd = open(argv[3], O_RDONLY)) == -1 )
            {
                    perror(argv[3]);
                    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]=='
    ')
                {
                    printf("\n  ");
                }
                else
                {
                    printf("%c 	",str[j]);
                }
            }
            printf("
    ");
    //输出文本
            outputAscii(tx2,Dan,LJ,tx,str);
            if(2==count(&tSY,&Dan,&LJ,&SY,&num))exit(0);
        }
    }
    

    myod_func.c

    #include "myod.h" 
    
    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("字符数太大,超出限制
    ");
            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("
    ");
        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("  	");
            }
            printf("
    ");
    }
    

    myod.h

    #ifndef _MYOD_H_TQH_
    #define _MYOD_H_TQH_
    
    #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[]);
    
    #endif
    

    复习制作静态库和动态库

    • 静态库

      注意在第一次制作静态库时加上-Iinclude链接头文件,生成.a静态库之后可以不需要再加,直接编译即可。
    • 动态库

      注意每次都要加-Iinclude。

    制作myod静态库和动态库

    • 静态库
      tree下的结构图

      用静态库运行myod结果

      可以看到实现了od -tx -tc XXX的要求

    • 动态库

      上面这张截图中我忘记添加-o参数指定输出路径,在当前目录下生成了a.out,下图是修改后的。

      下图是在动态库下的运行结果

    • 问题1:执行的时候不能找到动态库,如下图

      可以发现同静态库、直接用od命令结果一致。

    Makefile
    makefile的存在主要是为了通过提前编写好文件依赖关系的脚本,实现自动化编译运行,提高效率。

    • 制作makefile

    • Makefile练习

      myt实现的功能是:从键盘读入两整数,使用、输出两整数的和。

      尝试使用对myod用makefile

      首先是未在所有出现文件前加上相对路径,只在gcc语句中出现的文件加相对路径,出现了如下提示

      尝试着都加上相对路径

      结果编译报错找不到头文件,一看还是忘了加-Iinclude选项

      加上Iinclude选项后还是出错

      结果查看树形图发现根本没有myod_func.o,之前在编译生成myod.o时已经是把两个文件一起编译成myod.o目标文件了,并且之前存放.o文件的路径也是在lib下

      重新开始,又出现了新的问题

      仔细检查发现是gcc编译的几个参数弄混了,-c对应的才是生成目标文件。

      成功实现用Makefile完成gcc编译。

    解决办法:

    1. 拷贝到系统的库路径下(不推荐)
    2. 修改LD_LIBRARY_PATH环境变量,将库所在的路径添加到环境变量中,用冒号分割。
      假设libfile.so在/root/LProject_20191218TangQiheng中
      export LD_LIBRARY_PATH=//root/LProject_20191218TangQiheng:$LD_LIBRARY_PATH

      教材上演示的也是这种方法。
    3. 修改sudo vi /etc/ld.so.conf,添加库路径在文件中,sudo ldconfig -v (加-v的话是动态显示加载过程,不加也行)
    sudo  vi  /etc/ld.so.conf(在这里面添加路径)
    sudo  ldconfig  -v (加-v的话是动态显示加载过程,不加也行)
    

    然后输入echo $LD_LIBRARY_PATH,会显示用户在/etc/ld.so.conf中添加的路径。

    参考博客Linux中静态库和动态库的制作及发布

    • 问题2
      解决方案:加上-Iinclude参数即可

    • 问题3:在运行生成的可执行文件时出现段错误

      解决方案
      在编译过程忘记加对应参数了……加上-tx -tc xxx就可以正常运行。

  • 相关阅读:
    Alink漫谈(五) : 迭代计算和Superstep
    Alink漫谈(四) : 模型的来龙去脉
    Elasticsearch索引模板-转载
    Filebeat配置文件解析-转载
    Logtash 配置文件解析-转载
    Logtash遇到的异常和注意点
    Linux中Sshd服务配置文件优化版本(/etc/ssh/sshd_config)
    运维应急方案撰写-草稿版分享
    du和df的统计结果为什么会不一样?
    全网最详细的Linux命令系列-Screen远程会话命令
  • 原文地址:https://www.cnblogs.com/20191218tangqiheng/p/15327779.html
Copyright © 2020-2023  润新知