《C语言程序设计新视角》课件第8章_第1页
《C语言程序设计新视角》课件第8章_第2页
《C语言程序设计新视角》课件第8章_第3页
《C语言程序设计新视角》课件第8章_第4页
《C语言程序设计新视角》课件第8章_第5页
已阅读5页,还剩110页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第8章文件8.1问题的引入 8.2文件的概念 8.3内存和外存的数据交流8.4程序如何操作文件8.5关于文件读写的讨论8.6程序调试与数据测试文件8.7本章小结

【主要内容】

•文件的概念;

•通过人工操作文件与程序操作文件的对比,说明文件操作的基本步骤;

•文件操作库函数的介绍及使用方法实例;

•分类简要介绍可以对文件进行操作的库函数功能。

【学习目标】

•能够创建、读取、写入、更新文件;

•熟悉顺序访问文件处理;

•熟悉随机访问文件处理。

编程的目的是对数据进行处理,完成特定的功能。数据的处理包括数据的输入、加工处理及结果的输出。对程序的运行及测试涉及数据的输入/输出。数据的输入/输出有如下特点:8.1问 题 的 引 入

(1)待处理的数据由程序员编程时在程序中设定(该程序只能处理固定的数据)或在程序运行时由用户输入(每次运行时都要重新输入)。

(2)程序处理的结果输出到显示屏,无法实现永久性的保存。

当处理的数据有下列情形出现时,可把这些数据保存起来,以达到查看方便或可以反复使用的目的。

(1)输入:输入的数据量很大;输入的数据每次都相同。

(2)输出:需要多次查看程序结果;程序结果较多,一屏显示不下。计算机系统长久保存数据的方法是把数据存储到外存上,操作系统以文件为单位对外存的数据进行管理。

文件:存储在外部介质上具有名称(文件名)的一组相关数据的集合。

文件是一组相关数据的有序集合,这个数据集有一个名称,叫做文件名。实际上在前面的各章中我们已经多次使用了文件,例如源程序文件、目标文件、可执行文件、库文件(头文件)等。用文件可长期保存数据,并实现数据共享。8.2文 件 的 概 念在C语言中按内容存放方式,文件可分为二进制文件和文本文件两种。

1.二进制文件

二进制文件是按二进制的编码方式来存放数据的。例如,整数5678的存储形式为0001011000101110,只占两个字节(5678的十六进制为0x162E)。

二进制文件虽然也可在屏幕上显示,但其内容无法读懂。

2.文本文件

文本文件也称为ASCII码文件,这种文件在磁盘中存放时每个字符对应一个字节,用于存放对应的ASCII码。例如,数5678的存储形式如表8.1所示。

表8.1文本文件中的字符表示

ASCII码文件可在屏幕上按字符显示。例如源程序文件就是ASCII码文件,由于是按字符显示,因此我们能读懂文件内容。

文本文件与二进制文件的区别:将文件看做是由一个一个字符组成的,一个字符为一个单位;而二进制文件则是由bit(位)组成的,一个bit为一个单位。

流式文件:C语言将文件看做“数据流”,即文件是由一串连续的、无间隔的字节构

成,用文件结束符结束,这种结构称为“流式文件结构”。

流式文件在处理时不需考虑文件中数据的性质、类型和存放格式,访问时只是以字节为单位对数据进行存取,而将对数据结构的分析、处理等工作都交给后续程序去完成。因此,这样的文件结构更具灵活性,对存储空间的利用率高。

文件结束标志有以下两种:

(1)EOF——文本文件结束标志。EOF是EndofFile的缩写,整型符号常量,在<stdio.h>头文件中定义,它的值通常是-1。

(2)feof函数——用来判断文件是否结束。二进制文件与文本文件均适用。

关于EOF

在程序中测试符号常量EOF,而不是测试-1,这可以使程序更具有可移植性。ANSI标准强调,EOF是负的整型值(但没有必要一定是-1)。因此,在不同的系统中,EOF可能具有不同的值,即输入EOF的按键组合取决于系统,如下表所示。

