MyOD实验(20191211杨守森)

发布时间:2022-07-05 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了MyOD实验(20191211杨守森)脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

 

实验任务

 

1 复习c文件处理内容

 

2 编写myod.c myod XXX实现Linuxod -tx -tc XXX的功能

 

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

 

编写Makefile

 

5 遇到的问题和解决过程

 

(一c语言文件操作

文件的打开与关闭

本节所涉及的文件如无特殊说明均指缓冲文件系统文件,即 ANSI C 标准文件。C 程序中对任何文件进行操作,都必须先“打开”文件,即打开流;操作完成后,需“关闭”文件,即关闭流。

 

这里的“打开”和“关闭”可调用标准库 stdio.h 中的 foPEn 和 fclose 函数实现。

 

打开函数 fopen 的原型如下。

FILE * fopen(char *filename, char *mode);

函数参数:

  1. filename:文件名,包括路径,如果不显式含有路径,则表示当前路径。例如,“D:\F1.txt”表示 D 盘根目录下的文件 f1.txt 文件。“f2.doc”表示当前目录下的文件 f2.doc。
  2. mode:文件打开模式,指出对该文件可进行的操作。常见的打开模式如 “r” 表示只读,“w” 表示只写,“rw” 表示读写,“a” 表示追加写入。更多的打开模式如表 2 所示。

 

 

模式

含 义

说 明

r

只读

文件必须存在,否则打开失败

w

只写

若文件存在,则清除原文件内容后写入;否则,新建文件后写入

a

追加只写

若文件存在,则位置指针移到文件末尾,在文件尾部追加写人,故该方式不 删除原文件数据;若文件不存在,则打开失败

r+

读写

文件必须存在。在只读 r 的基础上加 '+' 表示增加可写的功能。下同

w+

读写

新建一个文件,先向该文件中写人数据,然后可从该文件中读取数据

a+

读写

在” a”模式的基础上,增加可读功能

rb

二进制读

功能同模式”r”,区别:b表示以二进制模式打开。下同

wb

二进制写

功能同模式“w”。二进制模式

ab

二进制追加

功能同模式”a”。二进制模式

rb+

二进制读写

功能同模式"r+”。二进制模式

wb+

二进制读写

功能同模式”w+”。二进制模式

ab+

二进制读写

功能同模式”a+”。二进制模式

 

 

 

返回值:打开成功,返回该文件对应的 FILE 类型的指针;打开失败,返回 NULL。故需定义 FILE 类型的指针变量,保存该函数的返回值。可根据该函数的返回值判断文件打开是否成功。

 

关闭函数 fclose 的原型如下。

int fclose(FILE *fp);

函数参数:

fp:已打开的文件指针。

 

返回值:正常关闭,返回否则返回 EOF(-1)。

文件的顺序读写

换字符输入输出

c 语言中提供了从文件中逐个输入字符及向文件中逐个输出字符的顺序读写函数 fgetc 和 fputc 及调整文件读写位置到文件开始处的函数 rewind。这些函数均在标准输入输出头文件 stdio.h 中。

 

字符输入函数 fgetc 的函数原型为:

int fgetc(FILE *fp);

 

 

函数功能:从文件指针 fp 所指向的文件中输入一个字符。输入成功,返回该字符;已读取到文件末尾,或遇到其他错误,即输入失败,则返回文本文件结束标志 EOF

 

注意:由于 fgetc 是以 unsigned char 的形式从文件中输入(读取)一个字节,并在该字节前面补充若干 0 字节,使之扩展为该系统中的一个 int 型数并返回,而非直接返回 char 型。当输入失败时返回文本文件结束标志 EOF 即 -1,也是整数。故返回类型应为 int 型,而非 char 型。

 

字符输出函数 fputc 的函数原型为:

int fputc (intc,FILE *fp);

函数功能:向 fp 指针所指向的文件中输出字符 c,输出成功,返回该字符;输出失败,则返回 EOF(-1)。

 

文件读写位置复位函数 rewind 的函数原型为:

 

void rewind (FILE *fp);

 

函数功能:把 fp 所指向文件中的读写位置重新调整到文件开始处。

 

接字符串输入输出

 

字符串输入函数 fgets 的函数原型为:

char * fgets (char *s, int size, FILE * fp);

 

函数功能:从 fp 所指向的文件内,读取若干字符(一行字符串),并在其后自动添加字符串结束标志 '' 后,存入 s 所指的缓冲内存空间中(s 可为字符数组名),直到遇到回车换行符或已读取 size-1 个字符或已读到文件结尾为止。该函数读取的字符串最大长度为 size-1。

 

字符串输出函数 fputs 的函数原型为:

int fputs (const char *str, FILE *fp);

 

函数功能:把 str(str 可为字符数组名)所指向的字符串,输出到 fp 所指的文件中。

 

按格式化输入输出

文件操作中的格式化输入输出函数 fscanf 和 fprintf 一定意义上就是 scanf 和 PRintf 的文本版本。程序设计者可根据需要采用多种格式灵活处理各种类型的数据,如整型、字符型、浮点型、字符串、自定义类型等。

 

文件格式化输入函数 fscanf 的函数原型为:

int fscanf (文件指针,格式控制串,输入地址表列);

 

函数功能:从一个文件流中执行格式化输入,当遇到空格或者换行时结束。注意该函数遇到空格时也结束,这是其与 fgets 的区别,fgets 遇到空格不结束。

 

文件格式化输出函数 fprintf 的函数原型为:

int fprintf (文件指针,格式控制串,输出表列);

 

函数功能:把输出表列中的数据按照指定的格式输出到文件中。

 

按二进制方式读写数据块

按块读写数据的函数 fread 和 fwrITe,这两个函数主要应用于对二进制文件的读写操作,不建议在文本文件中使用。书本介绍了 fread 读取二进制文件时,判断是否已经到达文件结尾的函数 feof。

 

数据块读取(输入)函数 fread 的函数原型为:

unsigned fread (void *buf, unsigned size, unsigned count, FILE* fp);

 

函数功能:从 fp 指向的文件中读取 count 个数据块,每个数据块的大小为 size。把读取到的数据块存放到 buf 指针指向的内存空间中。

 

函数参数:

  • buf:指向存放数据块的内存空间,该内存可以是数组空间,也可以是动态分配的内存。void类型指针,故可存放各种类型的数据,包括基本类型及自定义类型等。
  • size:每个数据块所占的字节数
  • count:预读取的数据块最大个数。
  • fp:文件指针,指向所读取的文件。

 

在操作文件时,经常使用 feof 函数来判断是否到达文件结尾。

 

feof 函数的函数原型为:

int feof (FILE * fp);

 

函数功能:检查 fp 所关联文件流中的结束标志是否被置位,如果该文件的结束标志已被置位,返回非 0 值;否则,返回 0。

 

需要注意的是:

1) 在文本文件和二进制文件中,均可使用该函数判断是否到达文件结尾。

 

