Linux I/O编程
一、实验目的:
练习用UNIX I/O进行文件读写的编程方法,用UNIX I/O函数管理文本信息、二进制数据、结构体数据,掌握UNIX I/O的基本编程方法。练习测时函数使用,通过测量UNIX I/O函数运行时间,建立UNIX I/O API函数基本开销的概念。
二、实验内容与要求:
先创建用户家目录下创建文件名为“姓名+学号+04”的子目录,作为本次实验目录,本次实验的所有代码都放到该目录下,要求将所有源代码与数据文件打包成文件”学号-姓名-lab4.tar.gz”, 压缩包与实验报告分别上传到指定目录下。
- 任务1. 在当前用户目录下创建数据文件student.txt,文件的内部信息存储格式为Sname:S#:Sdept:Sage:Ssex,即“姓名:学号:学院:年龄:性别”,每行一条记录,输入不少于10条学生记录,其中包括学生本人记录。调用标准I/O库编写程序task41.c,从文件中查找Sdept字段值为“计算机与网络安全学院”的文本行,输出到文件csStudent.txt中,保存时各字段顺序调整为S#:Sname:Sage: Ssex:Sdept。
提示:从终端读入一个文本行到字符串 char buf[MAXSIZE]可调用函数可调用函数:
“fgets(buf, MAXSIZE, stdin);”,其中stdin是表示键盘输入设备的文件指针。
- 任务2. 调用Unix I/O库函数,编写程序task42.c,从键盘读入5个学生的成绩信息,包括学号、姓名、语文、数学、英语,成绩允许有一位小数,存入一个结构体数组,结构体定义为:
typedef struct _subject { char sno[20]; //学号 char name[20]; //姓名 float chinese; //语文成绩 float math; //数学成绩 float english; //英语成绩 } subject;
将学生信息,逐条记录写入数据文件data,最后读回第1、3、5条学生成绩记录,显示出来,检查读出结果是否正确。
- 任务3(可选):在Linux环境下,可以调用库函数gettimeofday测量一个代码段的执行时间,请写一个程序task43.c,测量read、write、fread、fwrite函数调用所需的执行时间,并与prof/gprof工具测的结果进行对比,看是否基本一致。并对四个函数的运行时间进行对比分析。
提示:由于一次函数调用时间太短,测量误差太多,应测量上述函数多次(如10000次)运行的时间,结果才会准确。
附录:使用prof/gprof测量程序运行时间
Linux/Unix环境提供了prof/gprof工具来收集一个程序各函数的执行次数和占用CPU时间等统计信息,使用prof/gprof工具查找程序性能问题,要求编译命令添加-p选项(prof)或-pg选项(gprof),程序执行时就会产生执行跟踪文件mon.out(或gmon.out),再运行prof(或gprof)程序读取跟踪数据,产生运行报告。现在用gprof对以下程序各函数运行性能(占用CPU时间)进行测量。先输入程序源代码:
$ cat multiply.c #include <stdio.h> int fast_multiply(x, y) { return x * y; } int slow_multiply(x, y) { int i, j, z; for (i = 0, z = 0; i < x; i++) z = z + y; return z; } int main(int argc, char *argv[]) { int i,j; int x,y; for (i = 0; i < 2000; i ++) { for (j = 0; j < 3000 ; j++) { x = fast_multiply(i, j); y = slow_multiply(i, j); } } printf("x=%d, y=%d\n", x, y); return 0; }
然后编译和执行该程序,检查是否函数性能跟踪数据文件gmon.out:
$ gcc -pg -o multiply multiply.c -pg -g
$ ./multiply
x=5995001, y=5995001
$ ls gmon.out
gmon.out
最后,用gprof命令产看各函数执行时间:
$ gprof multiply gmon.out
Flat profile:
Each sample counts as 0.01 seconds.
% cum 24d3e ulative self self total
time seconds seconds calls us/call us/call name
99.44 14.11 14.11 6000000 2.35 2.35 slow_multiply
0.42 14.17 0.06 main
0.14 14.19 0.02 6000000 0.00 0.00 fast_multiply
在这里,slow_multipy和fast_multiply执行600000次所花运行时间为14.11s和0.02秒。
- 任务4:在Linux系统环境下,编写程序task44.c,对一篇英文文章文件的英文单词词频进行统计。
(1)以“单词:次数”格式输出所有单词的词频(必做)
(2)以“单词:次数”格式、按词典序输出各单词的词频(选做)
(3)以“单词:次数”格式输出出现频度最高的10个单词的词频
例如,若某个输入文件内容为:
GNU is an operating system that is free software—that is, it respects users’ freedom.
The development of GNU made it possible to use a computer without software that would trample your freedom.
则输出应该是:
GNU:2
is:3
it:2
……
提示:可以调用字符串处理函数、二叉树处理函数等库函数
三、涉及实验的相关情况介绍(包含使用软件或实验设备等情况):
安装Linux操作系统的计算机
四、报告内容(给出每个任务的要求、设计思想、源代码,后接编译过程、测试数据与运行结果截图)
- 任务一:
源代码:
#include<stdio.h> #include<string.h> #define MAXSIZE 200 int main() { FILE *fp1, *fp2; char buf[MAXSIZE]; char cha[] = "计算机与网络安全学院"; if ((fp1 = fopen("student.txt", "r")) == NULL) { printf("Open Failed!"); } if ((fp2 = fopen("csStudent.txt", "a+")) == NULL) { printf("Open Failed!"); } while (!feof(fp1)) { fgets(buf, MAXSIZE, fp1); if (strstr(buf, cha)) { fputs(buf, fp2); } } fclose(fp1); fclose(fp2); return 0; }
运行结果:
- 任务二:
源代码:
#include<stdio.h> #define N 5 struct _subject { char sno[20]; //学号 char name[20]; //姓名 float chinese; //语文成绩 float math; //数学成绩 float english; //英语成绩 }subject[N], subject2[N]; int main() { FILE *fp; int i; fp = fopen("data.txt", "a+"); for (i = 0; i < N; i++) { printf("该学生的学号为:\n"); scanf("%s", &subject[i].sno); printf("该学生的姓名为:\n"); scanf("%s", &subject[i].name); printf("该学生的语文成绩为:\n"); scanf("%f", &subject[i].chinese); printf("该学生的数学成绩为:\n"); scanf("%f", &subject[i].math); printf("该学生的英语成绩为:\n"); scanf("%f", &subject[i].english); fwrite(&subject[i], sizeof(struct _subject), 1, fp); } fclose(fp); fp = fopen("data.txt", "r"); for (i = 0; i < N; i++) { fread(&subject2[i], sizeof(struct _subject), 1, fp); } for (i = 0; i < N; i = i + 2) { printf("学号:%s 姓名:%s 语文成绩:%.1f 数学成绩:%.1f 英语成绩:%.1f\n", subject2[i].sno, subject2[i].name, subject2[i].chinese, subject2[i].math, subject2[i].english); } return 0; }
运行结果:
- 任务四:
源代码:
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> int main() { int fd,i,j,k,wordsCount=0,wordNum[200],flag1,flag2; char c,temp[20],words[200][20]; fd=open("text44.txt",O_RDONLY,0); for(i=0;i<200;i++) { flag1=0; for(j=0;j<20;j++) { read(fd,&c,sizeof(char)); if((c>=65&&c<=90)||(c>=97&&c<=122)) temp[j]=c; else if(c=='\0') { flag1=2; break; } else { temp[j]='\0'; flag1=1; break; } } if(flag1==2) break; if(flag1==1) { flag2=0; for(k=0;k<wordsCount;k++) { if(strcmp(temp,words[k])==0) { wordNum[k]++; flag2=1; break; } } if(flag2==0) { strcpy(words[wordsCount],temp); wordNum[wordsCount]=1; wordsCount++; } } } printf("输出所有单词的词频:\n"); for(i=0;i<wordsCount;i++) { printf("%s:%d\n",words[i],wordNum[i]); } j=0; for(k=1;k<wordsCount;k++) { if(wordNum[k]>wordNum[j]) j=k; } wordNum[j]=0; printf("输出出现频度最高的10个单词的词频:\n"); for(i=0;i<10;i++) { j=0; for(k=1;k<wordsCount;k++) { if(wordNum[k]>wordNum[j]) j=k; } printf("%s:%d\n",words[j],wordNum[j]); wordNum[j]=0; } }
运行结果:
五、实验分析和总结(任务3要求进行分析)
学会了文件的读取操作.加强了对C语言语法的理解.
- linux下C编程(四)之*p++=*q++
- linux笔记 第六天 bash编程入门之变量、条件判断、条件测试和for循环等
- Linux文件编程实例
- Linux下C语言编程--文件的操作
- Linux串口编程 【转】
- Linux系统进程控制编程(三)——exec函数族的使用
- Linux 下串口编程入门
- Linux/Unix环境编程电子资料汇总
- Linux下串口编程心得
- 基于TCP的服务器端/客户端(二)---------网络编程(Linux----C)
- Linux 驱动 之 模块化编程
- Linux 多线程编程实例
- Linux文件编程之【系统调用】——综合实例:文件拷贝
- Unix/Linux编程之ftok函数用法
- Linux中C语言编程如何使用bool
- Linux管道编程实例
- linux编程之定时器
- Linux Socket编程(不限Linux)
- Linux系统文件I/O编程(二)---文件锁函数
- storysnail的Linux串口编程笔记