缓冲文件系统

由于CPU与内存的工作速度非常快,而对外存(磁盘、光盘等)的存取速度很慢,当访问外存时,主机必须等待慢速的外存操作完成后才能继续工作,严重影响了CPU效率的发挥。解决二者速度不匹配的方法是采用“缓冲区”技术。

缓冲读写操作可使磁盘得到高效利用。标准C采用缓冲文件系统,如图8.1所示。8.3内存和外存的数据交流

图8.1缓冲文件系统

缓冲区是在内存中分配的一块存储空间,是由操作系统在每个文件被打开时自动建立并管理的。缓冲区的大小由C的具体版本确定,一般为512字节。

缓冲区的作用:当需要向外存文件中写入数据时,并不是每次都直接写入外存,而是先写入到缓冲区,只有当缓冲区的数据存满或文件关闭时,才自动将缓冲区的数据一次性写入外存。读数时,也是一次将一个数据块读入缓冲区中,以后读取数据时,先到缓冲区中寻找,若找到,则直接读出,否则,再到外存中寻找,找到后将其所在的数据块一次读入缓冲区。缓冲区可有效减少访问外存的次数。

使用缓冲文件系统时,系统将自动为每一个打开的文件建立缓冲区,此后,程序对文件的读写操作实际上是对文件缓冲区的操作。

为了便于编程,ANSIC将有关文件缓冲区的一些信息(如缓冲区对应的文件名、文件所允许的操作方式、缓冲区的大小以及当前读写数据在缓冲区的位置等)用一个结构体类型来描述,类型名为FILE,该结构体类型的定义包含在stdio.h文件中。文件类型FILE描述文件缓冲区的信息,具体内容为:

typedefstruct_iobuf

{

char*_ptr; //指向buffer中第一个未读的字节

int_cnt; //记录剩余未读字节的个数

char*_base; //指向一个字符数组,即这个文件的缓冲区

int_flag; //标志位,记录了FILE结构所代表的打开文件的一些属性

int_file; //用于获取文件描述,可使用fileno函数获得此文件的句柄

int_charbuf; //单字节的缓冲,如果为单字节缓冲,_base将无效

int_bufsiz; //缓冲区大小

char*_tmpfname; //临时文件名

}FILE;有了FILE类型后,每当打开一个文件时,操作系统自动为该文件建立一个FILE类型的结构体数据,并返回指向它的指针,系统将被打开文件及缓冲区的各种信息都存入这个FILE型数据区域中,程序通过上述指针获得文件信息及访问文件,如图8.2所示。

文件关闭后,它的文件结构体被释放。

只要有了指向某个文件的文件指针,具体的文件操作都由系统提供的文件操作函数实现,而不需了解文件缓冲区的具体情况,方便了程序员关于文件操作的编程。

图8.2文件操作

文件通常是驻留在外部介质(如磁盘等)上的,在使用时才调入内存中。

在文件的操作中,经常会涉及文件的读写操作,通常把数据从磁盘流到内存称为“读”,数据从内存流到磁盘称为“写”。

每个文件由唯一的文件名来标识。计算机按文件名对文件进行读、写等有关操作。8.4程序如何操作文件对文件操作的经验是,如果想找存在外部介质上的数据,必须先按文件名找到指定的文件,然后再从该文件中读取数据,文件使用完毕,再关闭它。那么用程序来对文件进行操作,是否也是这样的步骤呢?具体又是怎么处理的呢?用程序来访问文件,与我们直接对文件的操作与步骤是类似的。

程序访问文件的三个步骤如下:

(1)打开文件。

(2)操作文件。

(3)关闭文件。程序对文件的操作步骤如下:

(1)在磁盘上建立、保存文件。

(2)打开已有文件。

(3)读写文件。

在C语言中,没有输入/输出语句,对文件的读写都是用库函数来实现的。ANSI规定了标准输入/输出函数,用它们对文件进行读写,相应的库函数参见附录C。