2) 文件流中的结束标志,是最近一次调用输入等相关函数(如 fgetc、fgets、fread 及 fseek 等)时设置的。只有最近一次操作输入的是非有效数据时,文件结束标志才被置位;否则,均不置位。

 

 

 

(二)学习Linux下的od命令

 

Linux od命令用于输出文件内容。

 

od指令会读取所给予的文件的内容,并将其内容以八进制字码呈现出来。

 

命令格式:

 

od [-A 地址进制] [-t 显示格式] 文件名

 

命令选项:

 

 -t<TYPE>:指定输出格式,格式包括acdfoux,各含义如下:

 

a:具名字符;

 

cASCII字符或者反斜杠;

 

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

 

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

 

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

 

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

 

x[SIZE]:十六进制,SIZE字节为单位以十六进制输出,即输出时一列包含SIZE字节。在默认条件下,以四个字节为一组输出

 

三、实验步骤与结果

 

(一)编写myod.c myod XXX实现Linuxod -tx -tc XXX的功能

 

1.编写函数:

 

20191211yss.h

 

#define _20191211_YSS_H_(不加空格会怎样)

 

void asc(char *p);

 

void hex(char *p);

 

 

 

hex.c

 

#include "20191211yss.h"

 

#include <stdio.h>

 

#include <stdlib.h>

 

