1、2022-8-251C语言程序设计 第1章 C语言程序设计基础C2C语言程序设计 第4章 数 组C3第第第第第第4 4 4 4 4 4章章章章章章 数数数数数数 组组组组组组C语言程序设计 第4章 数 组C2022-8-2542022-8-255类型说明符类型说明符 数组名数组名 常量表达式常量表达式2022-8-256(1)数组名是标识符,它遵循标识符的命名规则。例如:)数组名是标识符,它遵循标识符的命名规则。例如:int a8;(2)数组名后的常量表达式一定要用方括号括起来,不能用圆括号)数组名后的常量表达式一定要用方括号括起来,不能用圆括号或其他形式的括号。例如下例不合法:或其他形式的括
2、号。例如下例不合法:int a(6);(3)常量表达式用来规定数组元素的数目,即数组的长度。)常量表达式用来规定数组元素的数目,即数组的长度。一个数组所占用长度一个数组所占用长度=数组类型长度数组类型长度*数组长度。例如:数组长度。例如:int a5;在在a5中,中,5表示数组表示数组a有有5个元素,下标从个元素,下标从0开始,数组元素分别是:开始,数组元素分别是:a0,a1,a2,a3,a4。数组被定义为整型,每个数组元素占两。数组被定义为整型,每个数组元素占两个字节,因此该数组在内存中占用个字节,因此该数组在内存中占用10字节的连续空间。字节的连续空间。(4)常量表达式中可以包括常量和符号
3、常量,不能包含变量。也就)常量表达式中可以包括常量和符号常量,不能包含变量。也就是说是说C语言不允许对数组的大小做动态定义。语言不允许对数组的大小做动态定义。例如下例不合法:例如下例不合法:int an;2022-8-257score0score1score2score3score491.534.567.572.084.0低地址低地址高地址高地址score数组数组2022-8-258初始化:在定义数组时给数组元素赋初值。初始化:在定义数组时给数组元素赋初值。1在定义数组时,对全部数组元素赋初值在定义数组时,对全部数组元素赋初值 例如:例如:int a5=0,1,2,3,4;此时可以省略数组长度
4、,例如:此时可以省略数组长度,例如:int a=0,1,2,3,4;2在定义数组时,对部分数组元素赋初值在定义数组时,对部分数组元素赋初值 例如:例如:int a5=1,2,3;系统为其余元素赋系统为其余元素赋 0。3当初值的个数多于数组元素的个数时,编译出错当初值的个数多于数组元素的个数时,编译出错 例如:例如:int a5=0,1,2,3,4,5;2022-8-2592022-8-2510(1)数组必须先定义,然后使用。)数组必须先定义,然后使用。(2)只能逐个引用数组元素,不能一次引)只能逐个引用数组元素,不能一次引用整个数组。用整个数组。(3)引用数组元素,下标不可越界,否则)引用数组
5、元素,下标不可越界,否则会造成程序溢出错误,严重时甚至会对操作会造成程序溢出错误,严重时甚至会对操作系统造成破坏引起系统崩溃。系统造成破坏引起系统崩溃。2022-8-25112022-8-25122022-8-2513输入数组a的各个元素for(i=1;i=9;i+)min=ifor(j=i+1;jaiT Fmin=j交换amin和ai输出已经排序的10个数2022-8-25142022-8-2515数据类型数据类型 数组名常量表达式数组名常量表达式1常量表达式常量表达式2的定义的定义2022-8-2516x00 x01x02x10 x11x12元素元素的的2022-8-2517x0是数组名,
6、是元素是数组名,是元素x00的地址的地址x1是数组名,是数组名,是元素是元素x10的地址的地址二维数组可看作是一种特殊的一维数组二维数组可看作是一种特殊的一维数组2022-8-2518例例:int a23=1,2,3,4,5,6;例:例:int a23=1,4;初始化后结果:初始化后结果:1 0 0 4 0 02022-8-25192022-8-25202022-8-2521a34=3;/*下标越界下标越界*/a1,2=1;/*应写成应写成 a12=1;*/例:例:int a34;a00=3;a01=a00+10;2022-8-2522main()int a44,sum=0;int i,j;p
7、rintf(请输入矩阵元素请输入矩阵元素:n);for(i=0;i4;i+)for(j=0;j4;j+)scanf(%d,&aij);/*输入矩阵元素输入矩阵元素*/for(i=0;i4;i+)sum=sum+aii;/*对矩阵元素对角线元素求和对矩阵元素对角线元素求和*/printf(矩阵对角线元素之和矩阵对角线元素之和:%d,sum);2022-8-25232022-8-252411 21 2 11 3 3 11 4 6 4 15 5 10 10 12022-8-25252022-8-25264.3 字符数组与字符串字符数组与字符串基本概念基本概念不是字符串不是字符串2022-8-2527
8、2022-8-2528 不是字符串不是字符串BEIJING0002022-8-2529 不是字符串不是字符串BEIJING0002022-8-2530 思考:哪个数组存放的是字符串思考:哪个数组存放的是字符串2022-8-2531 2022-8-2532【例例4.9】输出一个等腰三角形图形。输出一个等腰三角形图形。字符数组的引用与整型数组的引用形式相同,采用下标字符数组的引用与整型数组的引用形式相同,采用下标引用,即引用,即数组名数组名 下标下标 *2022-8-2533main()char a59=,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,
9、*,*;int i,j;for(i=0;i5;i+)for(j=0;j0)printf(s1s2);else printf(s1 y?x:y;return(z);int max(x,y)int x,y;或或int max(int x,y)或或int max(x,y)int x,y,z;z=x y?x:y;return(z);形参也可以这样定义形参也可以这样定义 2022-8-2553函数名(函数名(实际参数表实际参数表)在在C语言中,把函数调用也作为一个表达式。语言中,把函数调用也作为一个表达式。因此凡是表达式可以出现的地方都可以出现函数因此凡是表达式可以出现的地方都可以出现函数调用。例如:调
10、用。例如:welcome();if(iabs(a)max)max=iabs(a);m=max(c,max(a,b);函数调用的一般形式:函数调用的一般形式:2022-8-25542022-8-2555程序输出结果:程序输出结果:7,6,6,7 2022-8-25562022-8-2557编程如下:编程如下:void main()int n;printf(input numbern);scanf(%d,&n);s(n);printf(n=%dn,n);int s(int n)int i;for(i=n-1;i=1;i-)n=n+i;printf(n=%dn,n);input number100n
11、=5050n=100形式参数(形参)形式参数(形参)例例5.3】本例题中实参将值传递给形参,形参值改变不影响实参值。本例题中实参将值传递给形参,形参值改变不影响实参值。2022-8-2558 当函数被调用时才给形参分配内存单元。调用结当函数被调用时才给形参分配内存单元。调用结束,所占内存被释放。束,所占内存被释放。实参可以是常量、变量或表达式,但要求它们有实参可以是常量、变量或表达式,但要求它们有确定的值。确定的值。实参与形参类型要一致,字符型与整型可以兼容实参与形参类型要一致,字符型与整型可以兼容。实参与形参的个数必须相等。在函数调用时,实实参与形参的个数必须相等。在函数调用时,实参的值赋给
12、与之相对应的形参。参的值赋给与之相对应的形参。“单向值传递单向值传递”。2022-8-2559函数的返回值是通过函数的返回值是通过return语句带回到主调函数的语句带回到主调函数的如果不一致,系统自动将表达式类型转如果不一致,系统自动将表达式类型转换为函数类型换为函数类型2022-8-2560void swap(int x,int y)main()swap(a,b);2022-8-2561函数类型函数类型 函数名(函数名(参数类型参数类型1 1 参数名参数名1 1,);或或 函数类型函数类型 函数名(函数名(参数类型参数类型1 1,参数类型参数类型2 2,);第二种形式省略了参数名,此种形式
13、也称为第二种形式省略了参数名,此种形式也称为函数的原型函数的原型。2022-8-25625.3.1 函数的嵌套调用函数的嵌套调用2022-8-2563运行结果:运行结果:s=3629042022-8-25645.3.2 函数的递归调用函数的递归调用1递归的基本概念递归的基本概念递归调用递归调用:一个函数直接或间接地调用了它本身:一个函数直接或间接地调用了它本身,就称为函数的递归调用。,就称为函数的递归调用。递归函数递归函数:在函数体内调用该函数本身。:在函数体内调用该函数本身。int f(int x)int y;z=f(y);return z;例如:例如:直接调用直接调用f函数本身函数本身“从
14、前有一座山,山里有一座庙,庙里有一个老和尚,从前有一座山他在讲故事,讲的是什么呢?”这个故事就是递归的逻辑思想,在现实生活中老和尚讲累了或者到吃饭时候不讲就结束了。2022-8-2565【例例5.5】利用函数递归调用求利用函数递归调用求3!思路思路:以求:以求4的阶乘为例的阶乘为例:4!=4*3!,3!=3*2!,2!=2*1!,1!=1,0!=1。递归结束条件递归结束条件:当:当n=1或或n=0时,时,n!=1。递归公式:递归公式:2022-8-2566#includelong f(int n)if(n=1)return 1;elsereturn n*f(n-1);main()int x;s
15、canf(%d,&x);printf(%ld,f(x);运行情况如下:运行情况如下:67202022-8-2567 回回 推推main()fact(4)fact(3)fact(2)fact(1)y=fact(4);f=4*fact(3);f=3*fact(2);f=2*fact(1);f=1;return 24 return 6 return 2 return 1 递递 推推 2022-8-25682022-8-25692022-8-25702022-8-25712022-8-25722022-8-25732022-8-2574变量的作用域变量的作用域5.5.1 局部变量局部变量变量的作用域变
16、量的作用域:变量在程序中可以被使用的范围。:变量在程序中可以被使用的范围。根据变量的作用域可以将变量分为根据变量的作用域可以将变量分为局部变量和全局局部变量和全局变量。变量。局部变量(局部变量():在:在函数内函数内或或复合语句内复合语句内定定义的变量以及义的变量以及。作用域作用域:函数内或复合语句内。:函数内或复合语句内。2022-8-2575void sub(int a,int b)int c;a=a+b;b=b+a;c=b-a;printf(sub:ta=%d b=%d c=%dn,a,b,c);main()int a=1,b=1,c=1;printf(main:ta=%d b=%d c
17、=%dn,a,b,c);sub(a,b);printf(main:ta=%d b=%d c=%dn,a,b,c);int a=2,b=2;printf(comp:ta=%d b=%d c=%dn,a,b,c);printf(main:ta=%d b=%d c=%dn,a,b,c);“分程序分程序”或或“程序块程序块”程序输出结果:程序输出结果:main:a=1 b=1 c=1sub:a=2 b=3 c=1main:a=1 b=1 c=1comp:a=2 b=2 c=1main:a=1 b=1 c=12022-8-25765.5.2 全局变量全局变量全局变量全局变量():在):在函数外部函数外部
18、定义的定义的变量。变量。作用域作用域:。如在其作用域内的函数或分程序中定。如在其作用域内的函数或分程序中定义了同名局部变量,则在局部变量的作用域义了同名局部变量,则在局部变量的作用域内,同名全局变量暂时不起作用。内,同名全局变量暂时不起作用。2022-8-2577int a=5;void f(int x,int y)int b,c;b=a+x;c=a-y;printf(%dt%dt%dn,a,b,c);main()int b=6,c=7;f(b,c);printf(%dt%dt%dn,a,b,c);int a=9,b=8;printf(%dt%dt%dn,a,b,c);c=10;printf(
19、%dt%dt%dn,a,b,c);printf(%dt%dt%dn,a,b,c);printf(%dt%dt%dn,a,b,c);程序输出结果:程序输出结果:5 11 -25 6 79 8 79 8 109 8 105 6 10全局变量全局变量2022-8-25785.5.3 变量的存储方式变量的存储方式变量的属性2022-8-2579变量的完整声明一般形式为:变量的完整声明一般形式为:1自动变量(自动变量(auto类别)类别)局部变量可以定义为自动变量。局部变量可以定义为自动变量。main()int x,y;main()auto int x,y;等价等价可省2022-8-25802022-8
20、-2581【例例5.12】求求1+2+3+500的和。的和。main()register i,s=0;for(i=1;i p1、p2=p1。指针与一个整型数据进行比较是没有意指针与一个整型数据进行比较是没有意义的义的。不同类型指针变量之间比较是非法的不同类型指针变量之间比较是非法的。NULL可以与任何类型指针进行可以与任何类型指针进行=、!=的关系运算,用于判断指针是否为空指针的关系运算,用于判断指针是否为空指针。2022-8-251042022-8-251052022-8-251062022-8-25107a a000123a a4442022-8-251082022-8-251092022
21、-8-251102022-8-251112022-8-25112程序的输出结果913 17 213 19 -202022-8-25113【例例6.14】用字符数组存放一个字符串。用字符数组存放一个字符串。main()char string=I love China!;printf(%sn,string);运行程序,输出结果:运行程序,输出结果:I love China!2022-8-25114【例例6.15】用字符串指针指向一个字符串。用字符串指针指向一个字符串。main()char*string=I love China!;printf(%sn,string);2022-8-25115202
22、2-8-251162022-8-251172022-8-251182022-8-251192022-8-251202022-8-25121指针作为函数参数的作用是将一个变量的地址传指针作为函数参数的作用是将一个变量的地址传送到另一个函数中。送到另一个函数中。2022-8-251222022-8-251232022-8-251242022-8-251252022-8-251262022-8-251272022-8-251282022-8-251292022-8-251302022-8-25131C语言程序设计 第第7章章 预预处处理理命命令令C2022-8-251327.1 预处理命令简介预处理
23、命令简介7.2宏定义宏定义7.3文件包含文件包含7.4条件编译条件编译7.5小结及常见错误列举小结及常见错误列举语言程序设计 第七章 预处理命令C本章主要内容2022-8-25133本章主要内容:本章主要内容:1.学习和掌握学习和掌握C语言提供的多种预处理命令功能,语言提供的多种预处理命令功能,如如宏定义、宏定义、文件包含、条件编译等。文件包含、条件编译等。2.合理地使用预处理功能编写的程序便于合理地使用预处理功能编写的程序便于阅读、修改、阅读、修改、移植和调试,移植和调试,也有利于模块化程序设计。也有利于模块化程序设计。语言程序设计 第七章 预处理命令C2022-8-25134 7.1 预处
24、理命令简介预处理命令简介语言程序设计 第七章 预处理命令C宏定义宏定义文件包含文件包含条件编译条件编译 C语言提供的预处理功能主要包含三种语言提供的预处理功能主要包含三种 这三种功能分别使用宏定义命令、文件包含命这三种功能分别使用宏定义命令、文件包含命令和条件编译命令来实现。预处理命令之所以令和条件编译命令来实现。预处理命令之所以都是以都是以“#”开头的目的是为了与其他开头的目的是为了与其他C语句进语句进行行 区别。区别。命令的实现和注意命令的实现和注意2022-8-25135 7.2宏定义宏定义语言程序设计 第七章 预处理命令C7.2.1不带参数的宏定义不带参数的宏定义 1.定义格式定义格式
25、 2.应引起注意的问题应引起注意的问题 3.关于不带参数宏的其他用法关于不带参数宏的其他用法7.2.2带参数的宏定义带参数的宏定义 1.定义格式定义格式 2.应引起注意的问题应引起注意的问题2022-8-25136 不带参数宏的宏名后没有参数。不带参数宏的宏名后没有参数。语言程序设计 第七章 预处理命令C7.2.1不带参数的宏定义不带参数的宏定义 1.定义格式定义格式 其定义的一般形式为:其定义的一般形式为:#define 标识符标识符 字符串字符串 其中的其中的“#”表示这是一条预处理命令。凡是以表示这是一条预处理命令。凡是以“#”开头的均开头的均为预为预 处理命令。处理命令。“define
26、”为宏定义命令。为宏定义命令。“标识符标识符”为所定义为所定义的宏名。的宏名。“字符串字符串”不加双引号,它可以是常数、表达式、格式串不加双引号,它可以是常数、表达式、格式串等。等。例如:例如:#define PI 3.14159 2022-8-25137语言程序设计 第七章 预处理命令C 2.应引起注意的问题应引起注意的问题 在宏定义中表达式在宏定义中表达式(y*y+3*y)两边的括号不能少。否则会发生两边的括号不能少。否则会发生错错 误。误。宏定义是用宏名来表示一个字符串,在宏展开时又以该字符宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取串取 代宏名,这只是一种简单的代换,字符串
27、中可以含任何字符,代宏名,这只是一种简单的代换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程序对它不作任何检查。如有可以是常数,也可以是表达式,预处理程序对它不作任何检查。如有错误,只能在编译已被宏展开后的源程序时发现。错误,只能在编译已被宏展开后的源程序时发现。宏定义不是说明或语句,在行末尾不应加分号,如加上分号宏定义不是说明或语句,在行末尾不应加分号,如加上分号则连分号也一起置换。则连分号也一起置换。宏定义必须写在函数之外,其作用域从宏定义命令起到源程序宏定义必须写在函数之外,其作用域从宏定义命令起到源程序结结 束束。如要终止其作用域可使用如要终止其作用域可使用#undef
28、命令。命令。宏名习惯上用大写字母表示,以便于与变量区别。宏名习惯上用大写字母表示,以便于与变量区别。宏名在源程序中若用引号括起来,则预处理程序不对其作宏代宏名在源程序中若用引号括起来,则预处理程序不对其作宏代换。换。2022-8-25138语言程序设计 第七章 预处理命令C 3.关于不带参数宏的其他用法关于不带参数宏的其他用法 (1)在在C语言中也经常使用宏定义来表示数据类型,使书写方便,语言中也经常使用宏定义来表示数据类型,使书写方便,易于理易于理解。解。例如:例如:#define STU struct stu 则在程序中可用则在程序中可用STU作变量说明:作变量说明:STU student
29、5,*p;#define INTEGER int 在程序中即可用在程序中即可用INTEGER作整型变量说明:作整型变量说明:INTEGER a,b,s;但应注意用宏定义表示数据类型和用但应注意用宏定义表示数据类型和用typedef定义数据说明符的区别定义数据说明符的区别 (2)对对“输出格式输出格式”作宏定义,可以大大减化书写。作宏定义,可以大大减化书写。2022-8-25139语言允许宏带有参数。在宏定义中的参数被称为形式参数,在宏调语言允许宏带有参数。在宏定义中的参数被称为形式参数,在宏调用中的参数被称为实际参数。带参数的宏定义不是进行简单的字符串用中的参数被称为实际参数。带参数的宏定义不
30、是进行简单的字符串替换,还要进行参数的替换,也就是在调用过程中进行宏展开时,用替换,还要进行参数的替换,也就是在调用过程中进行宏展开时,用实参去替换形参。实参去替换形参。语言程序设计 第七章 预处理命令C7.2.2带参数的宏定义带参数的宏定义 1.定义格式定义格式 带参宏定义的一般形式为:带参宏定义的一般形式为:#define 标识符标识符(形参表形参表)字符串字符串;带参宏调用的一般形式为:标识符带参宏调用的一般形式为:标识符(实参表实参表);其中标识符就是宏名。其中标识符就是宏名。例如:例如:#define PI 3.14159 /*宏定义宏定义*/#define S(r)PI*(r)*(
31、r)area=S(10);2022-8-25140语言程序设计 第七章 预处理命令C 2.应引起注意的问题应引起注意的问题 带参宏定义中,宏名和形参表之间不能有空格出现。带参宏定义中,宏名和形参表之间不能有空格出现。在带参宏定义中,形参与实参可以使用不同的名字来表示,形在带参宏定义中,形参与实参可以使用不同的名字来表示,形式参数不分配内存单元,因此不必作类型定义。而宏调用中的实参有式参数不分配内存单元,因此不必作类型定义。而宏调用中的实参有具体的值。要用它们去代换形参,因此必须作类型说明。这是与函数具体的值。要用它们去代换形参,因此必须作类型说明。这是与函数中的情况不同的。在函数中,形参和实参
32、是两个不同的量,各有自己中的情况不同的。在函数中,形参和实参是两个不同的量,各有自己的作用域,调用时要把实参值赋予形参,进行的作用域,调用时要把实参值赋予形参,进行“值传递值传递”。而在带参。而在带参宏中,只是符号代换,不存在值传递的问题宏中,只是符号代换,不存在值传递的问题。之前说过,对于带参宏的展开,只是将实参作为字符串,进行之前说过,对于带参宏的展开,只是将实参作为字符串,进行简单的字符串替换来代替形参,这与函数的调用也是不同的,在这个简单的字符串替换来代替形参,这与函数的调用也是不同的,在这个过程中并不做语法检查,因此用户就更应该注意宏展开后的正确性。过程中并不做语法检查,因此用户就更
33、应该注意宏展开后的正确性。在宏定义中的形参是标识符,而宏调用中的实参可以是表达式。在宏定义中的形参是标识符,而宏调用中的实参可以是表达式。带参的宏和带参函数很相似,但有本质上的不同,除上面已谈带参的宏和带参函数很相似,但有本质上的不同,除上面已谈到的几点外,把同一表达式用函数处理与用宏处理两者的结果有可能到的几点外,把同一表达式用函数处理与用宏处理两者的结果有可能是不同的。是不同的。2022-8-25141 7.3文件包含文件包含 语言程序设计 第七章 预处理命令C 1.命令格式命令格式 文件包含命令的一般形式有两种。文件包含命令的一般形式有两种。格式一:格式一:#include文件名文件名
34、格式二:格式二:#include 2.命令功能命令功能 文件包含命令的功能是把指定的文件插入该命令行位文件包含命令的功能是把指定的文件插入该命令行位 置取代该命令置取代该命令 行,从而把指定的文件和当前的源程序文件连成一个源文件。通常情况行,从而把指定的文件和当前的源程序文件连成一个源文件。通常情况下被包含的文件总用在一个文件的头部,将这样的文件称为下被包含的文件总用在一个文件的头部,将这样的文件称为“标题文件标题文件”或是或是“头文件头文件”,常以,常以“h”为后缀,也就是头(为后缀,也就是头(head)的缩写。当然,)的缩写。当然,不用不用“h”作后缀而用作后缀而用“c”作后缀也是可以的,
35、但很显然用作后缀也是可以的,但很显然用“h”作后缀更作后缀更能表明该文件的性质。能表明该文件的性质。2022-8-25142语言程序设计 第七章 预处理命令Cfile1.c#includeAfile2.hBFile3.cBA包含包含 图图(a)表示文件表示文件file.c中有一条文件包含命令中有一条文件包含命令#include,在,在编译预处理时,文件编译预处理时,文件file2.h的全部内容将复制到的全部内容将复制到#include命命令处,也就是文件令处,也就是文件file1.c包含包含file2.h。然后再将已包含了文件。然后再将已包含了文件file2.h文件的文件的file1.c文件作
36、为一个源文件进行编译。文件作为一个源文件进行编译。(a)2022-8-25143语言程序设计 第七章 预处理命令C 2.应引起注意的问题应引起注意的问题 文件包含命令有两种格式,如前所述,也就是文件名可以用双引号括起文件包含命令有两种格式,如前所述,也就是文件名可以用双引号括起来,也可以用尖括号括起来。来,也可以用尖括号括起来。例如以下写法都是允许的:例如以下写法都是允许的:#includestdio.h“#include 但是这两种形式是有区别的:使用双引号表示首先在当前的源文但是这两种形式是有区别的:使用双引号表示首先在当前的源文 件目录件目录中查找,若未找到才到包含目录(用户在配置环境时
37、设置的)中去查找。使用中查找,若未找到才到包含目录(用户在配置环境时设置的)中去查找。使用尖括号则表示在包含文件目录中去查找,而不在源文件目录去查找;尖括号则表示在包含文件目录中去查找,而不在源文件目录去查找;Turbo C系统的包含目录,是由用户在配置环境时通过系统的包含目录,是由用户在配置环境时通过Options/Directores菜单设置的。菜单设置的。一个一个include命令只能指定一个被包含文件,若有多个文件要包命令只能指定一个被包含文件,若有多个文件要包 含,则含,则需用多个需用多个include命令。命令。文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件,文件包含
38、允许嵌套,即在一个被包含的文件中又可以包含另一个文件,标准标准C编译器至少支持八重嵌套包含。编译器至少支持八重嵌套包含。2022-8-25144 7.4条件编译条件编译语言程序设计 第七章 预处理命令C 1.第一种形式:第一种形式:#ifdef 标识符标识符 程序段程序段1#else 程序段程序段2#endif 它的功能是如果标识符已被它的功能是如果标识符已被#define命令定义过则对程序段命令定义过则对程序段1进行编译;进行编译;否则对程序段否则对程序段2进行编译。如果没有程序段进行编译。如果没有程序段2(它为空它为空),本格式中的,本格式中的#else可以没有,即可以写为:可以没有,即可
39、以写为:#ifdef 标识符标识符 程序段程序段#endif条件编译有三种形式,下面分别介绍:条件编译有三种形式,下面分别介绍:2022-8-25145语言程序设计 第七章 预处理命令C 2.第二种形式:第二种形式:#ifndef 标识符标识符 程序段程序段1#else 程序段程序段2#endif 在书写上同第一种形式的区别是将在书写上同第一种形式的区别是将“ifdef”改为改为“ifndef”。这种形式的。这种形式的 功能功能是,如果标识符未被是,如果标识符未被#define命令定义过则对程序段命令定义过则对程序段1进行编译,否则对程序段进行编译,否则对程序段2进行编译。这与第一种形式的功能
40、正相反。读者可将例题进行编译。这与第一种形式的功能正相反。读者可将例题7.9进行相应修改并上进行相应修改并上机运行。机运行。3.第三种形式:第三种形式:#if 常量表达式常量表达式 程序段程序段1#else 程序段程序段2#endif 它的功能是,如果常量表达式的值为真它的功能是,如果常量表达式的值为真(非非0),则对程序段,则对程序段1 进行编译,否则进行编译,否则对程序段对程序段2进行编译。因此可以使程序在不同条件下,完成不同的功能。进行编译。因此可以使程序在不同条件下,完成不同的功能。2022-8-25146C语言程序设计 第第8章章 复复杂杂数数据据类类型型C2022-8-251478
41、.1 复杂数据类型概述复杂数据类型概述8.2结构体结构体8.3 使用结构体指针处理链表使用结构体指针处理链表8.4共用体共用体8.5枚举类型枚举类型8.6用户自定义类型用户自定义类型8.7小结及常见错误列举小结及常见错误列举 语言程序设计 第七章 预处理命令C本章主要内容2022-8-25148语言程序设计 第七章 预处理命令C主要内容:主要内容:本章主要介绍本章主要介绍C语言中相对于基本类型语言中相对于基本类型(或称简单类型或称简单类型)而言的复杂数据类而言的复杂数据类型(或称构造数据类型)。型(或称构造数据类型)。C语言中的复杂数据类型主要包含:数组、结构语言中的复杂数据类型主要包含:数组
42、、结构体、共用体等。数组在以前的学习中已经接触过,这里主要学习其他几种数体、共用体等。数组在以前的学习中已经接触过,这里主要学习其他几种数据类型以及枚举类型和用户自定义类型的定义与使用。据类型以及枚举类型和用户自定义类型的定义与使用。学习任务:学习任务:结构体类型与结构体类型变量结构体类型与结构体类型变量 结构体数组结构体数组 结构体与指针结构体与指针 使用结构体指针处理链表使用结构体指针处理链表 共用体类型与共用体类型变量共用体类型与共用体类型变量 枚举类型枚举类型 用户自定义类型用户自定义类型2022-8-25149语言程序设计 第七章 预处理命令C8.1 复杂数据类型概述复杂数据类型概述
43、 C语言有着丰富而灵活的数据类型,这些数据类语言有着丰富而灵活的数据类型,这些数据类型主要分为基本数据类型(或称简单数据类型),型主要分为基本数据类型(或称简单数据类型),复杂数据类型(或称构造数据类型),指针类型以复杂数据类型(或称构造数据类型),指针类型以空类型。基本数据类型就是前面已经介绍过的整型、空类型。基本数据类型就是前面已经介绍过的整型、实型、字符型等等,复杂数据类型主要包括数组、实型、字符型等等,复杂数据类型主要包括数组、结构体、共用体类型等。这些数据类型之所以被称结构体、共用体类型等。这些数据类型之所以被称为构造类型是因为构造类型的数据都是由基本类型为构造类型是因为构造类型的数
44、据都是由基本类型数据按一定规则组成的,例如数组是一组有序的数数据按一定规则组成的,例如数组是一组有序的数据集合,据集合,C语言规定数组中的每一个元素都属于同语言规定数组中的每一个元素都属于同一种基本一种基本的数据类型,并存储在一组连续的内存单元中。因的数据类型,并存储在一组连续的内存单元中。因此构造类型都是建立在基本数据类型基础之上的。此构造类型都是建立在基本数据类型基础之上的。2022-8-25150语言程序设计 第七章 预处理命令C8.2结构体结构体8.2.1 结构体类型的定义结构体类型的定义8.2.2 结构体变量的定义结构体变量的定义8.2.3 结构体变量的引用结构体变量的引用8.2.4
45、 结构体变量的初始化结构体变量的初始化8.2.5 结构体数组结构体数组8.2.6 结构体指针结构体指针 2022-8-25151语言程序设计 第七章 预处理命令C8.2.1 结构体类型的定义结构体类型的定义8.2.2 结构体变量的定义结构体变量的定义定义结构体变量的方法有以下三种。定义结构体变量的方法有以下三种。1.先定义结构体类型,再说明结构体变量。先定义结构体类型,再说明结构体变量。例如:例如:struct stu int num;char name20;char sex;int age;float score;struct stu stu1,stu2;2022-8-25152语言程序设计
46、 第七章 预处理命令C2.在定义结构体类型的同时定义结构体变量。在定义结构体类型的同时定义结构体变量。例如:例如:struct stu int num;char name20;char sex;int age;float score;stu1,stu2;这种形式的说明的一般形式为:这种形式的说明的一般形式为:struct 结构体类型名结构体类型名 数据类型说明符数据类型说明符 成员名成员名;变量名列表变量名列表;2022-8-25153语言程序设计 第七章 预处理命令C3.直接定义结构体变量。直接定义结构体变量。例如:例如:struct int num;char name20;char sex
47、;int age;float score;stu1,stu2;这种形式的说明的一般形式为:这种形式的说明的一般形式为:struct 数据类型说明符数据类型说明符 成员名成员名;变量名列表变量名列表;2022-8-25154语言程序设计 第七章 预处理命令C8.2.3 结构体变量的引用结构体变量的引用对于结构体变量而言,只有以下的两种情况可以对结对于结构体变量而言,只有以下的两种情况可以对结构体变量进行引用构体变量进行引用 1.对结构体变量整体赋值。对结构体变量整体赋值。例如:例如:stu1=stu2;2.取结构体变量的地址。取结构体变量的地址。例如:例如:&stu1;而其他对于结构体变量的引用
48、则必须引用相应结构体而其他对于结构体变量的引用则必须引用相应结构体变量的各个成员。结构体变量中成员引用的一般形式变量的各个成员。结构体变量中成员引用的一般形式是:是:结构体变量名结构体变量名.成员名成员名 例如:例如:stu1.num 即第一个人的学号即第一个人的学号 stu2.sex 即第二个人的性别即第二个人的性别2022-8-25155语言程序设计 第七章 预处理命令C8.2.4 结构体变量的初始化结构体变量的初始化如同其他数据类型的变量一样,对于结构体变量也如同其他数据类型的变量一样,对于结构体变量也可以在定义时指定初始值。需要注意的是结构体变可以在定义时指定初始值。需要注意的是结构体
49、变量的初始化在数据类型、顺序上要和结构体类型定量的初始化在数据类型、顺序上要和结构体类型定义中的成员相匹配,数据间用逗号分隔,所有的数义中的成员相匹配,数据间用逗号分隔,所有的数据写在一个花括号内,最后以分号结尾。据写在一个花括号内,最后以分号结尾。分析:结构体变量的初始化就是在结构体类型定义的同时对其变量赋初分析:结构体变量的初始化就是在结构体类型定义的同时对其变量赋初始值。始值。编程序如下:编程序如下:main()struct stu /*定义结构定义结构*/int num;char name20;char sex;2022-8-25156语言程序设计 第七章 预处理命令C int age
50、;float score;stu2=10258,LiMing,F,21,453.5;printf(Number=%dnName=%snSex=%cnAge=%dnScore=%fn,stu2.num,stu2.name,stu2.sex,stu2.age,stu2.score);运行程序输出为:运行程序输出为:2022-8-25157语言程序设计 第七章 预处理命令C8.2.5 结构体数组结构体数组 结构体数组的定义结构体数组的定义 结构体数组的初始化结构体数组的初始化 结构体数组的引用结构体数组的引用1.结构体数组的定义结构体数组的定义(1)先定义结构体类型,再说明结构体数组先定义结构体类型