广义上,操作系统将每一个与主机相连的输入/输出设备都看做是文件,把它们的输入/输出等同于对磁盘文件的读和写。通常把显示器定义为标准输出文件,一般情况下在屏幕上显示有关信息就是向标准输出文件输出。如前面经常使用的printf、putchar函数就是这类输出。

键盘通常被指定为标准输入文件,从键盘上输入就意味着从标准输入文件上输入数据。如scanf、getchar函数就属于这类输入。8.4.1打开文件

打开文件的库函数是fopen。

声明形式:FILEfopen(char*filename,char*mode)

函数功能:在内存中为文件分配一个文件缓冲区。

参数说明:

Filename——字符串,包含欲打开的文件路径及文件名;

Mode——字符串,说明打开文件的模式。

返回值:文件指针(NULL为异常,表示文件未打开)。

特别提示:文件打开后,应检查此操作是否成功,即判断文件指针是否为空(NULL),然后才能决定能否对文件继续访问。

表8.2文件打开模式说明:

(1)打开的文件分文本文件与二进制文件。

(2)文本文件用“t”表示(可省略);二进制文件用“b”表示。

在用户希望保存原有文件内容时,使用模式“w”来打开文件,使得文件的内容丢失而没有任何警告。

用不正确的文件模式来打开文件将导致破坏性的错误。例如,当应该用更新模式“r+”的时候用写入模式“w”打开文件将删除文件内容。

文件的路径

用户在磁盘上寻找文件时,所历经的文件夹线路叫路径。路径分为绝对路径和相对路径。绝对路径是完整的描述文件位置的路径,它是从盘符开始的路径。相对路径是相对于目标位置的路径,是指在当前的目录下开始的路径。

能唯一标识某个磁盘文件的字符串形式为:

盘符:\路径\文件名.扩展名例1:我们要找c:\windows\system\config文件,如果当前在c:\winodws\,则相对路径表示为system\config,绝对路径表示为c:\windows\system\config。

例2:

fp=fopen("a1.txt","r");

表示相对路径,无路径信息,则a1.txt文件在当前目录下(注:此时当前目录为程序所在工程的目录)。

fp=fopen("d:\\qyc\\a1.txt","r")

表示绝对路径,a1.txt在d盘qyc目录下。

注:此处用“\\”是因为在字符串中“\”是要用转义字符表示的。8.4.2关闭文件

关闭文件的库函数是fclose。

声明形式:intfclose(FILE*fp);

函数功能:关闭文件指针指向的文件,将缓冲区数据做相应处理后释放缓冲区。

输出:如果关闭文件出错,函数返回非零值;否则返回0。

特别提示:使用完文件后应及时关闭,否则可能会丢失数据,因为写文件时,只有当缓冲区满时才将数据真正写入文件,若当缓冲区未满时结束程序运行,缓冲区中的数据将会丢失。

【例8-1】文件的例子1。

1 /*对data.txt文件写入10条记录*/

2 #include<stdio.h>

3 intmain()

4 {

5 FILE*fp;/*FILE为文件类型*/

6 inti;

7 intx;

8

9 fp=fopen("data.txt","w"); /*以文本写方式"w"打开data.txt*/

10

11 for(i=1;i<=10;i++)

12 {

13 scanf("%d",&x);

14 fprintf(fp,"%d",x); /*将x输出到fp指向的文件中*/

15 }

16 fclose(fp); /*关闭文件*/

17 return0;

18 }程序结果:程序运行结束,在程序文件所在工程的目录下,可以找到新建的文件data.txt,打开后即可看到程序运行时从键盘输入的10个数据。

文件存储成为二进制还是文本文件取决于fopen的方式。如果用wt,则存储为文本文件,这样用记事本打开就可以正常显示了;如果用wb,则存储为二进制文件,这样用记事本打开有可能会出现小方框,若要正常显示,可以用写字板或UltraEdit等工具打开。8.4.3文件的读写

对文件的读写有系列函数,参见表8.3和表8.4。

表8.3文件读写函数(1)