void hex(char *p)

 

{

 

FILE *fp;

 

char ch;

 

printf("hex mode:n");

 

if((fp = fopen(p, "r")) == NULL)    {

 

        printf("File open failed!n");

 

       exit(0);

 

    }

 

while(!feof(fp))  

 

{

 

        ch = fgetc(fp);  

 

        if(ch != EOF)

 

{

 

if(ch=='n')

 

printf("n");

 

 

 

else

 

printf("%4x",ch);

 

}

 

}

 

}

 

 

 

asc.c

 

#include "20191211yss.h"

 

#include <stdlib.h>

 

#include <stdio.h>

 

void asc(char *p)

 

{

 

FILE *fp;

 

 char ch;

 

printf("asc mode:n");

 

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

 

  {

 

        printf("File open failed!n");

 

        exit(0);

 

    }

 

while(!feof(fp))

 

    {

 

        ch = fgetc(fp);  

 

if(ch=='n')

 

printf("n");

 

else

 

printf("%4d",ch);

 

}

 

}

 

 

myod.c

 

#include "20191211yss.h"

 

#include <stdio.h>

 

void ;main()

 

{

 

  char Text[50];

 

  printf("Enter textname:");

 

  scanf("%s",Text);

 

   hex(Text);

 

  printf("n"); 

 

asc(Text);

 

}

 

2.新建一个txt文件20191211.txt

 

20191211

 

sensen

 

cat >命令快速编辑文本文件,按CTRl+D退出编辑

 

3.编译并运行

MyOD实验(20191211杨守森)

4.od -tc -tx

MyOD实验(20191211杨守森)

5.结果:通过对比ascii表进行验证,结果正确

 

@H_670_1126@ 00100000 32 20 (Space) 空格 00100001 33 21 !   00100010 34 22 "   00100011 35 23 #   00100100 36 24 $   00100101 37 25 %   00100110 38 26 &   00100111 39 27 '   00101000 40 28 (   00101001 41 29 )   00101010 42 2A *   00101011 43 2B +   00101100 44 2C ,   00101101 45 2D -   00101110 46 2E .   00101111 47 2F /   00110000 48 30 0   00110001 49 31 1   00110010 50 32 2   00110011 51 33 3   00110100 52 34 4   00110101 53 35 5   00110110 54 36 6   00110111 55 37 7   00111000 56 38 8   00111001 57 39 9   00111010 58 3A :   00111011 59 3B ;   00111100 60 3C <   00111101 61 3D =   00111110 62 3E >   00111111 63 3F ?   01000000 64 40 @   01000001 65 41 A   01000010 66 42 B   01000011 67 43 C   01000100 68 44 D   01000101 69 45 E   01000110 70 46 F   01000111 71 47 G   01001000 72 48 H   01001001 73 49 I   01001010 74 4A J   01001011 75 4B K   01001100 76 4C L   01001101 77 4D M   01001110 78 4E N   01001111 79 4F O   01010000 80 50 P   01010001 81 51 Q   01010010 82 52 R   01010011 83 53 S   01010100 84 54 T   01010101 85 55 U   01010110 86 56 V   01010111 87 57 W   01011000 88 58 X   01011001 89 59 Y   01011010 90 5A Z   01011011 91 5B [   01011100 92 5C   01011101 93 5D ]   01011110 94 5E ^   01011111 95 5F _   01100000 96 60 `   01100001 97 61 a   01100010 98 62 b   01100011 99 63 c   01100100 100 64 d   01100101 101 65 e   01100110 102 66 f   01100111 103 67 g   01101000 104 68 h   01101001 105 69 i   01101010 106 6A j   01101011 107 6B k   01101100 108 6C l   01101101 109 6D m   01101110 110 6E n   01101111 111 6F o   01110000 112 70 p   01110001 113 71 q   01110010 114 72 r   01110011 115 73 s   01110100 116 74 t   01110101 117 75 u   01110110 118 76 v   01110111 119 77 w   01111000 120 78 x   01111001 121 79 y   01111010 122 7A z   01111011 123 7B {   01111100 124 7C |   01111101 125 7D }   01111110 126 7E ~   01111111 127 7F DEL (Delete) 删除

 

