《程序设计教程下清华课件》由会员分享,可在线阅读,更多相关《程序设计教程下清华课件(100页珍藏版)》请在金锄头文库上搜索。
1、 程序设计教程程序设计教程(下下)朱小菲朱小菲 主主 编编清华大学出版社清华大学出版社21世纪高等学校计算机教育实用规划教材世纪高等学校计算机教育实用规划教材第第8章章 函函 数数第9章预处理命令第11章位运算 2第8章 函 数 8.1 函数概述8.2 函数的定义8.3 数据在函数之间的传递8.4 函数的调用8.5数组作为函数的参数8.6指针作为函数的参数8.7 函数与指针8.8函数的嵌套调用8.9 函数的递归调用8.10 变量的作用域8.11变量的存储类别8.12内部函数和外部函数8.13 多个源文件的C程序的连接38.1 函数概述函数概述8.1.1模块化程序设计【例8.1】函数调用简单的例
2、子。#includemain()print_line( );print_message( );print_line( );4void print_line( )printf( = = = = = = = = = = = = = = = = = = = = = = = );void print_message( )printf( n Hello world!n); 58.1.2 C函数的分类函数的分类 (1)库函数【例8.2】使用库函数abs( )求一个整数的绝对值。#includemain() int a,b; printf(please input a data:); scanf(%d,&a
3、); b=abs(a); printf(|%d|=%d,a,b);6(2)自定义函数)自定义函数【例8.3】使用自定义函数myabs( ),求一个整数的绝对值。#includemain() int a,b; printf(please input a data:); scanf(%d,&a); b=myabs(a); printf(|%d|=%d,a,b);myabs(int x) if(b=0) return(x); else return(-x); 7从函数的形式看,可将函数分为有参函数从函数的形式看,可将函数分为有参函数和无参函数两种。和无参函数两种。(1)无参函数(2)有参函数88.2
4、 函数的定义8.2.1无参函数的定义类型标识符类型标识符 函数名函数名( ) 变量声明部分变量声明部分 语句部分语句部分函数首部函数体无参函数定义的一般形式98.2.2有参函数的定义形参表列类型标识符 函数名(类型名1 形参1,类型名2 形参2,类型n,形参n)变量声明部分语句部分函数体函数体函数首部函数首部108.3 数据在函数之间的传递8.3.1形参与实参【例8.4】定义一个求较大数的函数。int max(int x, int y) int z;z=xy? x: y;return (z);main()int a,b;printf(Input two numbers:n);scanf(%d%
5、d,&a,&b);printf(max=%dn,max(a,b); 11【例例8.5】函数参数的值传递方式函数参数的值传递方式#includevoid swap ( int x, int y)int temp;temp = x;x = y; y = temp;printf (in swap: x=%d, y=%dn, x, y);12main ( )int a, b;a=5; b=10; /* 说明两个变量并赋初值 */printf (before swap: a=%d, b=%dn, a, b);swap(a,b);/* 用变量a和b作为实际参数调用函数 */printf (after sw
6、ap: a=%d, b=%dn, a, b);138.3.2函数值的返回1retrurn语句的一般形式:return(表达式);2关于函数的返回值(1)函数的返回值类型一般应与return语句中的表达式值的类型一致,但C语言也允许不一致,这时,以函数类型说明为准,并自动将return语句中表达式的值转换为函数类型。(2)当缺省函数类型说明时,系统默认的返回值类型为int型。14【例例8.6】分析程序的运行结果。分析程序的运行结果。#include float max ( float x, float y )if(xy) return(x);else return(y);main( ) floa
7、t a,b,c;printf(please input two data:);scanf (%f%f,&a,&b);c=max(a,b);printf (MAX is %fn,c); 153无类型函数无类型函数【例8.7】编写程序输出边长为n的菱形,由“*”组成。#include void print_char( );main( ) int i,j,k,n;printf (Enter length:);scanf (%d,&n); /* 输入边长N */ for(i=0;in;i+) print_char(ni, ); /* 输出空格,定位一行中第一个*的位置*/ print_char(2*i
8、+1,*); /* 输出每行的* */ print_char(1,n); /* 输出换行 */ for(i=0;i 0 )printf (%c,ch);178.4 函数的调用函数的调用 8.4.1函数调用的形式和执行过程1函数调用的一般形式函数名(实参表列);2函数调用语句的执行过程(1)首先计算每个实参表达式的值,并把此值传入所对应的形参单元中。(2)执行流程转入函数体,执行函数体中的各语句。(3)函数体执行完之后,返回到主调函数,继续执行主调函数的后续语句。18【例8.8】实参求值顺序举例。#include void main( )int i=1,n; n=f(i,+i);printf(n
9、n=%dn,n);f(int a,int b)int c; if(a=b) c=1; else c=0; return(c); 198.4.2函数调用的方式函数调用的方式 1作为独立语句调用【例8.9】分析程序的执行过程。#include void func1( )printf(*n);printf(Hello World!n);printf(*n);20main( )printf(&n);func1( );printf(&n);21main( )printf(&n);func1( );printf(&n);void func1( )printf(*n);printf(Hello World!
10、n);printf(*n);222作为表达式调用作为表达式调用【例8.10】库函数pow(a,b)的功能是求ab,在主函数中调用该函数。#include #includemain( )int a=3, b=4, i=2, j=1, c;c = pow(a,i) + pow(b,j);printf(c=%d,c);233作为实参作为实参【例8.11】函数调用作为实参形式举例。#include #includemain( )int a=2, b=4, i=1,c;c = pow(a,pow(b,i);printf(c=%d,c);248.4.3对被调用函数的声明和函数原型1函数的声明函数声明的一般
11、格式为:函数类型 函数名(形参类型1 形参名1,形参类型2 形参名2,);【例8.12】对被调函数作声明。#include main() double func(float x1);/*对函数func声明*/float x; double y;x=1.0; y=func(x);printf(y=%fn,y); 25double func(float x1)double y1;y1=2*x1+1.0;return(y1);26【例例8.13】求求s=(1+2+3+n)/(1+2+3+m)的值的值(n、m为整数)。为整数)。#include float sum(int k) /* 定义sum函数。
12、sum函数定义在前,调用在后*/float q=0.0;int i;for(i=1;i0)printf(%4d,x);elseprintf(%2d,0);29main()int a5, i;printf(请输入5个数:n);for(i=0;i5;i+)scanf(%d,&ai);for (i=0;i5;i+)func1(ai);302数组名作为函数参数数组名作为函数参数数组名作函数的参数,遵循以下原则:(1)用数组名作为函数参数时,要求形参和实参是类型相同的数组。(2)要在主调函数和被调函数中分别定义数组。(3)在C语言中,数组名还代表了该数组在内存中的起始地址。当数组名作函数参数 31【例例
13、8.15】数组数组a中存放了一个学生的中存放了一个学生的5门课门课程的成绩,求平均成绩。程的成绩,求平均成绩。float aver(float a,int n)int i ;float av,s=a0;for(i=1;in;i+)s=s+ai;av=s/n;return(av);32main()float sco5, av;int i;printf(n 请输入5门课成绩: n);for(i=0;i5;i+)scanf(%f,&scoi);av=aver(sco,5);printf(平均成绩=%5.2f,av);33【例8.16】判别一个整数数组中各元素的值,若大于0,则输出该值;若小于或等于0
14、,则输出0(用数组名作为函数参数)。void func1(int a,int n) int i ;printf(n 数组a的值是: n);for(i=0;in;i+)if(ai0)ai=0;printf(% 4d,ai); 34main()int b5, i;printf(请输入5个数:n);for(i=0;i5;i+)scanf(%d,&bi);printf(n 数组b初始值是: n);for(i=0;i5;i+)printf(% 4d,bi);func1(b,5);printf(n 数组b终值是: n);for(i=0;i5;i+)printf(% 4d,bi);358.6指针作为函数的参
15、数指针作为函数的参数 8.6.1基本数据类型的指针作函数的参数 【例8.18】若在主函数中变量a=10,b=20,编写一个函数交换主函数中两个变量的值,使变量a=20,b=10。 #includemain ( )void s *x, int *y);int a, b,*p,*q;a=5; b=10; /* 给两个变量赋值 */p=&a;q=&b;36printf (交换前:a=%d,b=%dn, a, b);swap(p, q); printf (交换后:a=%d,b=%dn, a, b);void swap ( int *x, int *y)int temp;/* 借助临时变量交换两个形参变
16、量x和y的值 */temp = *x;*x =*y; *y = temp; 378.6.2指向数组的指针作为函数参数指向数组的指针作为函数参数 【例8.20】用选择法对10个整数按由小到大顺序排序。main()int *p,i,a10;p=a;for(i=0;i10;i+)scanf(%d,p+);p=a;sort(p,10);for(p=a,i=0;i10;i+)printf(%d ,*p);p+; 38sort(int x,int n)int i,j,k,t;for(i=0;in1;i+)k=i;for(j=i+1;jn;j+)if(xjxk) k=j;if(k!=i)t=xi;xi=xk
17、;xk=t;39【例例8.21】用选择法对用选择法对10个整数按由小到大个整数按由小到大顺序排序(使用指针变量作为形参)。顺序排序(使用指针变量作为形参)。main()int *p,i,a10;p=a;for(i=0;i10;i+)scanf(%d,p+);p=a;sort(p,10);for(p=a,i=0;i10;i+)printf(%d ,*p);p+; 40sort(int *x,int n)int i,j,k,t;for(i=0;in1;i+)k=i;for(j=i+1;jn;j+)if(*(x+j)*(x+k) k=j;if(k!=i)t=*(x+i);*(x+i)=*(x+k);
18、*(x+k)=t;418.6.3字符串指针作为函数参数字符串指针作为函数参数 【例8.23】用指针变量实现字符串的复制,同时返回字符串长度。int str_copy(char * str1,char * str2)int k;k=0;while(str1k!=0)str2k=str1k;k=k+1;str2k=0;return(k);42#include main()char str120,str220;int k;printf(输入字符串1:);scanf(%s,str1);printf(str1=%sn,str1);k=str_copy(str1,str2);printf(字符串2=%sn
19、,str2);printf(k=%dn,k);438.7 函数与指针函数与指针 8.7.1用函数指针变量调用函数 指向函数的指针变量定义形式如下:类型标识符类型标识符 (*指针变量名)();指针变量名)();【例8.24】从键盘输入5个整数,找出其中最小值显示出来。#include main()int find_min();int (*fp)();int a5,i,mv; 44for(i=0;i5;i+)scanf(%d,&ai);fp=find_min;mv=(*fp)(a,5);printf(min=%d,mv); int find_min(int a,int n) int m,i;m=a
20、0;for(i=1;iai)m=ai;return(m); 458.7.2用指向函数的指针作为函数参数【例8.25】从键盘输入大于1的正整数n,当n是偶数时,计算1+1/2+1/4+1/n的值;当n是奇数时,计算1+1/3+1/5+1/n的值。 #include main()float peven(int n), podd(int n), dcall(float (*fp)(),int n);float sum;int n;46while(1)scanf(%d,&n);if(n1)break;if(n%2=0)printf(Even=);sum=dcall(peven,n);elseprint
21、f(Odd=);sum=dcall(podd,n);printf(%f,sum);47float peven(int n) float s;int i;s=1;for(i=2;i=n;i+=2)s+=1/(float)i;return(s); float podd(int n) float s;int i;s=0;for(i=1;i=n;i+=2)s+=1/(float)i;return(s); float dcall(float(*fp)(int),int n) float s;s=(*fp)(n);return(s); 488.7.3返回指针值的函数类型名 *函数名(参数表);【例8.26
22、】用户输入一个月份号(如10),程序返回对应月份的英文名(October)。#include char *month_name(int n);main() int n;char *p;printf( 请输入一个月份 n);scanf(%d,&n);p=month_name(n);printf(it is %sn,p); 49char *month_name(int n)static char *name=illegal month, January, February, March, April, May, June,July,August,September,October,November
23、,December;if(n12)return(name0);elsereturn(namen);508.7.4 main函数的参数和返回值【例8.27】编写一个程序,其功能是将若干个字符串连接成一个字符串。要求将要连接的字符串作为命令行参数。#include main(int argc, char *argv) int i;for(i=1;iargc1;i+)strcat(argv1,argvi+1);printf(%sn,argv1);518.8函数的嵌套调用【例8.28】阶乘求和:计算s=1!+2!+3!+n!。long b(int n)/*n个数求和*/int i;long k=0;l
24、ong a(int n);/*被调函数a的声明*/for(i=1;i=n;i+)k=k+a(i);return(k);52long a(int n)/*求n的阶乘*/long c=1;int i;for(i=1;i=n;i+)c=c*i ;return(c);main()int i, n;long s;scanf(%d,&n);s=b(n);printf(ns=%ldn,s);538.9 函数的递归调用函数的递归调用 1直接递归调用2间接递归调用funcl(n) func2(x)int n; int x; int m; int y; . .func2(m); funcl(y); . . 54【
25、例例8.29】从键盘输入一非负整数从键盘输入一非负整数n,并求出,并求出n!的值。的值。#include void main( )int n;long int result;long int fact(int);while(1)printf(Input a number:);scanf(%d,&n);if(n=0) break;result=fact(n);printf(Result=%ld,result); 55long int fact(int n)long int f;if(n=1) f=1;else f=n*fact(n1);return(f);568.10 变量的作用域8.10.1内
26、部变量【例8.30】编写使用内部变量的程序。main()int i=2,j=3,k;k=i+j;if(i=2)int k=8;i=3;printf(%d ,k);printf(%d %dn,i,k);578.10.2 外部变量【例8.31】输入正方体的长、宽、高:l、w、h。求体积及三个面的面积。int s1,s2,s3;int vs( int a,int b,int c)int v;v=a*b*c;s1=a*b;s2=b*c;s3=a*c;return(v);58main()int v,l,w,h;printf(n 请输入长方体的长、宽、高: n);scanf(%d%d%d,&l,&w,&h
27、);v=vs(l,w,h);printf(v=%d s1=%d s2=%d s3=%dn,v,s1,s2,s3);598.11变量的存储类别(1)静态存储变量存储在内存中的静态存储区,在编译时就分配了存储空间,在整个程序运行期间,该变量占有固定的存储单元,程序结束后,这部分空间才释放。这类变量的生存期为整个程序。(2)动态存储变量存储在内存中的动态存储区,在程序运行过程中,只有当变量所在函数被调用时,系统才为该变量分配内存单元,函数调用结束,这部分空间释放。这类变量的生存期仅在函数调用期间。608.11.1自动变量【例8.32】编写一个使用动态存储变量的程序。main( ) int x=1;
28、/* 函数main中的自动变量x */ void func1( ), func2( ); func1( ); func2(x); /* 分别调用函数func1和func2 */printf (x=%dn, x);61void func1(void) int x=3;/* 函数func1中的自动变量x */printf (x=%dt, x);void func2(x)int x; /* 函数f2中的形参x也是自动变量 */ printf (x=%dt, +x); /* x加1 */628.11.2用extern声明外部变量【例8.33】实现两个变量值交换。#include main()exter
29、n int x, y;scanf(%d%d,&x,&y);swap();printf(x=%d, y=%dn,x,y);int x, y;swap() int t;t=x;x=y;y=t;return; 63【例例8.34】两个函数分别存放在两个文件中。两个函数分别存放在两个文件中。/*/int x, y;#include main() scanf(%d%d,&x,&y);swap();printf(x=%d, y=%dn,x,y); /*/extern int x, y;swap() int t;t=x; x=y; y=t;return; 648.11.3静态变量静态变量 【例8.36】下列
30、程序的目的是实现两个变量值交换。/*/static int x, y; /*x与y只是适用于本文件的全局变量*/#include main()scanf(%d%d,&x,&y);swap();printf(x=%d, y=%dn,x,y); /*/extern int x, y;/*实际上x, y没有定义*/swap() int t;t=x; x=y; y=t;return; 658.11.4寄存器变量寄存器变量 【例8.39】求1+2+3+200的和。main()register i,s=0;for(i=1;i=200;i+)s=s+i;printf(s=%dn,s);66第9章 预处理命令
31、 9.1宏定义一一9.2文件包含二二9.3条件编译三三9.4应用程序举例四四679.1宏定义宏定义9.1.1无参数宏定义 #define 标识符标识符 字符串字符串 例如:#define PRICE 100 689.1.2带参数宏定义带参数宏定义 #define 宏名(形参表) 字符串例如:#define PI 3.14159#define Radium(area) sqrt(area/PI)69【例例9.1】计算球体的体积。计算球体的体积。#define PI 3.1415926#define V(r) 4.0/3.0*PI*r*r*rmain()float r,v;printf(Input
32、 a number:n);scanf(%f,&r);v=V(r);printf(r=%fnvolumn=%fn,r,v); 70【例例9.2】分析以下程序的运行结果。分析以下程序的运行结果。#include #define MIN(x,y) (x)(y)?(x):(y)main() int i,j,k;i=10;j=15; k=10*MIN(i,j);printf(k=%dn,k); 71【例例9.3】利用宏定义编写自己的输入输出格利用宏定义编写自己的输入输出格式。式。#define PRI printf#define SC scanf#define NL n#define D %f#defi
33、ne D1 D NL#define D2 D D NLmain() float a,b=4.0,c=5.0;SC(D,&a);PRI(D1,a);PRI(D2,b,c); 729.2 文件包含文件包含 9.2.1文件包含的概念 9.2.2文件包含命令的一般格式 #include 或者或者#include 文件名文件名 例如:#include #include 739.3 条件编译条件编译 1条件编译的三种格式格式一:#if 表达式程序段1#else程序段2#endif或者#if 表达式程序段1#endif74#define MAX 100main()int a=30;float b=12.6;
34、#if MAX99printf(a=%dn,a);#else printf(b=%fn,b);#endifprintf(a=%d,b=%fn,a,b);75格式二格式二#ifdef 标识符程序段1#else程序段2#endif或者#ifdef 标识符程序段1#endif76【例例9.4】分析以下程序中条件编译语句的功分析以下程序中条件编译语句的功能。能。main() float s,r;printf(Input a number:);scanf(%f,&r);#ifdef PIs=2*PI*r;#else#define PI 3.14159s=2*PI*r;#endif printf(s=%f
35、n,s); 77格式三格式三 #ifndef 标识符程序段1#else 程序段2#endif或者#ifndef 标识符程序段1#endif 782条件编译的用途条件编译的用途 便于程序调试 增强程序的可移植性例如,下面的程序段:#define TYPE 2#if TYPE=2#define SIZE 32#else#define SIZE 16#endif799.4应用程序举例【例9.5】编写一个程序:定义一个判断字符是大写字母的宏、一个判断字符是小写字母的宏以及实现大小写字母相互转换的宏,并将用户输入的一个字符串中的大小写字母互换。#include #define isupper(c) (c
36、)=A&(c)=a&(c)=z)#define tolower(c) (isupper(c)?(c)+(aA):(c)#define toupper(c) (islower(c)?(c)(aA):(c) 80main() char s20;int i;printf(Input the string:);scanf(%s,s);for(i=0;si;i+)if(isupper(si)si=tolower(si);else if (islower(si)si=toupper(si);printf(Output the string:%sn,s); 81【例9.6】编写一个程序,用户输入一个字符串,
37、可以原样输出,也可逆向输出,使用条件编译的方法加以控制。#include #define CONVERSEmain()char str50,*p;p=str;printf(Input the string:);scanf(%s,str);printf(Output the string:);82#ifndefCONVERSEprintf(%sn,str); /*原样输出*/#elsep=str+strlen(str)1; /*逆序输出*/while(p=str)printf(%c,*p);printf(n);#endif83第11章 位运算 11.1位运算的概念一一11.2位运算举例二二11.
38、3位段三三8411.1位运算的概念位运算的概念11.1.1 字节与位对于大多数计算机系统而言,字节是由8个更小的叫作“位”的单位组成的,一个位可取0或1。 8511.1.2 位运算符C语言提供了6种位运算符 运算符运算符含义含义运算符运算符含义含义&按位与按位与取反取反|按位或按位或右移右移861按位与运算符按位与运算符&表11.2 按位与真值表b1b2b1&b200001010011187【例例11.1】计算一个给定整数的二进制码中计算一个给定整数的二进制码中1的个数。的个数。int GetOneNumber(unsigned int m)int num=0;while(m!=0)if(m%
39、2=1)num+;m=m/2;return num;882按位或运算符按位或运算符|表11.3 按位或真值表b1b2b1|b2000011101111893按位异或运算符按位异或运算符表13.4 按位异或真值表b1b2b1b2000011101110904取反运算符取反运算符取反运算符是位运算符中唯一的一个单目运算符,它用来对数据的各个二进制位求反,即1变0,0变1。例如053=0324:05300101011 ; 05311010100=0324915左移运算左移运算 a的值a的补码a1a 10101main() unsigned a,b,c; int n; scanf(a=%o,n=%d,
40、&a,&n); b=an; c=c|b; printf(“%on%o”,a,c); 937位运算符与赋值运算符的组合位运算符与赋值运算符的组合-复合赋值复合赋值运算符运算符 &= 例:a &= b 相当于a=a & b |= 例:a |= b 相当于a=a | b = 例:a = b 相当于a=a b = 例:a = b 相当于a=a 5;b=b&15;printf(a=%dtb=%dn,a,b);95【例例11.4】左移运算和逻辑与运算结合示例左移运算和逻辑与运算结合示例. main()char a=a,b=b;int p,c,d;p=a;p=(p8;printf(a=%dnb=%dnc=%
41、dnd=%dn,a,b,c,d);96【例例11.5】写一个函数,计算所使用的系统写一个函数,计算所使用的系统中整型数据的长度中整型数据的长度int intlen()int i=0;unsigned int v=0;while(v!=0)v=v1;i+;return i;97【例例11.6】将十进制数转换为二进制数。将十进制数转换为二进制数。#include int main()int x,i;scanf(%d,&x);for(i=31;i=0;i-) printf(%d,xi&1);system(pause);98【例例11.7】编写一个函数编写一个函数 invert_end(),反,反转一个值中最后转一个值中最后n位,并将结果返回。位,并将结果返回。intinvert_end(int num,int bits) int mask=0; int bitval=1; while(bits- ;0) mask|=bitval; bitval=1; return nummask; 99谢谢 谢谢100