表8.4文件读写函数(2)特别提示:文件的读写都是在文件的当前位置进行的。所谓当前位置,是指文件的数据读写指针在当前时刻指示的位置。文件打开时,该指针指向文件的开头;一次读写完成后,该指针自动后移(移至本次读写数据的下一个字节)。

【例8-2】文件的例子2。逐个按序读出并显示已有文件file.txt中的字符。

1 /*按序逐个读出文件中的字符*/

2 #include<stdio.h>

3 #include<stdlib.h>

4

5 voidmain()

6 {

7 charch;

8 FILE*fp; /*定义一个文件类型的指针变量fp*/

9 fp=fopen("file.txt","r"); /*以只读方式打开文本文件file.Txt*/

10 if(fp==NULL) /*打开文件失败*/

11 {

12 printf("cannotopenthisfile\n");

13 exit(0); /*库函数exit,终止程序*/

14 }

15 ch=fgetc(fp); /*读出文件中的一个字符,赋给变量ch*/

16 while(ch!=EOF) /*判断文件是否结束,此判断条件等价于(!feof(fp))*/

17 {

18 putchar(ch); /*输出从文件中读出的字符*/

19 ch=fgetc(fp); /*读出文件中的一个字符,赋给变量ch*/

20 }

21 fclose(fp); /*关闭文件*/

22 return0;

23 }

exit函数:在<stdlib.h>中声明,将强制程序结束。在检测到输入错误或者程序无法打开要处理的文件时使用。

exit(0)为正常退出,exit(1),为非正常退出(只要其中的参数不为零)。

C语言中的exit()和return有什么不同?

在主程序main中,语句return(表达式)等价于函数exit(表达式)。但是,函数exit有一个优点,它可以从其他函数中调用,并且可以用查找程序查找这些调用。用exit()函数可以退出程序并将控制权返回给操作系统,而用return语句可以从一个函数中返回并将控制权返回给调用该函数的函数。如果在main()函数中加入return语句,那么在执行这条语句后将退出main()函数并将控制权返回给操作系统,这样的一条return语句和exit()函数的作用是相同的。

【例8-3】文件的例子3。将指定字符串写到文件中;将文件中的字符串读到数

组里。

1 /*将指定字符串写到文件中*/

2 #include<stdio.h>

3 chars="Iamastudent"; /*设定字符串s*/

4 intmain()

5 {

6 chara[100];

7 FILE*fp; /*定义文件指针为fp*/

8 intn=strlen(s); /*计算字符串s的长度*/

9

10 /*以写方式打开文本文件f1.txt*/

11 if((fp=fopen("f1.txt","w"))!=NULL)

12 {

13 fputs(s,fp); /*将s所指的字符串写到fp所指的文件中*/

14 }

15 fclose(fp); /*关闭fp所指向的文件*/

16

17 /*以只读方式打开文本文件f1.txt*/

18 fp=fopen("f1.txt","r");

19 fgets(a,n+1,fp); /*将fp所指的文件中的内容读到a中*/

20 printf("%s\n",a); /*输出a中的内容*/

21 fclose(fp); /*关闭fp所指向的文件*/

22 return0;

23 }说明:第19行语句fgets(a,n+1,fp)是将读出的字符串放入a串中,其中a是已经定义好的字符串,n+1是让fp所指的文件内容依次取n个字符给a,这n个字符恰为s串的内容,之后还要在该串后自动加入一个'\0'字符,因此要写n+1。

【例8-4】文件的例子4。向磁盘写入格式化数据,再从该文件读出显示到屏幕。

1 /*数据成块写入文件*/

2 #include"stdio.h"

3 #include"stdlib.h"

4

5 intmain()