(二)静态库

MyOD实验(20191211杨守森)

动态库

 

@H_235_2304@

 

 

 

MyOD实验(20191211杨守森)

 

 

 

遇到的问题:建立动态库后,可以看到生成了a.out执行文件,但在执行该文件时弹出了错误提示,发现找不到libmyod.so文件,查找具体原因后,了解原来Linux是通过 /etc/ld.so.cache 文件搜寻要链接的动态库的。而 /etc/ld.so.cache ldconfig 程序读取 /etc/ld.so.conf 文件生成的。(注意, /etc/ld.so.conf 中并不必包含 /lib  /usr/libldconfig程序会自动搜索这两个目录)

如果我们把 libmax.so 所在的路径添加到 /usr/lib中,就可以得到正常的执行结果(注意要用sudo命令)

解决后可以运行得到正确的结果如下:

MyOD实验(20191211杨守森)

 

 

 

 

另一方面我们可以为a.out指定 LD_LIbrARY_PATHLD_LIBRARY_PATH=. ./a.out

 

程序就能正常运行了。LD_LIBRARY_PATH=. 是告诉 a.out,先在当前路径寻找链接的动态库。

 

(三)Makefile

 

先编辑makefile文件,内容如下:

 

testmyod:asc.o hex.o myod.o

 

        gcc asc.o hex.o myod.o -o testmyod

 

asc.o:asc.c 20191211yss.h

 

        gcc -c asc.c -o asc.o

 

hex.o:hex.c 20191211yss.h

 

        gcc -c hex.c -o hex.o

 

myod.o:myod.c 20191211yss.h

 

        gcc -c myod.c myod.o

 

 

 

后用make指令执行文件得到结果:

 

 

MyOD实验(20191211杨守森)

 

 

 四、实验总结

 

1.实验时总是因为编译报错,经常弹出incompatible implicit declaration of built-in function 'exit' ,原因是在写代码头文件大小写没有区分清楚,或者头文件引入错误,比如我在函数中用到了exti0),但实际上它是包含在stdlib中的,需要事先申明之后我需要继续复习巩固C语言相关知识,止出现比较基本的头文件错误。

 

2.编辑动态链接时发现执行文件找不到链接,这时想起来娄老师上课时跟我们讲过文件分类的重要性,像是aso等链接文件应该统一mvlib路径中,另外在静态链接和动态链接都存在的情况下,会优先选择动态链接。

 

3.关于makefile的用法并不是很熟悉,但通过这次实验进行了学习巩固,个人对makefile的理解是一种自动化编辑器,系统会自动识别各个文件之间的关系然后对这些文件进行编译处理,因为文件之间的关系不同,所以不同文件编译顺序也会不同,就编译一个hello.c文件来说,make指令会先将hello.hhello.c编译成为hello.o,同时将main.c编译成为main.o,最后将两个o文件和接口链接形成执行文件hello,具体隶属关系如下图。

 

脚本宝典总结

以上是脚本宝典为你收集整理的MyOD实验(20191211杨守森)全部内容,希望文章能够帮你解决MyOD实验(20191211杨守森)所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。