脚本宝典收集整理的这篇文章主要介绍了MyOD实验(20191211杨守森),脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
实验任务:
1 复习c文件处理内容
2 编写myod.c 用myod XXX实现Linux下od -tx -tc XXX的功能
4 编写Makefile
5 遇到的问题和解决过程
文件的打开与关闭
本节所涉及的文件如无特殊说明均指缓冲文件系统文件,即 ANSI C 标准文件。C 程序中对任何文件进行操作,都必须先“打开”文件,即打开流;操作完成后,需“关闭”文件,即关闭流。
这里的“打开”和“关闭”可调用标准库 stdio.h 中的 foPEn 和 fclose 函数实现。
打开函数 fopen 的原型如下。
FILE * fopen(char *filename, char *mode);
函数参数:
模式 |
含 义 |
说 明 |
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 指针指向的内存空间中。
函数参数:
在操作文件时,经常使用 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>:指定输出格式,格式包括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字节。在默认条件下,以四个字节为一组输出
三、实验步骤与结果
(一)编写myod.c 用myod XXX实现Linux下od -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.编译并运行
4.od -tc -tx
5.结果:通过对比ascii表进行验证,结果正确
@H_670_1126@
(二)静态库
动态库
@H_235_2304@
遇到的问题:建立动态库后,可以看到生成了a.out执行文件,但在执行该文件时弹出了错误提示,发现找不到libmyod.so文件,查找具体原因后,了解到原来Linux是通过 /etc/ld.so.cache 文件搜寻要链接的动态库的。而 /etc/ld.so.cache 是 ldconfig 程序读取 /etc/ld.so.conf 文件生成的。(注意, /etc/ld.so.conf 中并不必包含 /lib 和 /usr/lib,ldconfig程序会自动搜索这两个目录)
如果我们把 libmax.so 所在的路径添加到 /usr/lib中,就可以得到正常的执行结果(注意要用sudo命令)
解决后可以运行得到正确的结果如下:
另一方面我们可以为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指令执行文件得到结果:
四、实验总结
1.实验时总是因为编译报错,经常弹出incompatible implicit declaration of built-in function 'exit' ,原因多是在写代码头文件大小写没有区分清楚,或者头文件引入错误,比如我在函数中用到了exti(0),但实际上它是包含在stdlib中的,需要事先申明。之后我需要继续复习巩固C语言相关知识,防止出现比较基本的头文件错误。
2.编辑动态链接时发现执行文件找不到链接,这时想起来娄老师上课时跟我们讲过文件分类的重要性,像是a和so等链接文件应该统一mv到lib路径中,另外在静态链接和动态链接都存在的情况下,会优先选择动态链接。
3.关于makefile的用法并不是很熟悉,但通过这次实验进行了学习巩固,个人对makefile的理解是一种自动化编辑器,系统会自动识别各个文件之间的关系然后对这些文件进行编译处理,因为文件之间的关系不同,所以不同文件编译顺序也会不同,就编译一个hello.c文件来说,make指令会先将hello.hhello.c编译成为hello.o,同时将main.c编译成为main.o,最后将两个o文件和接口链接形成执行文件hello,具体隶属关系如下图。
以上是脚本宝典为你收集整理的MyOD实验(20191211杨守森)全部内容,希望文章能够帮你解决MyOD实验(20191211杨守森)所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。