6 {

7 FILE*fp1;

8 inti;

9 structstudent/*定义结构体*/

10 {

11 charname[15];

12 charnum[6];

13 floatscore[2];

14 }stu;

15

16 fp1=fopen("test.txt","wb");

17 if(fp1==NULL) /*以二进制只写方式打开文件*/

18 {

19 printf("cannotopenfile");

20 exit(0);

21 }

22 printf("inputdata:\n");

23 for(i=0;i<2;i++)

24 {

25 /*输入一行记录*/

26 scanf("%s%s%f%f",

27 ,stu.num,&stu.score[0],&stu.score[1]);

28 /*成块写入文件,一次写结构的一行*/

29 fwrite(&stu,sizeof(stu),1,fp1);

30 }

31 fclose(fp1);

32

33 /*重新以二进制只写方式打开文件*/

34 if((fp1=fopen("test.txt","rb"))==NULL)

35 {

36 printf("cannotopenfile");

37 exit(0);

38 }

39 printf("outputfromfile:\n");

40 for(i=0;i<2;i++)

41 {

42 fread(&stu,sizeof(stu),1,fp1); /*从文件成块读*/

43 printf("%s%s%7.2f%7.2f\n", /*显示到屏幕*/

44 ,stu.num,stu.score[0],stu.score[1]);

45 }

46 fclose(fp1);

47 return0;

48 }

程序结果:

inputdata:

xiaowangj00187.598.4

xiaolij00299.589.6

outputfromfile:

xiaowangj00187.5098.40

xiaolij00299.5089.60

把希望的内容写入文件后,查看文件时出现乱码,这往往是文件操作函数要求的文件制式与你写入时打开文件的制式不一致造成的。8.4.4文件位置的确定

确定文件位置的库函数是fseek。

声明形式:fseek(文件类型指针,位移量,起始点位置)

函数功能:重定位文件内部指针的位置。以“起始点位置”为基准,按“位移量”指定字节数做偏移(起始位置值:文件头0,当前位置1,文件尾2)。

返回值:成功返回0;失败返回-1。

【例8-5】文件的例子5。已知stu_list.txt中存放了多个学生的信息,在此文件中读出第二个学生的数据。

程序实现:

1 /*在文件指定位置读取数据——对文件进行随机读写*/

2 #include"stdio.h"

3 #include"stdlib.h"

4

5 structstu/*学生信息结构*/

6 {

7 charname[10];

8 intnum;

9 intage;

10 charaddr[15];

11 }boy,*qPtr;/*定义结构变量boy,结构指针qPtr*/

12

13 intmain()

14 {

15 FILE*fp;

16 charch;

17 inti=1;/*跳过结构的前i行*/

18 qPtr=&boy;/*qPtr指向boy结构体的起始位置*/

19

20 if((fp=fopen("stu_list.txt","rb"))==NULL)

21 {

22 printf("Cannotopenfile!");

23 exit(0);

24 }

25 /*使文件的位置指针重新定位于文件开头*/

26 rewind(fp);

27 /*从文件头开始,向后移动i个结构大小的字节数*/

28 fseek(fp,i*sizeof(structstu),0);

29 /*从fp文件中读出结构的当前行,放到qPtr指向的地址中*/

30 fread(qPtr,sizeof(structstu),1,fp);

31 printf("%st%5d%7d%sn",qPtr->name,

32 qPtr->num,qPtr->age,qPtr->addr);

33 return0;

34 }

(1)有的教材中提到:按文本方式或二进制方式中的某一种方式存储的文件,使用时必须以原来的方式从外存中读出,才能保证数据的正确性。

(2)程序设计错误:把希望的内容写入文件后,查看文件时出现乱码,这往往是文件操作函数要求的文件制式与写入文件时打开文件的制式不一致造成的。8.5关于文件读写的讨论

这究竟是怎么回事呢?

以下按不同的情形来讨论,要点:

(1)在不同文件打开模式(文本、二进制)状态下,文件缓冲区中的数据是否正确。

(2)在不同文件打开模式(文本、二进制)状态下,写入文件中的数据是否显示正常。

【情形一】以fprintf方式向文件data.txt写入数据,以fscanf方式读出data.txt中的数据。

1 /*文件的读写方式*/

2 #include<stdio.h>

3 #include<stdlib.h>

4

5 intmain()

