1、函数在 C 语言中一个较大的程序往往都是由多个模块构成,好处是:一可以对每个模块单独编制和调试,简化程序。二可由多人同时开发,加快软件的开发速度。三可使程序模块化,一个程序模块可供不同程序使用。四便于扩充软件新功能,即有良好的可维护性和可用性。C 语言往往由多个函数构成,一个或多个函数对应一个功能模块。一:C 程序的模块结构1 一个 C 程序由一个具有固定名称的 main()函数和若干个以标识符命名的其他函数组成。2C 函数是一种独立性很强的程序模块,所有函数处于平等地位,不存在从属关系。3 一个 C 程序中的函数可以集中存放在一个程序文件中,也可以分散在几个程序文件中。4 函数间的逻辑关系是
2、通过函数调用实现的。总是从 main()开始的,当一个函数调用另一个函数时,前一个函数称调用函数,后者为被调用函数。二:函数的定义和调用:函数分:标准库函数:是系统定义的,分别存放在不同文件中,用#include 直接调用。用户自定义函数:用户为解决自己的问题建立的。一)定义:定义的格式也有两种:K int a,int b;c=a*b; int c;return(c) ; c=a*b; return(c );从上可看出:ANSI 格式在形参表中即说明其名称又说明其类型,Kscanf(“%d%d”,c=sum(a,b); 表达式调用printf(“%dn”,c);sum(int x,int y)
3、return (x+y);当程序结束时,子函数 sum 的值 x+y 再返回主函数 main()无返回值的函数不能参加表达式的计算,只能以独立的表达式语句的方式被调用。Void p() printf(“c 2.0n”);main()printf(“Turbo “);p(); 表达式调句调用因为 p()是个无参函数,所以 main()不向 p()传递数据。当一个函数调用另一个函数时,总是先暂停执行自己后边的语句,使程序控制转去执行被调用函数,当被调用函数执行完成后,再由调用函数接收程序控制权,继续执行先有中止后的命令。三)函数的作用域:从作用的位置起,直到源程序文件的未尾。位置靠后的可直接调用前
4、面的函数;前面的函数如调用后面的函数,除 int、char 外,必须进行函数说明后才能调用。函数说明:函数说明的一般形式为:数据类型 函数名(形式参数表 )如:float ff(int x,float y); 有完整的形参说明float ff(int,float); 只说明形参的个数和类型float ff() 不带形参的函数说明对函数作用域的影响:若说明在函数体内,则该函数作用域仅限于调用函数体内说明位置之后;若在函数体内说明,则被说明函数的作用域是从说明处开始直到整个源文件结束。三:用参数传递数据:函数之间的数据联系是通过数据传递实现的。传递的数据即可以是变量的值,也可以是变量的地址。数据传
5、递的方式有:函数返回值、虚实结合、全局变量三种。一)虚实结合的过程和特点。虚实结合适用于所有的有参函数,传递的数据可以是变量、数组、指针、函数等。结合的过程:有参函数在被调用前,形参是没有值的,它的值要在调用时由调用它的函数通过实参传递过来,称为虚实结合。其过程就是调用函数将实参的值复制到被调用函数对应的形参中。实参的值即可是数据,也可是指针。特点:1 形参是一种 auto 型的局部变量,与实参各自占用自己的存储单元,在虚实结合前,形参与实参并无联系,此时形参的值是不确定的,不能引用。2 当函数被调用时,虚实才会结合。这时实参的值被复制到对应的形参中,形参有了初值,但当形参所在的函数运行结束时
6、,形参所占的存储单元将被释放,其值也不复存在。3 在虚实结合中,形参与实参不是靠名称相同来传递数据,而是在对应位置之间传递数据,这就要求形参与实参在数据类型、个数和顺序上一一对应,否则就会出错。二)变量的传递:分值传递和地址传递。值传递:当实参是变量、数组元素或表达式时,对应的形参必须是变量。虚实结合时,实参的值被复制到对应的形参中,形参获得实参的值后就终止与实参的联系。调用结束后,尽管形参的值发生了改变,但不会影响实参的值。这种传递是单向传递。读懂下列程序:main() int x,y,swap(int a,int b);scanf(“%d%d”,printf(“output in main
7、 before calling swap: x=%d,y=%dn”,x,y);swap(x,y); 函数调用printf(“output in main after calling swap: x=%d,y=%dn”,x,y);swap(int a,int b)int t;t=a,a=b,b=t; 变量交换printf(“output in swap:a=%d,b=%dn”,a,b);输出的结果是两次 printf 是一样的,如:123 456地址传递:当实参是变量的地址或指向变量的指针时,对应的形参必须是指针变量。虚实结合时,形参获得实参中的地址值,从而成为指向实参所指向变量的指针,对参形的
8、操作实际上是在实参所指向的存储单元中进行的,因此,形参的改变将导致对应的实参所指向的存储单元发生相同的变化。特点:可以在被调用函数中直接对实参所指的存储单元进行访问和处理,从而实现了数据的双向传递。读懂下列程序:main()int x,y,swap(int *,int *);scanf(“%d%d”,printf(“output in main before calling swap: x=%d,y=%dn”,x,y);swap(printf(“output in main after calling swap: x=%d,y=%dn”,x,y);swap(int *a,int *b)int
9、t;t=*a,*a=*b,*b=t;printf(“output in swap:a=%d,b=%dn”,*a,*b);结果是:两次运行的 printf 输出值正好相反,如:123 456 和 456 123文件文件:是一组相关数据的集合。按内容分为两类:一是程序文件,是源代码,二是数据文件,是程序运行时需要的原始数据及输出的结果。一)文件的逻辑结构:是指按什么形式将一批数据组织成文件。按数据的组织方式,数据文件分:有结构文件和无结构文件。有结构文件又称记录式文件,是以记录为单位来保存数据,每个记录由若干个数据项组成,每个数据项都规定了固定的长度。如数据库文件就是典型的一种。无结构文件又称流式
10、文件,是以字符流或二进制位流的形式保存数据,文件的以字节为单位,输入输出的数据流的开始和结束只受程序控制而不受物理符号的控制。如 C语言使用的就是流式文件。按数据的存储形式,数据文件分文本文件和二进制文件。文本文件也称 ASII 文件,是一种字符流文件,文件由一个个字符首尾相接而成,其中每个字符占 1 个字节,存放的是 ASII 码。如:25612,在内存中以二进制形式存放,占 2 个字节,而在文本文件中,它是以书写形式存放的,占 6 个字节,若要将该数写入文本文件,首先要将内存中 2 字节的二进制数转换成 6 个字符的 ASII 码;若要将该数从文本中写入内存,首先要将这 6 个字符转换成
11、2 字节的二进制数。文本文件优点是可以直接阅读,而 ASCII 码文件易移植,缺点是输入输出都要转换,效率低。二)文件的存取方式:就是读与写的过程。“读”就是将外部介质上的数据输入程序;“写”就是将程序的结果保存在个部介质上。读是使用文件的过程,而写是创建文件的过程,二者统称文件的存取。存取方式:顺序存取和随机存取。顺序存取:只能依先后次序存取文件中的数据,如在流式文件中,存取完第一个字节才能存取第二个字节。随机存取:也称直接存取,可以直接存取文件中指定的数据。如在流式文件中可以直接存取指定的第 I 个字节,不需要管第 I-1 个字节是否存取。可以进行顺序存取的是顺序文件,可以进行随机存取的是
12、随机文件。在顺序文件中,记录的逻辑顺序和物理顺序相同,记录可以不等长,读出某一条记录的速度慢,不能直接对文件进行修改,适宜对文件进行顺序批量处理操作;在随机文件中,每条记录等长,各数据项长度固定,每个记录有唯一的记录号。读写文件时按记录号直接读写指定的记录,适宜于随机读写某条记录的操作。三)文件操作的步骤:C 语言本身不提供文件的操作语句,而是由 C 编译系统以标准库函数的形式提供对文件操作的支持。这些函数都定义在 stdio.h 文件中。步骤一:打开文件。Fopen()函数,需要知道需要打开的文件名,使用文件方式(读、写) ,使用的文件指针。步骤二:文件读写。用文件输入输出函数进行读写。步骤
13、三:关闭文件。Fclose()函数可以关闭。四)文件指针:进行文件操作时用文件指针指向文件中当前操作的位置。当文件指针与某个文件连接后,用户就可以通过文件指针而不是文件名来存取文件了。文件指针是由系统在标题文件 stdio.h 中定义的结构类型,名为 FILE。定义文件指针的格式:FILE *fp1, *fp2;其中 fp1 和 fp2 是文件指针,由 fopen()函数将其指向指定的文件。一个文件指针只能指向一个文件,打开几个文件就有几个文件指针,不允许几个指针同时指向同一个文件。打开文件:格式:FILE *fp;fp=fopen(fname,mode);其中,fname 是要打开的文件名,
14、可以是字符型常量、字符型数组或字符型指针,文件名可以带路径;mode 表示文件的使用方式。文件打开后,fopen()返回是是文件在内存中的起始地址,将该地址赋给文件指针 fp 就建立起文件指针 fp 和文件 fname 之间的连接,即 fp 指向了文件 fname。为确保文件操作的正常进行,有时要检测文件是否正常打开,常用以下程序段来打开文件:if (fp=fopen(“fname”,”w”)= =NULL)printf(“cannot open filen”);exit(1);如果文件不能打开就显示 can not open file,程序终止。如果打开成功程序就往下走。常用文件使用方式说明
15、:w 方式:只能用于向文本文件写数据。若指定的文件不存在,则创建该文件;若存在,则先删除文件中全部内容。文件打开时,文件指针指向文件开头。R 方式:只能用于从文本文件中读数据。若指定的文件不存在,则出现错误信息。A 方式:用于向文件未尾添加数据。若文件存在,则打开并将文件指针指向文件文件未尾,新写入的内容被追加在原有数据之后;若文件不存在,则创建文件,这时指针指向的即是文件头,也是文件尾。R+,w+,a+方式:用于即可读也可写的方式打开文本文件。区别是:R+:用该方式打开文件后,若写入数据,则写入的内容只覆盖新数据需要的空间,其后的原有数据并不丢失。W+:用该方式打开文件后,文件原有的内容全部
16、丢失,只能先向文件写入数据,然后再读出。A+:用该方式打开文件后,将文件内容保留。读时从文件开头读,写时则追加到文件未尾。关闭文件:文件操作完后应用 fclose()关闭,以保证本次文件操作有效。格式:fclose(fp);fp 是由 fopen()函数打开文件时使用的文件指针。如成功,返回 0 值,否则返回非 0 值,文件关闭后,文件指针与文件名断开连接,文件指针可以再与别的文件连接。如下:#includeFILE *fp1, *fp2;Main()fp1=fopen(“text1.txt”,”w”);fp2=fopen(“text2.txt”,”r+”);fclose(fp1);fclos
17、e(fp2);五)文件的读写操作:文本文件和二进制文件使用不同的文件输入输出函数。文本文件读写函数:1、 字符读写函数 fgetc(),getc()和 fputc(),putc()向文本文件写入一个字符函数 fputc()、putc()两者是完全等价的函数,它们都用来向指定的文本文件写入一个字符。格式:fputc(ch,fp);putc(ch,fp);其中 ch 为欲写入的字符,可是字符型常量或变量,fp 为文件指针。如果写入成功,返回所写入的字符,否则返回 EOF。EOF 是 C 编译系统定义的文本文件结束标志,其值为1,十六进值表示为 0xFF。练习:将字符 X,Y,Z 和 EOF 写入
18、A 盘根目录下的文件 ex8-1.txt 中。#includeFILE *fi;Main()if (fi=fopen(“a:ex8-1.txt”,”w”)=NULL)printf(“cannot open filen”);exit(1);fputc(X,fi);fputc(Y,fi);fputc(Z,fi);fputc(0xff,fi);fclose(fi);程序运行时,先以“W”方式打开文件 A 盘根目录下的文件 ex8-1,然后由 fputc()写入XYZ 到文件中,最后写入 EOF 并关闭文件。从文本文件读出一个字符函数 fgetc()和 getc()fgetc()和 getc()也是完
19、全等价的函数。格式:ch=fgetc(fp);ch=getc(fp);功能:从指定的文件读取一个字符,并赋给字符型变量 ch。如果成功,返回读取的字符,如果读取错误或遇到 EOF,则返回 EOF。练习:从上述建立的文件 ex8-1.txt 中读出所有的字符并显示在屏幕上。#includeFILE *fi;Main()char a;int I;if (fi=fopen(“a:ex8-1.txt”,”r”)=NULL)printf(“can not open filen”);exit(1);while (a=fgetc(fi)!=EOF)putchar(a);fclose(fi);运行时,程序用
20、fgetc()读取文件中一个字符赋给变量 a,并将 a 输出到屏幕上,遇到 EOF时终止,而 EOF 将不显示。向文本文件写入字符串函数 fputs():格式:fputs(s,fp);S 是字符型数组名、字符型指针变量或字符串常量。Fp 为文件指针。功能是将字符串s 写入由 fp 指向的文件中,如果成功,返回所写的最后一个字符,否则返回 EOF练习:#includeFILE *fi;Main()char a11=“Beijing”,”shanghai”,”tianjin”,”chongqing”;Int I;If (fi=fopen(“a:ex8-2.txt”,”w”)=NULL)printf
21、(“can not open filen”);Exit(1);For (i=0;iFILE *fi;Main()char a711;Int I;If (fi=fopen(“a:ex8-2.txt”,”r”)=NULL)printf(“can not open filen”);Exit(1);For (i=0;iFILE *f;Main()char pc13=“Liming”,”27516483”,””, “wanglan”,”26348762”, “”;int I;if (f=fopen(“a:ex8_3.txt”,”w”)=NULL)printf(“can not open file”);e
22、xit(1);for (I=0;Imain()FILE *f;char pc1213;int I;if (f=fopen(“a:ex8_3.txt”,”r”)=NULL)printf(“can not open file”);exit(1);for (I=0;I#includeFILE *fp;Main()int sam50,I;If (!(fp=fopen(“a:ex8_4.dat”,”wb”)printf(“can not open filen”);Exit(1);For (i=0;iFILE *IN,*OUT;Main(int argc,char *argv)char ch;If (ar
23、gc!=3)puts(“you forget to enter a file namen”);Exit(0);If (in=fopen(argv1,”rb”)=NULL)puts(“can not open filen”);Exit(0);If (out=fopen(argv2,”wr”)=NULL)puts(“can not open filen”);Exit(0);While(!feof(in)ch=fgetc(in); 读取一个字符If (ferror(in) 读错printf(“read errorn”);Clearerr(in); 清除出错出错标志Exit(1);Else fputc
24、(ch,out); 写入一个字符If (ferror(out) 写错printf(”write errorn”);Clearer(out); 清除出错标志Exit(1);Fclose(in);fclose(out);如果程序起名为 a.c,要拷贝的源文件为 b.dat,目标文件 c.dat,则在 dos 下用下列命令来执行:ca b.dat c.dat六)文件的顺序存取和随机存取顺序存取时必须顺序写入和读出,而随机存取则可以按任意顺序写入和读出,一个文件是适合哪一种存取方式不在于它们是文本文件还是二进制文件,而在于文件中的记录长度是否相等,随机存取要求每个记录的长度必须相等,而顺序存取的记录可相等,也可不等。