6 {

7 FILE*fp;/*FILE为文件类型*/

8 inti;

9 intx;

10 intb=0;

11

12 fp=fopen("data.txt","wb");/*以"wb"方式打开data.txt文件*/

13

14 if(fp==NULL) /*打开文件失败*/

15 {

16 printf("1:cannotopenthisfile\n");

17 exit(0); /*库函数exit终止程序*/

18 }

19 /****以fprintf格式写入数据*****/

20 for(i=1;i<7;i++)

21 {

22 scanf("%d",&x);

23 fprintf(fp,"%d\n",x);/*将x输出到fp指向的文件中*/

24 }

25 fclose(fp);/*关闭文件*/

26

27 fp=fopen("data.txt","r"); /*以只读方式打开文本文件data.Txt*/

28 if(fp==NULL) /*打开文件失败*/

29 {

30 printf("2:cannotopenthisfile\n");

31 exit(0); /*库函数exit终止程序*/

32 }

33

34 /*********以fscanf方式从文件中读出数据*********/

35 fscanf(fp,"%d",&x); /*读出文件中的一个int型数值给x*/

36 while(!feof(fp)) /*判断文件是否结束*/

37 {

38 printf("%d",x);

39 fscanf(fp,"%d",&x);

40 }

41 fclose(fp);/*关闭文件*/

42 return0;

43 }

程序结果:

输入:234567

输出:234567

【情形二】以fprintf方式向data.txt文件写入数据,以fgetc方式读出data.txt中的数据。

分别用以下灰色框中的语句替代情形一中两个灰色框的语句。

/****以fprintf格式写入数据*****/

for(i=1;i<7;i++)

{

scanf("%d",&x);

fprintf(fp,"%d\n",x); /*将x输出到fp指向的文件中*/

}

/*********以fgetc方式从文件中读出的字符*********/

ch=fgetc(fp); /*读出文件中的一个字符,赋给变量ch*/

while(ch!=EOF) /*判断文件是否结束,此判断条件等价于(!feof(fp))*/

{

putchar(ch); /*输出从文件中读出的字符*/

ch=fgetc(fp); /*读出文件中的一个字符,赋给变量ch*/

}

程序结果:

输入:

234567

输出:

2

3

4

5

6

7

【情形三】以fwrite方式向文件data.txt写入数据,以fread方式读出data.txt中的数据。

分别用以下灰色框中的语句替代情形一中两个灰色框的语句。

/****以fwrite格式写入数据*****/

for(i=1;i<7;i++) /*循环6次,把6个int型数据写入文件*/

{

scanf("%d",&x);

fwrite(&x,sizeof(int),1,fp);/*将x输出到fp指向的文件中*/

}

/****以fread格式读出数据*****/

for(i=1;i<7;i++)

{

fread(&b,sizeof(int),1,fp);

printf("b=%x\n",b);

}

程序结果:

输入:

234567

输出:

b=2

b=3

b=4

b=5

b=6

b=7

查看文件缓冲区。图8.3~图8.8是分别为情形三的调试步骤1~调试步骤6。

图8.3中,创建文件,文件指针fp为0x426af8。

图8.4中,缓冲区_base地址是0x3851f0。

图8.3情形三调试步骤1

图8.4情形三调试步骤2图8.5中,缓冲区_bass中的内容为6个输入的int数据,一个int占4

byte。

图8.6中,以读方式打开文件,fp指针为0x426af8,同前面建立文件时是一样的。注意缓冲区_base地址是0x3851f0,即同前面写文件时也是一样的。

_ptr(指向buffer中第一个未读的字节)指向的是0x3851f4,将要读出的字节值为3。

图8.5情形三调试步骤3图8.6情形三调试步骤4

读与写用的是同一缓冲区。

图8.7中,_ptr指向的是0x3851f8,将要读出的字节值为4。

图8.8中,缓冲区_base地址是0x3851f0,其中的内容也依然未变。

图8.7情形三调试步骤5

图8.8调试步骤6

表8.5for循环相关量的变化表8.5中:

char*_ptr; /*指向buffer中第一个未读的字节*/

int_cnt; /*记录剩余未读字节的个数*/

char*_base; /*指向一个字符数组,即这个文件的缓冲区*/

【情形四】以fprintf方式向文件data.txt写入数据,以fread方式读出data.txt中的数据。省略的程序语句同情形一。

/****以fprintf格式写入数据*****/

for(i=1;i<7;i++)

{

scanf("%d",&x);

fprintf(fp,"%d\n",x);/*将x输出到fp指向的文件中*/

}

/**************以fread方式读出数据***************/

for(i=1;i<4;i++)

{

fread(&b,sizeof(int),1,fp);

printf("b=%x\n",b);

}

程序结果:

输入:

234567

输出:

b=a330a32

b=a350a34

b=a370a36

情形一中,以fprintf方式写入数据,以fscanf方式读出数据;情形四中,以fprintf方式写入数据,以fread方式读出数据。情形一的结果是正常的,为什么情形四的结果看起来就不对了呢?

答:跟踪查看一下便知。

图8.9、图8.10所示分别为情形四的调试步骤1和调试步骤2。

图8.9缓冲区的数据中,

0x0A是'\n'的ASCII码,是语句fprintf(fp,"%d\n",x)中的'\n'产生的,同输入的数字一起写入到文件中。

图8.9情形四调试步骤1图8.10中,用fread(&b,sizeof(int),1,fp)语句读缓冲区中的内容时,是按照sizeof(int)等于4

byte的长度读出并赋给变量b的。所以i=1时,b的值为从0x3851f0开始的4

byte的数值,即为0x0a330a32,对应十进制数为171117106。图8.10情形四调试步骤2总之,无论文件的写入方式、读出方式是文本模式还是二进制模式,程序结果都如表8.6所示,即读写的文件模式不影响程序的结果。

表8.6读写方式与程序结果至于写入data.txt文件的数据是否能正常查看,则与读写的文件模式有关,具体见表8.7。

表8.7data文件的显示结果

(1)在文件缓冲区中的数据形式,与文件读写模式无关;

(2)程序生成的文件是否能正常显示,与文件读写模式有关;

(3)若程序读文件出现数据显示不对,可以通过查看缓冲区数据的格式,选择合适的操作函数。

当我们在设计好算法和程序后,要在调试环境中输入测试数据,查看程序运行的结果。由于调试往往不能一次成功,每次运行时,都要重新输入一遍测试数据,对于有大量输入数据的题目,直接从键盘输入数据需要花费大量时间。

8.6程序调试与数据测试文件我们可以把要输入的数据事先放在文件中,用文件的读函数读入;将程序运行的结果用文件写函数写入指定的文件。可以根据测试数据的特点选用文件读写函数。下面给出两个代码模板。

1.使用fscanf和fprintf函数

【代码模板一】

#include<stdio.h>

intmain()

{

FILE*fp1,*fp2;

fp1=fopen("data.in","r"); /*以只读方式打开输入文件data.in*/

fp2=fopen("data.out","w"); /*以写方式打开输出文件data.out*/

/*中间按原样写代码,把scanf改为fscanf,printf改为fprintf即可*/

fclose(fp1);

fclose(fp2);

return0;

}

2.使用freopen函数

声明形式:FILE*freopen(constchar*path,constchar*mode,FILE*stream);

参数说明:

path——文件名,用于存储输入/输出的自定义文件名;

mode——文件打开的模式,和fopen中的模式(如r为只读,w为写)相同;

stream——一个文件,通常使用标准流文件。

功能:实现重定向,把预定义的标准流文件定向到由path指定的文件中。返回值:成功,返回一个path所指定文件的指针;失败,返回NULL。(一般不使用它的返回值。)

标准流文件

启动一个C语言程序时,操作系统环境负责打开3个文件,并将这3个文件的指针提供给该程序。这3个文件指针分别为标准输入stdin、标准输出stdout和标准错误stderr。它们在<stdio.h>中声明,其中:

stdin:标准输入流,默认为键盘输入;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论