1. 首页
  2. ppt
  3. 开发工具
该PPT是用户上传,如果对该PPT内容或使用有所疑问,请根据该ppt中作者所留的联系方式,咨询原作者!
如果涉及侵权等原因需要删除,请联系QQ:875388611

C语言教程

4682    0    0
zack
颜色:
下载需要 8 金币 [ 金币充值 ]
亲,您也可以通过 分享原创文档 来获得金币奖励!

服务器/托管费、人工审核、技术维护等都需要很多费用,感谢您支持深度开源的发展!

下载PPT

  • PPT 内容
  • PPT 图集
  • 1. 教材、参考书与课时安排教材 清华大学出版社 参考书 C语言程序设计教程 高等教育出版社 C高级实用程序设计 清华大学出版社 C程序设计试题汇编 清华大学出版社 课时安排 64学时
  • 2. 熟记C语言的基本概念 熟悉Turbo C的上机操作环境 会读、会编、会调试C程序 学习要点 熟记C语言的语法 学会算法分析与算法设计 课程目的
  • 3. 课程要求课前请做好预习 保持课堂安静,头脑清醒,思维活跃 认真、独立、按时完成并提交作业 重视上机实践,有效利用宝贵的上机时间
  • 4. 第1章 C语言概述第2章 程序的灵魂—算法第3章 数据类型、运算符与表达式第4章 最简单的C程序设计—顺序程序设计第5章 选择结构程序设计第6章 循环控制第7章 数组第8章 函数第9章 预处理命令第10章 指针第11章 结构体与共用体第12章 位运算第13章 文件目 录
  • 5. C语言发展历史C语言的特点简单的C程序介绍C程序的上机步骤第1章 C语言概述 C语言程序设计 第一章 C语言概述
  • 6. 1.1 C语言发展历史 程序设计语言的发展机器语言汇编语言高级语言面向过程面向对象CPU指令系统,由0、1序列构成的指令码组成 如:10000000 加 10010000 减用助记符号描述的指令系统,可进行地址、位操作 如 ADD A, B 编写系统软件,直接对硬件操作,可读性,移植性差面向机器的语言> C语言程序设计 第一章 C语言概述可读性,移植性好,编写应用程序 一般较难实现汇编语言的某些功能 如:地址和位的操作C语言兼有高级和低级语言的功能 适合写系统软件和应用软件 又称中级语言<
  • 7. C语言发展过程 产生背景 ALGOL 60→CPL语言→BCPL→B语言,写UNIX系统 产生过程 时间:1972~1973 地点:美国贝尔实验室 目的:UNIX操作系统 设计人: Ken.Thompson和Dennis.M.Ritchie C标准 标准C: 1978年 K&R合著《The C Programming Language》 ANSI C: 1983年 87 ANSI C: 1987年 1990年国际标准的ANSI C ,1994年再次修订。 C版本 Microsoft C 或称 MS-C Turbo C 或称 TC<> C语言程序设计 第一章 C语言概述
  • 8. 1.2 C语言的特点 语言简洁、紧凑、灵活 运算符丰富 数据结构、数据类型丰富 链表、树、栈 程序设计结构化、模块化 结构化控制语句:if…else、while、switch、for 函数作为模块单位 语法不严格、程序设计自由度大 可以访问内存地址、进行位运算 生成目标代码质量高 可移植性好<>>>>>> C语言程序设计 第一章 C语言概述
  • 9. 32个关键字:(由系统定义,不能重作其它定义) auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef unsigned union void volatile while Turbo C扩充了11个关键字: asm _cs _ds _es _ss cdecl far huge interrupt near pascal 注意:在C语言中,关键字都是小写的。 < C语言程序设计 第一章 C语言概述C语言简洁、紧凑,使用方便、灵活。 ANSI C一共只有32个关键字,见365页 附录B
  • 10. 9种控制语句: if( )~else~ for( )~ while( )~ do~while( ) continue break switch goto return< C语言程序设计 第一章 C语言概述C语言有 9 种控制语句,程序书写形式自由,主要用小写字母表示,压缩了一切不必要的成分。
  • 11. < C语言程序设计 第一章 C语言概述表1.1 C语言与Pascal语言比较通过表1.1 我们可以得出结论:C比 Pascal简练,因此源程序更短,编程效率高。C语言PASCAL语言含义{ } if(e) S; int i; int a[10]; int f(); int *p; i+=2; i++, ++I;BEGIN END IF (e) THEN S; VAR i :INTEGER; VAR a:ARRAY[1..10] OF INTEGER; FUNCTION f():INTEGER; VAR P: INTEGER; i=i+2; i=i+1;函数体、分程序、复合语句 条件语句 定义i为整形变量 定义a为一维数组 定义f为返回整形值函数; p为指向整形变量的指针变量; 赋值语句,使i+2赋给I i自增值1,i加1赋给I
  • 12. 34种运算符: 算术运算符:+ - * / % ++ -- 关系运算符:< <= == > >= != 逻辑运算符:! && || 位运算符 :<< >> ~ | ^ & 赋值运算符:= 及其扩展 条件运算符:?: 逗号运算符:, 指针运算符:* & 求字节数 :sizeof 强制类型转换:(类型) 分量运算符:. -> 下标运算符:[] 其它 :( ) - 注意:各种运算符混合使用,其优先级与结 合方法是难点,可先预习。 < C语言程序设计 第一章 C语言概述C语言运算符丰富(附录C)
  • 13. C 数 据 类 型基本类型构造类型指针类型空类型void定义类型typedef数值类型字符类型char枚举类型enum整 型浮点型单精度型float双精度型double短整型short长整型long整型int数组结构体struct共用体union< C语言程序设计 第一章 C语言概述C语言数据结构丰富
  • 14. 1.3 简单的C程序介绍/* example1.1 The first C Program*/ #include void main() { printf(“This is a c program.\n”); } C语言程序设计 第一章 C语言概述>注释编译预处理主函数语句输出: This is a c program.例1.1 第一个程序This is a c program .
  • 15. 例1.2求俩个数的和/* example1.1 calculate the sum of a and b*/ #include /* This is the main program */ void main() { int a,b,sum; /*定义变量*/ a=10; b=24; sum=add(a,b); printf(”sum= %d\n",sum); } /* This function calculates the sum of x and y */ int add(int x,int y) { int z; z=x+y; return(z); }运行结果: sum=34函数语句预处理命令注释 C语言程序设计 第一章 C语言概述>
  • 16. C语言程序设计 第一章 C语言概述><例1.3 从键盘输入两个整数,输出其中较大的数#include void main() { int max(int x,int y) int a,b,c; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(" max = %d",c); } int max(int x,int y) { int z; if(x>y) z=x; else z=y; return(z); }scanf语句中“&a”的含义是“取地址”输入:10,20  输出:max = 20声明部分,定义变量调用max函数,返回值赋给c定义max子函数,函数值、形参x、y为整型通过max函数将z值带回调用处
  • 17. C语言格式特点 习惯用小写字母,大小写敏感 不使用行号,无程序行概念 可使用空行和空格 常用锯齿形书写格式<> C语言程序设计 第一章 C语言概述main( ) { ………………. ……………… ………….. ………….. ……… ………. …………… ……………. ………………. ……………….. } main( ) { int i , j , sum; sum=0; for(i=1; i<10;i++) { for(j=1;j<10;j++) { sum+=i*j ; } } printf(“%d\n”,sum); }优秀程序员的素质之一: 使用TAB缩进 {}对齐 有足够的注释 有合适的空行
  • 18. C语言结构特点 函数与主函数 程序由一个或多个函数组成 必须有且只能有一个主函数main(),可以放在程序中任一位置 程序执行从main开始,在main中结束,其它函数通过嵌套调用得以执行。 程序语句 C程序由语句组成 用“;”作为语句终止符 注释 /* */为注释,不能嵌套 不产生编译代码<>例: /*This is the main /* of example1.1*/ */ 非法编译预处理命令 C语言程序设计 第一章 C语言概述
  • 19. 编辑链接编译执行1.4 C程序的上机步骤 C程序开发步骤<>file.exe C语言程序设计 第一章 C语言概述程序代码的录入, 生成源程序*.c语法分析查错,翻译 生成目标程序*.obj与其它目标程序或库 链接装配,生成可执行 程序*.exe
  • 20. Turbo C集成开发环境 配置要求 UNIX,PC-DOS,MS-DOS,UCDOS操作系统 硬盘容量约2M,448K RAM运行空间 安装Turbo C 创建子目录 Install 若不是可安装盘,将文件拷贝到对应的目录下TC*.*INCLUDELIB*.*SYS*.*<> C语言程序设计 第一章 C语言概述
  • 21. 进入Turbo C D:\TC>TC.exe 主控菜单 文件操作FILE :New Load Save Write to 编辑操作EDIT:插入/修改 块 查找/替换 编译链接COMPILE LINK MAKE 执行RUN 退出Turbo C Alt +x Alt+F ,Q 帮助Help F1 Ctrl+F1<> C语言程序设计 第一章 C语言概述
  • 22. (本页无文本内容)
  • 23. 基本操作: F10-----调用主菜单 F2------存盘 F3------打开 F1------帮助信息 Alt+F9------Compile Ctrl+F9------Run Alt+F5------User Screen Alt+X ------退出Tc常用热键文本编辑: -------移动光标 PgUp,PgDn------上下翻页 Ctrl+PgUp,Ctrl+PgDn------文件首尾 Home行首 End行尾 Ddelete Insert Bkspace块操作: Ctrl+KB-------块开始标记 Ctrl+KK--------块结束标记 Ctrl+KC-------块拷贝 Ctrl+KV--------块移动 Ctrl+KY-------块删除 Ctrl+KH--------块隐藏程序调试: F8-----Step over F7-------Trace into F4-----Goto Cursor Ctrl+F7--------Add Watch Ctrl+F8------Toggle Breakpoint Ctrl+F2--------Program Reset窗口操作: F5-----窗口缩放 F6-----窗口切换 C语言程序设计 第一章 C语言概述<>
  • 24. 课后作业 预习“题解与上机指导”一书中 P181~199页的14.3~14.10节 P236页实验1 教材P12: 1.5、 1.6、 1.7、 1.8题。 注意:有关设计程序的作业,必须经过上机调试! C语言程序设计 第一章 C语言概述<>
  • 25. 算法的概念简单算法举例算法的特性怎样表示一个算法第2章 程序的灵魂——算法 C语言程序设计 第二章 程序的灵魂——算法结构化程序设计方法
  • 26. <> C语言程序设计 第二章 程序的灵魂——算法程序包括的内容: 数据结构:数据的类型和组织形式 算法:操作步骤的描述Nikiklaus Wirth提出: 程序= 数据结构+算法教材认为: 程序=算法+数据结构+程序设计方法+语言工具和环境 灵魂加工对象工具
  • 27. <> C语言程序设计 第二章 程序的灵魂——算法2.1 算法的概念 为解决一个问题而采取的方法和步骤,就成为算法。例如:歌曲的乐谱,建造房子等。 算法核心是解决“做什么”和“怎么做”的问题。 P15页的例2.1,求1……5之积。 可以有多种方法,一般采用简单和运算步骤少的。准确、高效 计算机算法类别 数值运算算法 非数值运算算法
  • 28. <> C语言程序设计 第二章 程序的灵魂——算法2.2 简单算法举例 例2.1 方法1:累乘 方法2:用循环结构解决,灵活、通用。 例2.2 通过循环选择打印 例2.3 判断闰年 例2.4 累加求级数的和,循环改变正负号和分母加1。 例2.5 判断素数课后认真思考,加深什么是算法的概念
  • 29. <> C语言程序设计 第二章 程序的灵魂——算法2.3 算法的特性 有穷性—在合理范围内可完成 确定性—无歧义性 有零个或多个输入—从外界得到信息 有一个或多个输出—问题的答案 有效性—每步有确定的结果
  • 30. > C语言程序设计 第二章 程序的灵魂——算法2.4 怎样表示一个算法 自然语言表示 2.2节例。易懂,文字冗长,易歧义性 流程图表示 用流程图符号构成,直观,易懂 N-S流程图表示 伪代码表示 计算机语言表示 顺序结构 选择结构 循环结构<
  • 31. > C语言程序设计 第二章 程序的灵魂——算法 传统流程图流向混乱、可读性差,所以应该采用结构化流程图。 结构化程序设计 基本思想:任何程序都可以用三种基本结构表示,限制使用无条件转移语句(goto) 结构化程序:由三种基本结构反复嵌套构成的程序 优点:结构清晰,易读,提高程序设计质量和效率三种基本结构 顺序结构ABAB流程图N-S图<
  • 32. > C语言程序设计 第二章 程序的灵魂——算法PAB真假PBA真假选择结构kA1A2AiAnk=k2k=k1k=knk=ki......二分支选择结构多分支选择结构<
  • 33. > C语言程序设计 第二章 程序的灵魂——算法循环结构当型循环结构直到型循环结构PA假真当P为真AAP真假A直到P为真注:A,B,A1….An可以是一个简单语句,也可以是一个基本结构<
  • 34. > C语言程序设计 第二章 程序的灵魂——算法 三种基本结构的共同特点: 只有一个入口; 只有一个出口; 结构内的每一部分都有机会被执行到; 结构内不存在“死循环”。 <
  • 35. > C语言程序设计 第二章 程序的灵魂——算法2.5 结构化程序设计方法 结构化程序:用三种基本结构组成的程序 基本设计思路: 复杂问题分解成 几个最基本问题,再分别处理。 采用的方法: 自顶向下; 逐步细化; 模块化设计:复杂问题按功能分成多个子模块 结构化编码:正确采用三种基本结构实现<
  • 36. > C语言程序设计 第二章 程序的灵魂——算法课后作业 P36页习题: 2.4、2.8(结合实验指导读懂答案) 用N-S图表示2.4题中⑴⑵⑹ 用传统流程图求解以下问题:将一个16进制数转化为10进制数 复习二进制的基本概念 “计算机文化基础”一书中P27~33页<
  • 37. 第3章 数据类型、运算符与表达式 C语言程序设计 第三章 程序的灵魂——算法C的数据类型常量与变量整型数据实型数据字符型数据变量赋初值各种数值型数据间的混合运算算术运算符和算术表达式赋值运算符和赋值表达式逗号运算符和逗号表达式
  • 38. <> C语言程序设计 第三章 程序的灵魂——算法3.1 C的数据类型C 数 据 类 型基本类型构造类型指针类型空类型 void字符型 char整 型实 型(浮点型)单精度型 float双精度型 double数组类型结构体类型共用体类型短整型 short长整型 long整型 int枚举类型 enum数据类型决定: 1. 数据占内存字节数 2. 数据取值范围 3. 可以进行的操作
  • 39. <> C语言程序设计 第三章 程序的灵魂——算法常量和符号常量 定义:程序运行过程中,其值不能被改变的量(常数) 分类:直接常量、符号常量 3.2 常量与变量类型示例整型常量12 、 0 、 -3实型常量4.6 、 -1.23字符常量‘a’ 、 ‘b’ 符号常量PRICE 、 PAI
  • 40. <> C语言程序设计 第三章 程序的灵魂——算法符号常量:用标识符代表常量 一般用大写字母: PRICE 、 PI 定义格式: #define 符号常量 常量 其值在作用域内不能改变和再赋值。例3.1 符号常量举例 #define PRICE 30 #include void main() { int num,total; num=10; total=num*PRICE; printf("total=%d\n",total); }total=300运行结果:符号常量的优点是:见名知意、一改全改
  • 41. <> C语言程序设计 第三章 程序的灵魂——算法变量 定义:其值可以改变的量。 定义格式:数据类型 变量名; 变量应该有名字,并在内存中占据一定的存储单元。 变量名和变量值有不同的含义 变量名实为一个符号地址 a3例 变量的使用 main() { int a; a=3; printf(“a=%d",a); }变量名 变量值 存储单元
  • 42. <> C语言程序设计 第三章 程序的灵魂——算法标识符 定义:标识变量名、符号常量名、函数名、数组名、 文件名的字符串序列——名字。 命名规则: 只能由字母、数字、下划线组成,且第一个字符必须是字母或下划线 大小写字母含义不同,一般用小写 不能使用关键字 TC允许最长32个字符,建议长度不超过8个字符 使用:先定义、后使用标识符应该“见名知意”,如 total , max 标识符应该“不宜混淆”,如 l与1 , O与0这些标识符合法吗? 1A、M.D.John、¥123、#33、 Tatol、int、max
  • 43. > C语言程序设计 第三章 程序的灵魂——算法3.3 整型数据 整型常量(整常数)的三种表示方法 十进制整数:由数字0~9和正负号表示. 如 123,-456,0 八进制整数:由数字0开头,后跟数字0~7表示. 如 0123,011 十六进制整数:由0x开头,后跟0~9,a~f,A~F表示. 如 0x123,0xff<
  • 44. <> C语言程序设计 第三章 程序的灵魂——算法 补充知识:字节和位 内存以字节为单元组成 每个字节有一个地址 一个字节一般由8个二进制位组成 每个二进位的值是0或101234567012345678910……...7643251
  • 45. <> C语言程序设计 第三章 程序的灵魂——算法数值的表示方法——原码、反码和补码 原码:最高位为符号位,其余各位为数值本身的绝对值 反码: 正数:反码与原码相同 负数:符号位为1,其余位对原码取反 补码: 正数:原码、反码、补码相同 负数:最高位为1,其余位为原码取反,再对整个数加13126912457810119-5=4 9+7=16=(14)12
  • 46. <> C语言程序设计 第三章 程序的灵魂——算法原码反码补码+7000001110000011100000111-7100001111111100011111001+0000000000000000000000000-0100000001111111100000000数的范围01111111~ 11111111 (-127~+127)01111111~ 10000000 (-127~+127)01111111~ 10000000 (-128~+127)(用一字节表示数)负数补码转换成十进制数:最高位不动,其余位取反加1例 补码:11111001 取反:10000110 加1: 10000111=-7
  • 47. > C语言程序设计 第三章 程序的灵魂——算法整型变量 整型数据在内存中的存放形式 数据在内存中以二进制补码形式存放 每一个整型变量在内存中占2个字节 10的原码 反码 补码 -10的原码 取绝对值 反码 补码00 00 00 00 00 00 10 1000 00 00 00 00 00 10 1000 00 00 00 00 00 10 1010 00 00 00 00 00 10 1000 00 00 00 00 00 10 1011 11 11 11 11 11 01 0111 11 11 11 11 11 01 10整数的最左二进制位是符号位,0正、1负<
  • 48. > C语言程序设计 第三章 程序的灵魂——算法整型变量的分类 三类整型变量  有符号无符号基本型(简称整型)int unsigned int短整型short或short intunsigned short长整型long或long intunsigned long整数类型和取值范围TURBO C所占位数最小取值范围int16-32768~+32767short16-32768~+32767long32-2147483648~+2147483647unsigned int160~65535unsigned short160~65535unsigned long320~4294967295<
  • 49. > C语言程序设计 第三章 程序的灵魂——算法整型变量的定义 先定义后使用——强制类型定义 int a,b; ( 指定变量a、b为整型 ) unsigned short c, d; (指定变量c、d为无符号短整型 ) long e,f; ( 指定变量e、f为长整型) 00 00 00 00 00 00 11 0100 00 00 00 00 00 00 0000 00 00 00 00 00 11 0100 00 00 00 00 00 11 0100 00 00 00 00 00 00 0000 00 00 00 00 00 11 0100 00 00 00 00 00 11 0100 00 00 00 00 00 11 01int 型short 型long 型unsigned int 型unsigned int 型unsigned long 型符号位例3.2 整型变量的定义与使用 #include void main() {int a,b,c,d; unsigned u ; a=12;b=-24;u=10; c=a+u;d=b+u; printf(“a+u=%d,b+u=%d\n",c,d); } 指定abcd为整型变量指定u为无符号整型变量定义放在函数开头的声明部分作用域不同类型混合运算,类型自动转换结果: a+u=22,b+u= -14定义与赋值同时进行: int a=12;<
  • 50. > C语言程序设计 第三章 程序的灵魂——算法整型数据的溢出 此情况称为“溢出”,运行时不报错,编程时要注意01 11 11 11 11 11 11 11整型变量最大值3276710 00 00 00 00 00 00 00加1后是 –32768的补码形式例3.3 整型数据的溢出 #include void main( ) { int a , b; a= 32767; b= a+1; printf("%d , %d \n ",a,b); } 32767 , -32768 运行结果:改为:long b; 结果是什么?<
  • 51. > C语言程序设计 第三章 程序的灵魂——算法整型常量的类型 整型常量的值在-32768~+32767范围内,编译器认为是int类型 整型常量的值超过上述范围,而在-2147483648 ~ +2147483647范围内,编译器认为是long类型 当系统定义short int与int占内存长度相同,则两种类型常量均可以赋给 int和short int型变量 在整型常量后面加大写L或小写l,则告诉编译器,把该整型常量作为long类型处理。例:123L、0L 在整型常量后面加u,则按无符号整型方式存放,负数转换成补码再按无符号整型方式存放。<
  • 52. <> C语言程序设计 第三章 程序的灵魂——算法3.4 浮点型数据 浮点型常量的表示方法 浮点数(float)又称为实数(real) 两种表示方法: 十进制小数形式:必须有小数点 如 0.123 、.123 、123.0 、0.0 、123. 指数形式:e或E之前后必须有数字;指数必须为整数 如 123.456e0、12.3456e1 、1.23456e2 、 0.123456e3 、0.0123456e4 等 规范化指数形式 只有一位非零整数的指数形式 是指数的输出形式6.28e-2 表示 6.28× 10 -2-3.0824e4 表示 –3.0824× 10 4
  • 53. > C语言程序设计 第三章 程序的灵魂——算法浮点型变量 浮点型数据在内存中的存放形式 浮点型数据在内存中占4个字节(32位) 在内存中分成3部分,指数为2的幂次 + .314159 1数符小数部分指数浮点型变量的分类 单精度 float  32位6~7双精度 double 型64位15~16长双精度long double型128位18~19类 型 位数有效数字float x,y; (指定x、y为单精度浮点型变量) double z; (指定z为双精度浮点型变量) long double t; (指定t为长双精度浮点型变量)<
  • 54. > C语言程序设计 第三章 程序的灵魂——算法浮点型数据的舍入误差 数据超过有效位数,则产生误差 要避免一个很大的数与一个很小的数加减例3.4 浮点型数据的舍入误差 #include void main( ) { float a , b; a= 123456.789e5; b= a+20; printf("%f \n",b); } 舍入误差使1.0/3*3 的结果并不等于1 !12345678848.000000 运行结果:浮点型常量的类型 浮点型常量一般按双精度64位处理,数后加F或f按单精度 浮点型常量不分float和double <
  • 55. > C语言程序设计 第三章 程序的灵魂——算法3.5 字符型数据 字符常量 定义:用单引号括起来的单个字符或转义字符 字符常量的值:该字符的ASCII码值 定义格式:char 变量名 = 值 转义字符:反斜线后面跟一个字符或一个代码值表示如 ‘a’ ‘A’ ‘\n’ ‘\t ’ 如 ‘a’——97 ,‘A’——65 ‘\n’——10, ‘\t’——9char ch=65 与 char ch=‘A’ 与char=‘\101’是等效的<
  • 56. > C语言程序设计 第三章 程序的灵魂——算法<表3.3 转义字符及其含义转义字符含义\n\v\r\a\‘\ddd\t\b\f\\\“\xhh转义字符含义换行垂直制表回车(不换行)响铃单引号3位8进制数代表的字符水平制表(右移8格)退格换页反斜线双引号2位16进制数代表的字符例3.5 转义字符的使用 #include void main( ) { printf(“ ab c\t de\rf\tg\n”); printf(“h\ti\b\bj k”); }f gde h j k显示结果: 打印结果:fab gde h jik<
  • 57. > C语言程序设计 第三章 程序的灵魂——算法字符变量 存放字符常量,占用一个字节,存放一个字符 定义形式: 赋值: char c1,c2; c1=‘a’;c2=‘b’;字符数据在内存中的存储形式及其使用方法 以二进制存放字符的ASCII码值(0~255整数) 与整数的存储形式类似 以字符或整数形式输出例3.6 向字符变量赋整数 #include void main( ) { char c1,c2 ; c1=97 ; c2=98 ; printf(“%c %c \n",c1,c2); printf(“%d %d \n",c1,c2); } a b 97 98运行结果:输出形式取决于printf函数中的格式符格式符为“%c”时输出的变量值为字符 格式符为“%d"时输出的变量值为整数<
  • 58. > C语言程序设计 第三章 程序的灵魂——算法对字符数据进行算术运算 实质是对其ASCII值进行算术运算例3.7 大小写字母的转换 #include void main( ) {char c1,c2 ; c1=‘a’ ; c2=‘b’ ; c1=c1-32; c2=c2-32; printf(“%c %c ",c1,c2); } A B运行结果:字符型与整型间互相赋值例: 互相赋值 #include void main( ) {int c1; char c2 ; c1=‘a’ ; c2=98 ; c1=c1-32; c2=c2-32; printf(“%c %c ",c1,c2); } 小写字母比大写字母的ASCII码大(32)10<
  • 59. > C语言程序设计 第三章 程序的灵魂——算法字符串常量 定义:用双引号(“ ”)括起来的字符序列 “How do you do” , “CHINA” , “a” , “$123.45” 存储:每个字符串尾自动加一个 ‘\0’ 作为字符串结束标志h e l l o \0例 字符串“hello”在内存中例 空串 “”\0字符常量与字符串常量不同a a \0例 ‘a’“a”例: char ch; ch=“A”; 例: char ch; ch=‘A’; 没有字符串变量, 只能用字符数组存放<
  • 60. > C语言程序设计 第三章 程序的灵魂——算法3.6 变量赋初值 变量的使用:先定义,后使用 变量定义位置:一般放在函数开头 变量初始化:可以在定义时赋初值例: int a=1,b= -3,c; float data=3.67; char ch=‘A’; int x=1,y=1,z=1; int x=y=1;(× )编译程序根据变量定义为其 分配指定字节的内存单元…...地址int a=1, b=-3,c;abc2字节2字节2字节地址地址…...内存1-3随机数错!int a=b=c=3<
  • 61. > C语言程序设计 第三章 程序的灵魂——算法3.7 各类数值型数据间的混合运算 整型、实型、字符型数据间可以混合运算自动转换 什么情况下发生 运算转换------不同类型数据混合运算时 赋值转换------把一个值赋给与其类型不同的变量时 输出转换------输出时转换成指定的输出格式 函数调用转换------实参与形参类型不一致时转换 运算转换规则:不同类型数据运算时先自动转换成同一类型<
  • 62. > C语言程序设计 第三章 程序的灵魂——算法doublefloatlongunsignedintchar,short低高说明:必定的转换运算对象类型不同时转换例 char ch; int i; float f; double d;ch/i + f*d - (f+i)intintdoubledoubledoubledoubledoubledoubleintintdoubledoubledoubledoubledoubledouble10+‘a’ +i*f - d/l例 int i; float f; double d; long l;<
  • 63. > C语言程序设计 第三章 程序的灵魂——算法强制转换(见P56强制类型转换运算符部分) 一般形式:(类型名)(表达式) 例:(int)(x+y) (int)x+y (double)(3/2) (int)3.6 说明:强制转换得到 所需类型的中间变量, 原变量类型不变 例3.8 #include main() { float x; int i; x=3.6; i=(int)x; printf(“x=%f,i=%d”,x,i); } 结果:x=3.600000,i=3精度损失问题较高类型向较低类型转换时可能发生强制类型转换运算符表达式仅一个变量时,括号可以省略 <
  • 64. > C语言程序设计 第三章 程序的灵魂——算法3.8 算术运算符和算术表达式C 运 算 符算术运算符:(+ - * / % ++ --) 关系运算符:(< <= == > >= !=) 逻辑运算符:((! && ||) 位运算符 :(<< >> ~ | ^ &) 赋值运算符:(= 及其扩展) 条件运算符:(?:) 逗号运算符:(,) 指针运算符:(* &) 求字节数 :(sizeof) 强制类型转换:(类型) 分量运算符:(. ->) 下标运算符:([]) 其它 :(( ) -) 学习运算符应注意: 运算符功能 与运算量关系 要求运算量个数 要求运算量类型 运算符优先级别 结合方向 结果的类型<
  • 65. > C语言程序设计 第三章 程序的灵魂——算法算术运算符和算术表达式 基本算术运算符: + - * / % 结合方向:从左向右 优先级: - ---->* / % -----> + - (2) (3) (4) 说明: “-”可为单目运算符时,右结合性 两整数相除,结果为整数 %要求两侧均为整型数据 + - * / 运算的两个数中有一个数为实数,结果是double型例 5/2 = -5/2.0 =例 5%2 = -5%2 = 1%10 = 5%1 = 5.5%2例 5/2 = 2 -5/2.0 = -2.5例 5%2 = 1 -5%2 = -1 1%10 = 1 5%1 = 0 5.5%2 ()<
  • 66. > C语言程序设计 第三章 程序的灵魂——算法自增、自减运算符++ -- 作用:使变量值加1或减1 种类: 前置 ++i, --i (先执行i+1或i-1,再使用i值) 后置 i++,i-- (先使用i值,再执行i+1或i-1)例 j=3; k=++j; j=3; k=j++; j=3; printf(“%d”,++j); j=3; printf(“%d”,j++); a=3;b=5;c=(++a)*b; a=3;b=5;c=(a++)*b; //k=4,j=4//k=3,j=4//4,j=4//3,j=4//c=20,a=4//c=15,a=4<
  • 67. > C语言程序设计 第三章 程序的灵魂——算法几点说明:例 -i++ i=3; printf(“%d”,-i++);  -(i++)//-3 ++ -- 不能用于常量和表达式,如 5++,(a+b)++ ++ -- 结合方向: 自右向左 优先级:- ++ -- ------>* / % ----->+ - (2) (3) (4) 该运算符常用于循环语句中,使循环变量加减1有关表达式使用中的问题说明 不同系统对运算符和表达式的处理次序不同,尽可能写通用性强的语句 不要写有歧义和不知系统如何执行的程序<
  • 68. > C语言程序设计 第三章 程序的灵魂——算法3.9 赋值运算符和赋值表达式简单赋值运算符 符号: = 格式: 变量标识符=表达式 作用:将一个数据(常量或表达式)赋给一个变量 左侧必须是变量,不能是常量或表达式例 a=3; d=func(); c=d+2;例 3=x-2*y; a+b=3; (×)<类型转换 赋值转换规则:使赋值号右边表达式值自动转换成其左边变量的类型例 float f ; int i=10; f=i; 则 f=10.0例 int i; i=2.56; //结果i=2;
  • 69. 复合赋值运算符 种类:+= -= *= /= %= 《= 》= &= ^= |= 含义: exp1 op= exp2  exp1 = exp1 op exp2a+=3a=a+3x*=y+8x=x*(y+8)x%=3x=x%3
  • 70. > C语言程序设计 第三章 程序的灵魂——算法赋值表达式 形式:<变量> <赋值运算符> <表达式> 赋值表达式的值与变量值相等,且可嵌套例: a=b=c=5 a=(b=5) a=5+(c=6) a=(b=4)+(c=6) a=(b=10)/(c=2)//表达式值为5,a,b,c值为5// b=5;a=5//表达式值11,c=6,a=11//表达式值10,a=10,b=4,c=6//表达式值5,a=5,b=10,c=2<
  • 71. > C语言程序设计 第三章 程序的灵魂——算法3.10 逗号运算符和逗号表达式 形式:表达式1,表达式2,……表达式n 结合性:从左向右 优先级: 15,级别最低 逗号表达式的值:等于表达式n的值 用途:常用于循环for语句中例 a=3*5,a*4 a=3*5,a*4,a+5 例 x=(a=3,6*3) x=a=3,6*a 例 a=1;b=2;c=3; printf(“%d,%d,%d”,a,b,c); printf(“%d,%d,%d”,(a,b,c),b,c); //a=15,表达式值60//a=15,表达式值20//赋值表达式,表达式值18,x=18//逗号表达式,表达式值18,x=3//1,2,3//3,2,3<
  • 72. > C语言程序设计 第三章 程序的灵魂——算法例: 逗号表达式使用 main() { int x,y=7; float z=4; x=(y=y+6,y/z); printf("x=%d\n",x); } X=3 运行结果: 本章的内容散乱而复杂,但却是程序设计的基础,要认真看书,通过编程序才可以深入理解。<
  • 73. > C语言程序设计 第三章 程序的灵魂——算法课后作业 P66~68页习题: 3.2, 3.5(思考) 3.3, 3.4, 3.9, 3.12(写出答案) 3.6, 3.10(上机验证) 上机:实验教材:实验2(做好上机准备) 预习第四、第五章<
  • 74. 第4章 最简单的C程序设计—— 顺序程序设计 C语言程序设计 第四章 顺序程序设计C语言概述赋值语句数据输入输出的概念及在C语言中的实现字符数据的输入输出格式输入与输出顺序结构程序设计举例
  • 75. <>4.1 C语句概述 C程序结构: 一个C程序可以由多个源程序文件构成 一个源程序文件由若干函数、预编译命令及全局变量声明部分构成 函数包括数据定义部分和执行部分,执行部分是C语言语句,完成对数据的操作 C语言程序设计 第四章 顺序程序设计
  • 76. <>C语句分为5类 控制语句:共9种 完成一定的控制功能,这些语句能够根据一定的测试条件决定某些语句是否被执行,如分支、循环、跳转等语句。 C语言程序设计 第四章 顺序程序设计if( )~else~ (条件语句) for( )~ while( )~ (循环语句) do~while( ) continue (结束本次循环语句) switch (多分支选择语句) break (终止switch或循环语句) goto (转向语句) return (从函数返回语句)
  • 77. <> C语言程序设计 第四章 顺序程序设计 空语句:只有一个“ ; ”,什么也不做 表达式语句:由表达式加“ ; ”组成 典型的是赋值语句,由赋值表达式加分号构成,如:y=x+1是表达式,而y=x+1;则是赋值语句。实际上函数调用语句也属于表达式语句。 函数调用语句:由函数加“ ; ”组成printf(“This is a C program”); a=3 ; i++ ;for(i=0;i<100;i++) { ; }
  • 78. <>复合语句: 用 {…}括起来的一组语句,也称作程序块。 一般形式: C语言程序设计 第四章 顺序程序设计int i=0,sum=0; while(i<=100) { sum=sum+i; i=i+1; }说明 复合语句“ } ”后不加分号 语法上和其它语句相同 复合语句可嵌套
  • 79. <>4.2 赋值语句 基本格式: 赋值表达式 + ; 赋值表达式可以包含在其它表达式中,而赋值语句不可以。 C语言程序设计 第四章 顺序程序设计例:if ((a=b)>0) t=a; 不可写为:if ((a=b;)>0) t=a;
  • 80. <> C语言程序设计 第四章 顺序程序设计表达式中允许出现运算符号、变量、数值、函数序号语句 含义右侧表达式包括1a=5常量5i=0x30+255十进制、十六进制ch=ch- ‘A’6变量、字符常量7m=a[1]+a[2]数组变量8x=*px++指针变量、增1运算2S=pi*r*r变量、乘号求圆面积3average=(a+b)/2变量、常数、括号求平均数4x=l*cos(q)变量、函数求横坐标
  • 81. <>另一种形式的赋值语句 <变量><运算符> = <表达式>; C语言程序设计 第四章 顺序程序设计示例含义a+ = 表达式a= a + (表达式)a % = 表达式a= a %(表达式)a - = 表达式a= a - (表达式)a * = 表达式a= a * (表达式)a / = 表达式a= a / (表达式)我们可以理解为: <变量>=<变量><运算符><表达式>;只适合于 整型变量
  • 82. <>连续赋值语句 C语言程序设计 第四章 顺序程序设计int a , b , c ; a=b=c=1 ;连续赋值语句应“从右向左”计算 a=b=c=1 ; 等价于: a=(b=(c=1) ); 把常数 1 赋给变量c,表达式(c=1) 的值为1; 把表达式(c=1)赋给变量b,表达式(b=(c=1) )的值为1; 将右侧表达式的值1赋给a , a =1 。步骤: int a=b=c=1 ;
  • 83. <>4.3 数据输入输出的概念及在C语言中的实现 C语言程序设计 第四章 顺序程序设计标准输入输出函数 putchar 输出字符, scanf 格式输入,puts 输出字符串 getchar 输入字符, printf 格式输出,gets 输入字符串所谓数据的输入输出是从计算机角度出发的。 C语言本身没有I/O语句,所有I/O都由函数来实现。 C语言的标准库函数 由编译系统提供的一系列函数,以库形式存放在系统中,不是C语言文本的组成部分。 库函数已编译成目标文件(.obj),在连接阶段才与源程序编译成的目标文件相连接,生成可执行文件。 调用形式: 函数名(参数表) 注意在调用C语言库函数时,需要使用编译预处理命令#include <相关的头文件>,使相应的头文件包含到用户源程序中。 #include 或 #include ”stdio.h”Turbo C 2.0可以不加#include命令常用头文件: stdio.h 定义输入输出函数 string.h 定义字符串操作函数 math.h 定义sin、cos等数学函数
  • 84. <>4.4 字符数据的输入输出 putchar 函数(单字符输出函数) C语言程序设计 第四章 顺序程序设计输出一个字符:格式: putchar( ‘字符’); 或 putchar( 字符变量); 强调:被输出的单个字符必须被‘ ’括起来运行结果:BOY /* 例 4.1 putchar(‘字符’)*/ #include void main() { putchar('B'); putchar('O'); putchar('Y'); }/* 例 4.1 putchar(字符变量) */ #include void main() { char a,b,c; a='B'; b=‘O'; c=‘Y'; putchar(a); putchar(b); putchar(c); }结果当然还是一样的!
  • 85. <>输出控制字符 C语言程序设计 第四章 顺序程序设计/* 例 putchar(‘控制字符’) */ #include void main() { char a,b; a=‘O'; b=‘k'; putchar(a); putchar(‘\n’); putchar(b); }运行结果:O k 输出转义字符/*例 putchar( ) 含有转义符* / #include void main() { char a; a='B'; putchar('\101'); putchar(a); }运行结果:AB
  • 86. <>getchar 函数(单字符输入函数) 。 C语言程序设计 第四章 顺序程序设计格式: getchar( ) ; 强调:输入单个字符后,必须按一次回车, 计算机才接受输入的字符。# include 不能少!/*例4.2 */ #include void main() { char c; c=getchar( ); putchar(c); }运行结果: a a
  • 87. <>4.5 格式输入与输出 printf函数(格式输出函数) printf函数的一般格式 C语言程序设计 第四章 顺序程序设计格式: printf( 格式控制,输出表列); 格式控制:用双引号括起来的字符串,包含两种信息 格式说明:%[修饰符]格式字符,指定输出格式 普通字符:原样输出 输出表列:要输出的数据,可以是变量或表达式,可以没有,多个时以“,”分隔)例: printf( “%d %d”,a,b); printf( “a=%d b= %d\n”,a,b); 格式说明普通字符转义字符输出表列
  • 88. <> C语言程序设计 第四章 顺序程序设计/*从最简单的学起 */ #include void main() { printf(“Hello World !” ); }运行结果: Hello World!调用 printf( ) 时可以省略# include 命令!
  • 89. <>格式字符 d格式符:输出十进制整数,有3种用法 %d格式:按数据实际长度输出,数据范围 -32768~32767。 C语言程序设计 第四章 顺序程序设计/* %d 格式的 printf( ) 函数使用 */ #include void main() { int a=3 , b=4; printf(“%d %d\n ”,a,b); printf(“a=%d , b=%d\n”,a,b); }运行结果: 3 4 a=3, b=4格式说明决定最终输出的格式格式说明应与输出列表项个数相同,顺序一致格式说明通常用小写字母表示
  • 90. <>%md格式:m指定输出字段的宽度 数据位数小于m,左端补空格,反之按实际输出。 C语言程序设计 第四章 顺序程序设计 int a=123 , b=12345 ; printf(“%4d %4d ”, a , b); %ld格式:输出长整型数据 可以用%mld格式指定输出列宽 long c=135790 printf(“%ld \n”, c); printf(“%8ld ”, c); 135790 135790 135790 > 32767 ( int 型数据的最大值) 123 12345
  • 91. <>o格式符:八进制输出整数 是将内存中的二进制位整个按八进制输出,所以输出值没有符号。 可以指定输出宽度%mo,长整型可以用%lo格式输出。 C语言程序设计 第四章 顺序程序设计 int a= -1; printf(“%d , %o , %8o , %x ”, a , a , a , a);输出: -1,177777,_ _177777,ffff11 11 11 11 11 11 11 11-1在内存的存放形式(补码)x格式符:十六进制输出整数 同o格式符,无符号,即无负十六进制数。 可以指定输出宽度%mx ,长整型可以用%lx格式输出。
  • 92. <> C语言程序设计 第四章 顺序程序设计u格式符:十进制输出unsigned型数据 int型可以用%u格式输出,unsigned型也可以用%d、%o和%x格式输出。例4.3 无符号数据的输出 #include void main() { unsigned int a=65535; int b= -2; printf(“a=%d , %o , %x , %u\n ”,a,a,a,a); printf(“b=%d , %o , %x , %u\n” ,b,b,b,b); }运行结果: a= - 1 , 177777 , ffff , 65535 b= - 2 , 177776 , fffe , 65534
  • 93. <> C语言程序设计 第四章 顺序程序设计c格式符:输出一个字符 值在0~255的整数,可以用%c形式输出为字符例4.4 字符数据的输出 #include void main() { char c=‘a’; int i=97; printf(“%c , %d\n ”,c,c); printf(“%c , %d\n” ,i ,i); }运行结果: a , 97 a , 97
  • 94. <> C语言程序设计 第四章 顺序程序设计s格式符:输出一个字符串 有%s,%ms,% -ms,%m.ns,% -m.ns五种用法例4.5 字符串的输出 #include void main() { printf(“%3s , %7.2s , %.4s , %-5.3d\n ”, “CHINA”, “CHINA”, “CHINA”, “CHINA”); }运行结果: CHINA , _ _ _ _ _CH , CHIN , CHI _ _m自动=n
  • 95. <> C语言程序设计 第四章 顺序程序设计f格式符:输出实数 %f格式:整数部分全部输出,小数6位。可以有非有效数字输出,因为单精度有效位7位,双精度16位。 %m.nf格式:占m列,其中n位小数,左补空格。 % -m.nf格式:右补空格例4.8 %f格式输出实数时指定小数位数 #include void main() { flot f=123.456; printf(“%f %10f %10.2f %.2f %-10.2f\n”,f,f,f,f,f); }例4.6 %f格式输出实数时的有效位数 #include void main() { flot x,y; x=111111.111;y=222222.222; printf(“%f\n”,x+y); }运行结果: 333333.328125例4.7 %f格式输出双精度实数时的有效位数 #include void main() { double x,y; a=1111111111111.111111111; b=2222222222222.222222222; printf(“%f\n”,x+y); }运行结果: 3333333333333.333010运行结果: 123.456001_ _123.456001_ _ _ _ _ _123.46_ _123.46_ _123.46_ _ _ _
  • 96. <> C语言程序设计 第四章 顺序程序设计e格式符:指数形式输出实数 %e格式:不指定m和n,小数6位,指数部分共5位, 其中e和指数符号各1位,指数值3位。 %m.ne和% -m.ne格式:m、n、-的含义同前面。 没有n时,自动=6 g格式符:输出实数 可以自动根据数值大小选择 f 或 e 格式(选列少的) 不输出无意义的零
  • 97. <> C语言程序设计 第四章 顺序程序设计dx,Xoucse,Efg,G%% 格式字符表十六进制无符号整数不带符号十进制整数十进制整数指数形式浮点小数单一字符字符串八进制无符号整数小数形式浮点小数e和f中较短一种百分号本身int a=100;printf ( “%d”,a);int a=255;printf(“%x”,a);int a=8;printf(“%o”,a);int a=100;printf(“%u”,a);char a=65;printf(“%c”,a);printf(“%s”,“ABC”);float a=567.789;printf(“%e”,a);float a=567.789;printf(“%f”,a);float a=567.789;printf(“%g”,a);printf(“%%”);100ff10100AABC5.677890e+002567.789000567.789%
  • 98. <>scanf 函数(格式输入函数) 一般形式 功能:按指定格式从键盘读入数据,存入地址表指定的存储 单元中,并按回车键结束 格式控制:含义同printf函数 地址表列:变量地址或字符串地址,地址间“,”分隔。 强调:地址列表中每一项必须以取地址运算符&开头。 C语言程序设计 第四章 顺序程序设计格式: scanf(格式控制,地址表列 ) ; 例4.9 用scanf函数输入数据 #include voidmain() { int a , b , c ; scanf(“%d%d%d”,&a,&b,&c) ; printf(“%d, %d, %d\n”,a,b,c) ; }输入:3_4_5 输出:3,4,5
  • 99. <> C语言程序设计 第四章 顺序程序设计例 scanf(“%3d%*4d%f”,&k,&f); 输入 12345678765.43 则 123k, 8765.43f例 scanf(“%2d%*3d%2d”,&a,&b); 输入 1234567 则 12a, 67b例 scanf(“%3c%2c”,&c1,&c2); 输入 abcde  则 ‘a’c1, ‘d’ c2例 scanf(“%4d%2d%2d”,&yy,&mm,&dd); 输入 19991015  则 1999yy, 10 mm, 15 dd
  • 100. <>输入分隔符的指定 一般以空格、TAB或回车键作为分隔符 输入数据时,遇非法输入则认为数据结束 其它字符做分隔符:格式串中两个格式符间有其它字符,则输入时对应位置也要有相同的字符。 C语言程序设计 第四章 顺序程序设计例 scanf(“%d:%d:%d”,&h,&m,&s); 输入 12:30:45 则12 h, 30 m, 45 s例 scanf(“%d%c%f”,&a,&b,&c); 输入1234a123o.26  则 1234 a, ‘a’ b, 123 c非法字符
  • 101. <>4.6 顺序结构程序举例 C语言程序设计 第四章 顺序程序设计例4.10 输入三角形边长,求面积 #include #include void main() { float a,b,c,s,area; scanf("%f,%f,%f",&a,&b,&c); s=1.0/2*(a+b+c); area=sqrt(s*(s-a)*(s-b)*(s-c)); printf("a=%7.2f, b=%7.2f, c=%7.2f, s=%7.2f\n",a,b,c,s); printf("area=%7.2f\n",area); }输入:3,4,6  输出:a= 3.00, b= 4.00, c= 6.00 s= 6.50 area= 5.33文件包含预处理命令变量定义输入数据输出数据
  • 102. <> C语言程序设计 第四章 顺序程序设计例4.11 从键盘输入大写字母,用小写字母输出#include "stdio.h" void main() { char c1,c2; c1=getchar(); printf("%c,%d\n",c1,c1); c2=c1+32; printf("%c,%d\n",c2,c2); } 输入:A  输出:A,65 a,97
  • 103. <> C语言程序设计 第四章 顺序程序设计#include #include void main() { float a,b,c,disc,x1,x2,p,q; scanf("a=%f,b=%f,c=%f",&a,&b,&c); disc=b*b-4*a*c; p=-b/(2*a); q=sqrt(disc)/(2*a); x1=p+q; x2=p-q; printf("\n\nx1=%5.2f\nx2=%5.2f\n",x1,x2); }输入:a=1,b=3,c=2  输出:x1=-1.00 x2=-2.00
  • 104. <> C语言程序设计 第四章 顺序程序设计本章要求 程序的三种基本结构及其特点。 数据输入输出函数及其格式控制。 熟悉Turbo C环境的使用,头文件和帮助系统的使用(ctrl+F1) 课后作业 P86~90页习题: 4.7,4.10(思考) 4.4,4.5,4.6,4.8,4.9(答案写在作业本上) 4.4,4.8,4.9(上机验证) 上机:实验教材:实验3(做好上机准备) 预习第五、六章
  • 105. 第5章 选择结构程序设计 C语言程序设计 第五章 选择结构程序设计关系运算符和关系表达式逻辑运算符和逻辑表达式if语句switch语句程序举例
  • 106. <> 选择结构是三种基本结构之一,其作用是,根据指定的条件所满足的情况转而执行相应的操作。 C语言用关系表达式和逻辑表达式通过if语句实现双分支选择,用switch语句实现多分支选择。 C语言程序设计 第五章 选择结构程序设计5.1 关系运算符和关系表达式 “关系运算”即“比较运算,是对两个值进行比较,比较的结果是得到真假两种值。A>3关系表达式关系运算符
  • 107. <> C语言程序设计 第五章 选择结构程序设计关系运算符及其优先次序 C语言提供6种关系运算符 种类:< <= == >= > != 结合方向:自左向右 优先级别: < (小于) <= (小于等于) > (大于) > = (大于等于) = = (等于) ! = (不等于) 优先级6(高) 优先级7(低)c>a+b // c>(a+b) a>b!=c // (a>b)!=c a==bc // a=(b>c)算术运算符 高 关系运算符 赋值运算符 低
  • 108. <>关系表达式 用关系运算符将两个表达式连接起来的式子 C语言程序设计 第五章 选择结构程序设计关系表达式的值:是逻辑值“真”或“假”,用1和0表示a>b , (a+b)>(b+c) , 5==3int a=3,b=2,c=1,d,f; a>b (a>b)==c b+cb f=a>b>c//表达式值1//表达式值1//表达式值0//d=1//f=0
  • 109. <>关系运算几点注意: C语言程序设计 第五章 选择结构程序设计例 5>2>7>8在C中是允许的, 值为0例 int i=1, j=7,a; a=i+(j%4!=0); 则a=2例 ‘a’>0 结果为 ‘A’>100 结果为10>结合方向自左至右用ASCII值比较
  • 110. <>关系运算中应该注意 C语言程序设计 第五章 选择结构程序设计注意区分“ = ”与“ = = ” int a = 0,b =1; if(a = b) printf(“a equal to b”); else printf(“a not equal to b”);应避免对实数作相等或不等于0的判断 如 1.0/3.0*3.0==1.0 可改写为:fabs(1.0/3.0*3.0-1.0)<1e-6
  • 111. <>5.2 逻辑运算符和逻辑表达式 用逻辑运算符将关系表达式或逻辑量连接起来的式子就是逻辑表达式。 逻辑运算符: C语言提供3种逻辑运算符 C语言程序设计 第五章 选择结构程序设计运算符名称 含义&&逻辑与示例||逻辑或若a 、 b之一为真,则a || b为真!逻辑非若a为真,则!a为假;a为假,则!a为真 若a 、 b同时为真,则a && b为真a && ba || b! a “&&”和“ ||”是双目运算符 “!”是单目运算符
  • 112. <>逻辑运算真值表 C语言程序设计 第五章 选择结构程序设计ab!a!ba&&ba||b真假真假假假真真真假假假假假真真假假真真真假真真例:优先次序 (a>b)&&(x>y) (a==b)||(x==y) (!a)||(a>b)//写成 a>b&&x>y//写成 a==b||x==y//写成 !a||a>b逻辑运算符的优先次序 !(非) , &&(与), ||(或) 优先次序:高(2) (11) (12)低 结合方向:从右向左 从左向右 从左向右
  • 113. <>逻辑表达式 C语言程序设计 第五章 选择结构程序设计C语言中, 运算量: 0表示“假”,运算结果: 0表示“假”, 非0表示“真”, 1表示“真”, 例 a=4;b=5; !a a&&b a||b !a||b 4&&0||2 5>3&&2||8<4-!0 ‘c’&&‘d’值为1值为0值为1值为1值为1值为1//(5>3)&&2||(8<(4-(!0))) 值为1
  • 114. <>逻辑运算中的注意点: 短路特性:逻辑表达式求解时,并非所有的逻辑运算符都被执行,只是在必须执行下一个逻辑运算符才能求出表达式的解时,才执行该运算符。 C语言程序设计 第五章 选择结构程序设计 若 a=1;b=2;c=3;d=4;m=1;n=1; 则 (m=a>b)&&(n=c>d) a&&b&&c //只在a为真时,才判别b的值; 只在a、b都为真时,才判别 c的值 a||b||c //只在a为假时,才判别b的值; 只在a、b都为假时,才判别 c的值//结果m=0,n=1
  • 115. <>复杂逻辑条件的表述 判断某一年year是否为闰年 C语言程序设计 第五章 选择结构程序设计判别闰年的条件(int year): 能被4整除: year%4==0 能被4整除但不能被100整除: (year%4==0)&&(year%100!=0) 能被400整除: year%400==0 综合起来: ((year%4==0)&&(year%100!=0))||year%400==0此表达式为真时是闰年优化语句: (year%4==0&&year%100!=0)||year%400==0
  • 116. <>5.3 if 语句(条件选择语句) If语句的三种形式 形式一: 格式:if (表达式) 语句 执行过程: C语言程序设计 第五章 选择结构程序设计表达式语句非0=0main() { int x , y ; x=20 ; y=10 ; if (x>y) printf(“%d”,x); }没有“;”
  • 117. <> C语言程序设计 第五章 选择结构程序设计形式二: 格式:if (表达式) 语句1 else 语句2 执行过程:表达式语句1语句2非0=0main() { int x , y ; x=20 ; y=10 ; if (x>y) printf(“%d”,x); else printf(“%d”,y); }
  • 118. <> C语言程序设计 第五章 选择结构程序设计形式三: 格式:if (表达式1) 语句1 else if (表达式2) 语句2 else if (表达式3) 语句3 …… else if (表达式m) 语句m else 语句n 执行过程:表达式1语句1非0=0表达式2表达式3语句n语句3语句2非0非0=0=0例:if (number>500) cost=0.15 ; else if (number>300) cost=0.1 ; else if (number>100) cost=0.075 ; else if (number>50) cost=0.05 ; else cost=0 ; 必须有“ ;”
  • 119. <> C语言程序设计 第五章 选择结构程序设计几点说明: if后面的表达式类型任意if 后面的语句可以是复合语句,必须要加{ } if(a = =b&&x= =y) printf(“a=b,x=y”); if(3) printf(“OK”); if(‘a’) printf(“%d”,a);考虑下面程序的输出结果: main() { int x,y; scanf(“%d,%d”,&x,&y); if(x>y) x=y; y=x; else x++; y++; printf(“%d,%d\n”,x,y); }Compile Error!{ }后没有“ ;”
  • 120. <> C语言程序设计 第五章 选择结构程序设计 #include void main() { int a,b; printf("Enter integer a:"); scanf("%d",&a); printf("Enter integer b:"); scanf("%d",&b); if(a= =b) printf("a==b\n"); else printf("a!=b\n"); }例:输入两个数并判断两数是否相等运行:Enter integer a:12 Enter integer b:12 a==b 运行:Enter integer a:12 Enter integer b:9 a!=b
  • 121. <> C语言程序设计 第五章 选择结构程序设计#include void main() { char c; printf("Enter a character:"); c=getchar(); if(c<32) printf("The character is a control character\n"); else if(c>='0'&&c<='9') printf("The character is a digit\n"); else if(c>='A'&&c<='Z') printf("The character is a capital letter\n"); else if(c>='a'&&c<='z') printf("The character is a lower letter\n"); else printf("The character is other character\n"); }例:判断输入字符种类运行:Enter a character:  The character is a control character运行:Enter a character:8  The character is a digit运行: Enter a character: D The character is a capital letter运行: Enter a character: h The character is a lower letter运行: Enter a character:F1  The character is other character
  • 122. <> C语言程序设计 第五章 选择结构程序设计 #include void main() { float a,b,t ; scanf("%f,%f",&a,&b); if(a>b) {t=a;a=b;b=t;} printf("%5.2f,%5.2f",a,b); }例5.1:输入两个实数,按由小到大的次序输出两数输入:3.6, -3.2  输出:-3.20, 3.60
  • 123. <> C语言程序设计 第五章 选择结构程序设计 #include void main() { float a,b,c,t ; scanf("%f,%f,%f",&a,&b,&c); if(a>b) {t=a;a=b;b=t;} if(a>c) {t=a;a=c;c=t;} if(b>c) {t=b;b=c;c=t;} printf(“%5.2f,%5.2f,%5.2f”,a,b,c); }例5.2:输入三个数,按由小到大的次序输出输入:3,7,1  输出:1.00,3.00,7.00
  • 124. <>If 语句的嵌套 If语句中又包含一个或多个if语句称为if语句的嵌套。 实际上只要将前述if语句的形式1和2中的内嵌语句用一个if语句代替,即成为if语句的嵌套。 嵌套的if语句还可以嵌套另一个if语句,形成多重嵌套。 一般形式: C语言程序设计 第五章 选择结构程序设计if (条件1) if (条件2) 语句1 else 语句2 else if(条件3) 语句3 else 语句4内嵌if内嵌if
  • 125. <>if 嵌套的几种变形 C语言程序设计 第五章 选择结构程序设计if (条件1) 语句1 else if (条件2) 语句2 else 语句3内嵌ifif (条件1) if (条件2) 语句1 else 语句2 else 语句3内嵌ifif (条件1) if (条件2) 语句1 else if (条件3) 语句2 else 语句3内嵌ifif (条件1) {if (条件2) 语句1} else if (条件3) 语句2 else 语句3内嵌if内嵌if注意:else 总是与前面最近的if 配对。内嵌if内嵌if是这样吗?必要时用{ }限定内嵌if范围
  • 126. <>例:输入两个数并判断其大小关系 C语言程序设计 第五章 选择结构程序设计 #include void main() { int x,y; printf("Enter integer x,y:"); scanf("%d,%d",&x,&y); if(x!=y) if(x>y) printf("X>Y\n"); else printf("XY Enter integer x,y:12,12 X==Y
  • 127. <>if ~ else 配对原则:缺省{ }时,else总是和它上面离它最近的未配对的if 配对。 C语言程序设计 第五章 选择结构程序设计if(……)if(……)if(……)else…...else…...else…...例 考虑下面程序的输出结果 main() { int x=100,a=10,b=20; int v1=5,v2=0; if(a
  • 128. <> C语言程序设计 第五章 选择结构程序设计 程序1: main( ) { int x,y; scanf(“%d”,&x); if(x<0) y= -1; else if(x= =0) y=0; else y=1; printf(“x=%d,y=%d\n”,x,y); } 程序2: main( ) { int x,y; scanf(“%d”,&x); if(x>=0); if(x>0) y=1; else y=0; else y= -1 printf(“x=%d,y=%d\n”,x,y); } 程序3: main( ) { int x,y; scanf(“%d”,&x); y= -1; if(x!=0) if(x>0) y=1; else y=0; printf(“x=%d,y=%d\n”,x,y); }输入 :-2 得到:x=-2,y=0 程序3改: main( ) { int x,y; scanf(“%d”,&x); y= -1; if(x!=0) { if(x>0) y=1;} else y=0; printf(“x=%d,y=%d\n”,x,y); }例5.3 有一函数 -1 (x<0) y= 0 (x=0) 1 (x>0) 编一程序,输入一个x值,输出y值。请考虑: y=1或y=0时,if语句应该如何写? { }什么情况下可以不要?
  • 129. <>条件运算符 if语句中,当表达式为“真”和“假”时,都只执行一个赋值语句给同一个变量赋值时,可以用条件运算符处理。 C语言程序设计 第五章 选择结构程序设计 if (a>b) max=a; else max=b; max=(a>b)? a:b;表达式1 ? 表达式2 : 表达式3表达式1表达式2值表达式3值非0=0条件运算符是 C 语言中唯一的三目运算符
  • 130. <>条件运算符练习 C语言程序设计 第五章 选择结构程序设计例 求 a+|b| printf(“a+|b|=%d\n”,b>0?a+b:a-b);例 (a==b)?’Y’:’N’ (x%2==1)?1:0 (x>=0)?x:-x (c>=‘a’ && c<=‘z’)?c-’a’+’A’:c条件运算符几点说明: 条件运算符可嵌套 优先级: 13 结合方向:自右向左 表达式1?表达式2:表达式3 类型可以不同,表达式值取表达式2和表达式3中较高的类型x?‘a’:‘b’ //x=0,表达式值为‘b’; x≠0,表达式值为‘a’ x>y?1:1.5 //x>y ,值为1.0; xb)? a:b; //max=a>b? a:b; 嵌套:x>0?1:(x<0?-1:0) a>b?a:c>d?c:d  a>b?a:(c> d?c:d)
  • 131. <> C语言程序设计 第五章 选择结构程序设计例5.4 输入一个字母,大写转小写,然后输出字母 #include void main() { char ch; scanf("%c",&ch); ch=(ch>=‘A’ && ch<=‘Z’)? (ch+32) : ch; printf(“%c“,ch); }输入:A 输出:a
  • 132. <>5.4 switch语句(多分支选择语句) 一般形式: C语言程序设计 第五章 选择结构程序设计switch(表达式e) { case C1: 语句1; break; case C2: 语句2; break; ……. case Cn: 语句n; break; [default:语句n+1; break;] }switch表达式语句组1语句组2语句组n语句组…...C 1C 2Cndefaultcase 执行过程需要跳出switch语句时使用
  • 133. <>switch几点说明 C1,C2,…Cn是常量表达式,且值必须互不相同 常量表达式起语句标号作用,必须用break跳出 case后可包含多个可执行语句,且不必加{ } switch可嵌套 多个case可共用一组执行语句 C语言程序设计 第五章 选择结构程序设计#include main() { char grade; grade =getchar(); switch(grade) { case ‘A’ : printf(“85~100 \n”); case ‘B’ : printf(“70~84 \n”); case ‘C’ : printf(“60~69 \n”); case ‘D’ : printf(“<60 \n”); default : printf(“Error \n”); } }A 85~100 70~84 60~69 <60 Error 缺少 break;#include main() { char grade; grade =getchar(); switch(grade) { case ‘A’ : printf(“85~100 \n”); break; case ‘B’ : printf(“70~84 \n”); break; case ‘C’ : printf(“60~69 \n”); break; case ‘D’ : printf(“<60 \n”); break; default : printf(“Error \n”); } }A 85~100如: …… case ‘A’: case ‘B’: case ‘C’: printf(“score>60\n”); break; ……..
  • 134. <> C语言程序设计 第五章 选择结构程序设计#include void main( ) { int x=1,y=0,a=0,b=0; switch(x) { case 1: switch(y) { case 0: a++; break; case 1: b++; break; } case 2: a++;b++; break; case 3: a++;b++; } printf(“\na=%d,b=%d”,a,b); } a=2 , b=1 例 switch嵌套
  • 135. <>5.5 程序举例 C语言程序设计 第五章 选择结构程序设计例5.5 判断某一年是否闰年#include ① void main() { int year,leap; scanf(“Enter year:%d”,&year); if(year%4==0) { if(year%100==0) { if(year%400==0) leap=1; else leap=0;} else leap=1;} else leap=0; if(leap) printf(“%d is”,year); else printf(“%d is not”,year); printf(“a leap year.\n”); }{ }能省略吗?#include ② void main() { int year,leap; scanf(“Enter year:%d”,&year); if(year%4!=0) leap=0; else if(year%100!=0) leap=1; else if(year%400!=0) leap=0; else leap=1; if(leap) printf(“%d is”,year); else printf(“%d is not”,year); printf(“a leap year.\n”); }③使用逻辑表达式 #include void main() { int year,leap; scanf(“Enter year:%d”,&year); if((year%4==0&&year%100!=0)||(year%400==0)) leap=1; else leap=0; if(leap) printf(“%d is”,year); else printf(“%d is not”,year); printf(“a leap year.\n”); }
  • 136. <> C语言程序设计 第五章 选择结构程序设计例 根据输入的字母输出相应的字符串#include void main() { int c; printf("Enter m or n or h or other:"); c=getchar(); switch(c) { case 'm': printf(" Good morning!\n");break; case 'n': printf(" Good night!\n"); break; case 'h': printf(" Hello!\n"); break; default : printf(" ????????\n"); } }m Good morning!
  • 137. <> C语言程序设计 第五章 选择结构程序设计例5.6 求ax2+bx+c=0方程的解#include #include void main() { float a,b,c,d,disc,x1,x2,realpart,imagpart; scanf(“%f,%f,%f”,&a,&b,&c); printf(“The equation”); if(fabs(a)<=1e-6) printf(“is not a quadratie”); else {disc=b*b-4*a*c; if(fabs(disc)<=1e-6) printf(“has two equal roots:%8.4f\n”,-b/(2*a)); else if(disc>1e-6) {x1=(-b+sqrt(disc))/(2*a); x2=(-b-sqrt(disc))/(2*a); printf(“has has distinct real roots:%8.4f and %8.4f\n”,x1,x2);} else { realpart=-b/(2*a); imagpart=sqrt(-disc)/(2*a); printf(“has complex roots:\n”); printf(“%8.4f + %8.4fi\n”,realpart,imagpart); printf(“%8.4f + %8.4fi\n”,realpart,imagpart); } } }
  • 138. <> C语言程序设计 第五章 选择结构程序设计例5.7 计算运费#include void main() { int c,s; float p,w,d,f; scanf(“%f,%f,%d”,&p,&w,&s); if(s>=3000) c=12; else c=s/250; switch(c) { case 0: d=0;break; case 1: d=2;break; case 2: case 3: d=5;break; case 4: case 5: case 6: case 7: d=8;break; case 8: case 9: case 10: case 11: d=10;break; case 12: d=15;break; } f=p*w*s*(1-d/100.0); printf(“freight=%15.4f”,f); }
  • 139. <> C语言程序设计 第五章 选择结构程序设计本章要求 关系运算符、逻辑运算符,运算符的优先级。 if语句、switch语句的概念及其应用。 课后作业 P111~112页习题: 5.2(思考) 5.3,5.5,5.6,5.8,5.9(答案写在作业本上) 参考实验4分别用if和switch实现5.5,5.6(上机验证) 上机: 本章例题和作业程序的调试 实验教材:实验4(做好上机准备) 预习第六章
  • 140. <> C语言程序设计 第五章 选择结构程序设计补充习题 编程实现:输入整数a和b,若a2+b2大于100,则输出a2+b2百位以上的数字,否则输出a+b之和。 编程实现:输入一个整数,判断它能否被3、5、7整除,并输出以下信息之一: 能同时被3、5、7整除; 能被其中两数(要指出哪两个)整除; 能被其中一个数(要指出哪一个)个整除; 不能被3、5、7任一个整除。
  • 141. 第6章 循环控制 C语言程序设计 第六章 循环控制概述goto语句以及用goto语句构成循环while语句do-while语句for语句循环的嵌套几种循环的比较break语句和continue语句程序举例
  • 142. <>6.1 概述 程序中凡涉及求阶乘、累加、排序等问题都要用循环解决,因为程序中的某一程序段要重复执行若干次。 C语言实现循环的语句: goto 和if组合 while语句 do while语句 for语句 C语言程序设计 第六章 循环控制重点
  • 143. <>6.2 goto语句以及用goto语句构成循环 作用:无条件地转移到语句标号指向的语句去执行。 一般格式: C语言程序设计 第六章 循环控制 goto 语句标号; ….….. 标号:语句; 说明: 语句标号由字母、数字和下划线组成,定名规则同变量名,不能用数字开头。 goto loop; ( √ ) goto 100;(×) 与循环语句配合使用时,可从循环体内跳到循环体外,而不能从循环体外跳到循环体内。 goto语句转移的方向可前可后。 与if语句配合使用时可构成循环。 goto 语句违背结构化程序设计的原则,因此应限制使用。
  • 144. <> C语言程序设计 第六章 循环控制例6.1 用if 和goto语句构成循环,求#include void main( ) { int i,sum=0; i=1; loop: if(i<=100) { sum+=i; i++; goto loop; } printf("%d",sum); }sum=0+1 sum=1+2=3 sum=3+3=6 sum=6+4 …… sum=4950+100=5050循环初值循环终值循环变量增值循环条件循环体
  • 145. <> C语言程序设计 第六章 循环控制例 从键盘输入一组数据,以0结束输入,求数据和。#include void main() { int number,sum=0; read_loop: scanf("%d",&number); if(!number) goto print_sum; sum+=number; goto read_loop; print_sum: printf("The total sum is %d\n",sum); }
  • 146. <>6.3 while语句 while语句实现“当型”循环结构。 一般形式: C语言程序设计 第六章 循环控制 while(表达式) 循环体语句;没有“;”功能:先判断表达式,若为真则执行循环体,再判断表达式,重复上述过程,直到表达式为假时退出循环。 求sum=sum+i i=i+1i=1;sum=0i≤100假真i=1;sum=0当i≤100 sum=sum+i i=i+1
  • 147. <> C语言程序设计 第六章 循环控制#include void main( ) { int i,sum=0; i=1; while(i<=100) { sum=sum+i; i++; } printf("%d",sum); }循环条件循环体例6.2 用while语句构成循环,求循环初值循环终值循环变量增值
  • 148. <>关于while循环语句: while循环先判断表达式,后执行循环体。循环体有可能一次也不执行。 循环体若包含一个以上语句,应该用{}括起来。 循环体应包含有使循环趋向结束的语句; 下列情况,退出while循环 条件表达式不成立(为零) 循环体内遇 break , goto 无限循环 while(1) 循环体 ; C语言程序设计 第六章 循环控制
  • 149. <> C语言程序设计 第六章 循环控制例 用while语句显示1~10的平方#include void main() { int i=1; while(i<=10) { printf("%d*%d=%d\n",i,i,i*i); i++; } }1*1=1 2*2=4 3*3=9 4*4=16 5*5=25 6*6=36 7*7=49 8*8=64 9*9=81 10*10=100
  • 150. <>6.4 do-while语句 do-while语句实现“当型”循环结构。 一般形式: C语言程序设计 第六章 循环控制功能:先执行循环体,然后判断表达式。若为真,则再次执行循环体,否则退出循环。 求do 循环体语句; while(表达式) ; 有“;”i=1,sum=0sum=sum+i i=i+1i≤100真假i=1,sum=0sum=sum+i i=i+1 直到i>100
  • 151. <> C语言程序设计 第六章 循环控制例6.3 用do-while语句构成循环,求#include void main( ) { int i,sum=0; scanf("%d",&i); do { sum+=i; i++; } while(i<=100); printf("%d",sum); }循环条件循环体#include void main() {int i,sum=0; scanf("%d",&i); while(i<=100) { sum+=i; i++; } printf("%d",sum); }比较do-while 循环,循环体至少执行一次; while和do-while可以解决同一问题,两者可以互换。 while后的表达式一开始就为假时,两种循环结果不同。输入:1 输出: 5050 5050输入:101 输出: 101 0
  • 152. <>6.5 for语句 for 语句是 C 语言中最为灵活,使用最广泛的循环语句,可完全替代while,do-while语句。 一般形式 C语言程序设计 第六章 循环控制 for(表达式1;表达式2;表达式3) 循环体语句;常用形式 for(循环变量赋初值;循环条件;循环变量增值) 循环体语句;
  • 153. <> C语言程序设计 第六章 循环控制#include void main( ) { int i,sum=0; for(i=1;i<=100;i++) sum+=i; printf("%d",sum); }i≤ 100sum=sum+iNYi=1i ++for循环下面的语句循环步长例 用for语句构成循环,求
  • 154. <>几点说明: for语句中表达式1、2、3类型任意,都可省略,但分号“;”不能省。 无限循环:for(;;)不断执行循环体,循环不终止。 For语句可以转换成while结构 C语言程序设计 第六章 循环控制表达式1; while(表达式2) { 循环体语句; 表达式3; }
  • 155. <>几种形式: C语言程序设计 第六章 循环控制省略表达式1:应在for之前为变量赋初值。/*正常形式*/ main( ) { int i ,sum=0; for(i=1;i<=100;i++) sum=sum+i; printf("%d",sum); }/*省略表达式1*/ main( ) { int i,sum=0; i=1; for(;i<=100;i++) sum=sum+i printf("%d",sum); }省略表达式2:循环条件始终为“真”,循环不终止。省略表达式3:应另外设法使程序能够结束。/*省略表达式3*/ main( ) { int i,sum=0; for(i=1;i<=100;) {sum=sum+i i++;} printf("%d",sum); }省略表达式1、3:完全等同于while语句。/*省略表达式1、3*/ main( ) { int i,sum=0; i=1; for(;i<=100;) {sum=sum+i i++;} printf("%d",sum); }三个表达式都省略:无初值,不判断条件,循环变量 不增值,死循环。
  • 156. <> C语言程序设计 第六章 循环控制表达式1、3可以是与循环无关的表达式,也可以是逗号表达式。 for ( s=0 , i=1 ; i<=100 ; i++ ) s=s+i;/*表达式是逗号表达式*/ main() { int i,j,k; for(i=0,j=100;i<=j;i++,j--) { k=i+j; printf("%d+%d=%d\n",i,j,k); } }表达式2可以是关系、逻辑、算术、字符表达式,非0时,执行循环体,为0时退出循环。#include main() { char c; for(;(c=getchar())!='\n';) printf("%c ",c); }#include main() { int i,c; for(i=0;(c=getchar())!='\n';i+=c) printf("%d ",i+c); }
  • 157. <>6.6 循环的嵌套 定义:一个循环体内又包含了另一个完整的循环结构,称为循环的嵌套。 三种循环可以互相嵌套,层数不限。 嵌套循环的执行流程。 C语言程序设计 第六章 循环控制(1) while() { …… while() { …… } …... }(2) do { …… do { …… } while(); …... } while( );(3) for(;;) { …… for(;;) { …… } }(4) while() { …… do { …… } while(); ……. }
  • 158. <> C语言程序设计 第六章 循环控制(5) for( ; ;) { …… while() { …… } …... }(7) for( ; ;) { …… do { …… } while(); …… while() { …… } …... }(6) do { …… for(; ;) { …… } …... } while();循环可以互相嵌套,但不能相互交叉。 for for …… …... …... for for …… …... …...
  • 159. <> C语言程序设计 第六章 循环控制例 计算3组1~4累加的和#include void main() { int i,j,s=0; for(i=1;i<=3;i++) for(j=1;j<=4;j++) s=s+j; printf(“s=%d\n",s); }结果:s=301 2 3 i j s=01 1 11 3 62 1 112 2 132 4 203 1 213 2 233 3 263 4 302 3 161 4 10
  • 160. <> C语言程序设计 第六章 循环控制例 循环嵌套,输出九九乘法表1234567891234567892468101214161836912151821242791827364554637281……………..ijvoid main() { int i,j; for(i=1;i<10;i++) printf("%4d",i); printf("\n------------------------------------\n"); for(i=1;i<10;i++) for(j=1;j<10;j++) printf((j==9)?"%4d\n":"%4d",i*j); }条件运算符: j=9,输出i*j,再回车换行。 j≠9,只输出i*j。
  • 161. <> 九九乘法表逻辑框图 C语言程序设计 第六章 循环控制i<10printfNYi=1j++j=1j<10YNi++for(i=1;i<10;i++) for(j=1;j<10;j++) printf((j==9)?"%4d\n":"%4d",i*j);外循环内循环
  • 162. <>6.7 几种循环的比较 C语言程序设计 第六章 循环控制语 句适用范围 说 明while只知道结束条件 而无法确定执行 次数的情况下。① 循环变量初始化在循环体之前 ② 循环体中应包含使循环结束的语句 ③ 可以用 break 和continue 语句控制do-while至少执行一次时if~goto无条件循环 该循环不能用break 和continue 语句控制for已知执行次数或 者已知初值,终 值,步长时。使用比较灵活
  • 163. <>6.8 break语句和continue语句 Break语句 功能:在循环语句和switch语句中,终止并跳出循环体或开关体。 说明: break只能终止并跳出最近一层的结构。 break不能用于循环语句和switch语句之外的任何其它语句之中。 一般形式:break; C语言程序设计 第六章 循环控制
  • 164. <>流程形式: C语言程序设计 第六章 循环控制表达式…… break; ……假(0)真(非0)whiledo…… break; …...表达式假(0)真(非0)while表达式2…… break; …...假(0)真(非0)for表达式1表达式3
  • 165. <> C语言程序设计 第六章 循环控制switch表达式语句组1 break;语句组2 break;语句组n break;语句组 break;…...const 1const 2const ndefaultcase
  • 166. <> C语言程序设计 第六章 循环控制例 break举例:输出圆面积,面积大于100时停止#include #define PI 3.14159 void main( ) { int r ; float area; for(r=1;r<=10;r++) { area=PI*r*r ; if(area>100) break; printf("r=%d,area=%f",r,area); } }r ≤ 10area=3.14*r*rNYr =1i ++for循环下面的语句area>100NY使用break跳出整个循环输出: r=1, area=3.14 r=2, area=12.57 r=3, area=28.27 r=4, area=50.27 r=5, area=78.85 / * 当 r=6时, area=113.10 故此值没有被 输出 */
  • 167. <> C语言程序设计 第六章 循环控制例 break举例:小写字母转换成大写字母,直至输入非字母字符#include void main() {char c; while(1) { c=getchar(); if(c>='a' && c<='z') putchar(c-32); else if(c>=‘A' && c<=‘Z') putchar(c); else break; } }break 使无限循环结束
  • 168. <>Continue语句 功能:结束本次循环,跳过循环体中尚未执行的语句,进行下一次是否执行循环体的判断。 continue 语句仅用于循环语句中。 C语言程序设计 第六章 循环控制break 和 continue 语句的区别continue 语句只结束本次循环,break语句则是结束整个循环。 continue 语句只用于while,do-while,for循环语句中,break语句还可以用于switch语句中。
  • 169. <>流程形式: C语言程序设计 第六章 循环控制表达式…… continue; ……假(0)真(非0)while真(非0)do…… continue; …...表达式假(0)while表达式2…… continue; …...假(0)真(非0)for表达式1表达式3
  • 170. <> C语言程序设计 第六章 循环控制例6.5 把100~200之间不能被3整除的数输出#include void main() { int i; for(i=100;i<=200;i++) { if(i%3= =0) continue; printf(“%d”,n); } }使用continue 结束本次循环i ≤ 200NYi =100i ++for循环下面的语句i%3= =0YprintfN运行结果: 100,101, 103,104, 106,107, 109,110, 112,113, 115,116, 118,119,
  • 171. <> C语言程序设计 第六章 循环控制例 求输入的十个整数中正数的个数及其平均值#include void main() { int i,num=0,a; float sum=0; for(i=0;i<10;i++) { scanf("%d",&a); if(a<=0) continue; num++; sum+=a; } printf("%d plus integer's sum :%6.0f\n",num,sum); printf("Mean value:%6.2f\n",sum/num); }
  • 172. <>6.9 程序举例 C语言程序设计 第六章 循环控制t=1,pi=0,n=1.0,s=1当|t|1e-6pi=pi+tn=n+2s=-st=s/npi=pi*4输出pi分子:1,-1,1,-1… 分母:1,3,5,7,...#include #include void main() { int s; float n,t,pi; t=1; pi=0; n=1.0; s=1; while((fabs(t))>=1e-6) { pi=pi+t; n=n+2; s= -s; t=s/n; } pi=pi*4; printf("pi=%10.6f\n",pi); }运行结果: pi=3.141594
  • 173. <> C语言程序设计 第六章 循环控制例6.7 求Fibonacci数列:1、1、2、3、5、8……前40个数。 Fibonacci数列可以用一个有趣的古典数学问题来描述:有一对兔子,出生三个月后每个月都生一对兔子。小兔子长到三个月后每个月又生一对兔子。假设所有的兔子都不死,问每个月的兔子总数是多少对?月数小兔中兔老兔总数1111111111123450200002352……………
  • 174. <> C语言程序设计 第六章 循环控制f1=1,f2=1for i=1 to 20输出f1,f2f1=f1+f2 f2=f2+f1#include #include void main() { long int f1,f2; int i; f1=1; f2=1; for(i=1;i<=20;i++) { printf("%12ld %12ld ",f1,f2); if(i%2==0) printf("\n"); f1=f1+f2; f2=f2+f1; } }1 5 34 233 1597 10946 75025 514229 3524578 241578171 8 55 377 2584 17711 121393 832040 5702887 390881692 13 89 610 4181 28657 196418 1346269 9227465 632459863 21 144 987 6765 46368 317811 2178309 14930352 102334155
  • 175. <> C语言程序设计 第六章 循环控制例6.8 判断m是否素数。#include #include void main() { int m,i,k; scanf("%d",&m); k=sqrt(m); for(i=2;i<=k;i++) if(m%i==0) break; if(i>k) printf("%d is a prime number\n",m); else printf("%d is not a prime number\n",m); }读入mk=i=2当ikm被i整除真假用break 结束循环i=i+1ik+1真假输出”是素数”输出”不是素数” 19  19 is a prime number
  • 176. <> C语言程序设计 第六章 循环控制例6.9 求100~200间的全部素数。 由于不是求一个数是否素数,因此需要使用双循环嵌套。外层第一个循环,用于在100~200间提取一个数,然后内层第二个循环进行判断。#include #include void main() { int m, k, i, n=0; for(m=101;m<=200;m=m+2) { k=sqrt(m); for(i=2;i<=k;i++) if(m%i==0) break; if(i>=k+1) {printf("%d",m);n=n+1;} if(n%10==0) printf("\n"); } printf("\n"); }运行结果: 101 103 107 109 113 127 131 137 139 149 157 163 167 173 179 181 191 193 197 199
  • 177. <> C语言程序设计 第六章 循环控制例6.10 译密码。按一定规律将电文变成密码: 将字母A变为E、将字母a变为e,即变成其后的第四个字母,W将变成A。字母按上述规律转换,非字母字符不变。输入一行字符,输出相应密码。分析: 由于字符和整数之间可以通用,所以‘A’->’E’对应‘A’->’A’+4 可以定义一个字符型变量c,c接受输入,并c->c+4。 特殊之处是‘W’-’Z’和‘w’-’z’之间时,它们需要对应为‘A’-’D’和‘a’-’d’,怎么办? 一种是用书上的办法,再减回去,即用c->c-26来解决。ABCDEFGHIJKLMNOPQRSTUVWXYZ
  • 178. <> C语言程序设计 第六章 循环控制#include void main() { char c; while((c=getchar())!='\n') { if((c>='a'&&c<='z')||(c>='A'&&c<='Z')) { c=c+4; if(c> 'Z'&&c<= 'Z'+4||c>'z') c=c-26; } printf("%c",c); } printf(“\n"); } Hello,world!  Lipps,asvph!
  • 179. <>本章小结: 问题求解的过程和步骤叫算法,如求π值的算法、验证素数的算法。算法分析是程序设计的第一步,也是最重要的步骤。用某种编程程序语言来表达算法是程序设计的目的。 用编程语言实现结构化算法就是结构化程序设计。 结构化算法中只包含顺序、分支和循环三种控制结构。 在C语言中实现上述三种结构的控制语句分别是顺序语句,分支语句和循环语句。 if/if else语句在使用时应注意else和最近一个没有被else匹配的if匹配。 ?运算符相当于根据不同情况对同一变量赋值的if/else语句的简写形式。 C语言程序设计 第六章 循环控制
  • 180. <>switch语句实现多路选择,应用时应注意其条件表达式值为整型或字符型,且每个分支应用break语句结束。 while和do while语句在应用时要注意后者至少执行一次循环体。 for循环应用时要注意其控制结构中各个表达式的作用及执行次序。for(表达式1;表达式2;表达式3)→表达式1是初始执行,仅执行一次;表达式2接下来执行,以判断是否退出循环,如果执行了循环,接下来执行表达式3,对循环条件进行某中改变,然后再到表达式2进行判断…… 注意break和continue的区别,break是结束本层循环,continue是结束本次循环。 C语言程序设计 第六章 循环控制
  • 181. <> C语言程序设计 第六章 循环控制本章要求 初步熟悉用计算机解决问题的思路和方法。 掌握while, do while, for语句的特点和使用方法。 掌握break, continue语句的用法。 熟悉一些常见问题的算法及其C语言实现。 课后作业 P129~130页习题: 6.1,6.2,6.3,6.4,6.6,6.7(第一次) 6.8,6.9,6.10,6.14,6.15(第二次) 6.11,6.12,6.13(提高题) 上机: 本章例题和作业程序的调试 实验教材:实验5(做好上机准备) 预习第七章
  • 182. 第7章 数组 C语言程序设计 第七章 数组一维数组的定义和引用二维数组的定义和引用字符数组
  • 183. <> C语言程序设计 第七章 数组用基本数据类型可以解决所有问题吗? 例如:对学生的成绩按由高到低的次序进行排序。 3 名?stud01,stud02,stud03300 名?stud001,stud02,……stud300 ? 数组属于构造类型。 数组:是具有一定顺序关系的若干相同类型变量的集合, 用数组名标识。 元素:组成数组的变量,用数组名和下标确定
  • 184. <>7.1 一维数组的定义和引用 一维数组的定义 定义方式: 数据类型 数组名[常量表达式]; C语言程序设计 第七章 数组例 int a[6]; 合法标识符表示元素个数 下标从0开始[ ] : 数组运算符 单目运算符 优先级(1),左结合 不能用( )a[0]0145a[1]a[2]a[3]a[4]a[5]23a编译时分配连续内存 内存字节数=数组大小× 每元素的字节数组名表示内存首地址,是地址常量例 int i=15; int data[i]; (不能用变量定义数组维数)例 int data[5]; //C语言对数组不作越界检查, data[5]=10; 使用时要 注意
  • 185. <>一维数组元素的引用 数组必须先定义,后使用 只能逐个引用数组元素,不能一次引用整个数组。 数组元素表示形式: 数组名[下标] 其中:下标可以是常量或整型表达式 C语言程序设计 第七章 数组例 int a[10]; printf(“%d”,a); () 必须 for(j=0;j<10;j++) printf(“%d\t”,a[j]); ()例7.1 #include void main() { int i,a[10]; for(i=0;i<=9;i++) a[i]=i; for(i=9;i>=0;i- -) printf(“%d”,a[i]); }运行结果: 9 8 7 6 5 4 3 2 1 0
  • 186. <>一维数组的初始化 C语言程序设计 第七章 数组实现的方法: 在定义数组时对数组元素赋初值。只给一部分元素赋值。在定义数组时,为数组元素赋初值 (在编译阶段使之得到初值)int a[5]={1,2,3,4,5}; 等价于:a[0]=1; a[1]=2; a[2]=3; a[3]=4; a[4]=5;如 int a[5]={6,2,3}; 等价于: a[0]=6; a[1]=2;a[2]=3; a[3]=0; a[4]=0; 如 int a[3]={6,2,3,5,1}; ()数组元素值全部为0。int a[5]={0,0,0,0,0}; 或int a[5]={0}; 对整个数组元素赋初值时,可以不指定长度。int a[]={1,2,3,4,5,6}; 编译系统根据初值个数确定数组大小
  • 187. <>一维数组程序举例 C语言程序设计 第七章 数组例 读10个整数存入数组,找出其中最大值和最小值步骤: 1. 输入:for循环输入10个整数 2. 处理: (a) 先令max=min=x[0] (b) 依次用x[i]和max,min比较(循环) 若maxx[i],令min=x[i] 3. 输出:max和min #include #define SIZE 10 void main() { int x[SIZE],i,max,min; printf("Enter 10 integers:\n"); for(i=0;ix[i]) min=x[i]; } printf("Maximum value is %d\n",max); printf("Minimum value is %d\n",min); }
  • 188. <> C语言程序设计 第七章 数组例7.2 用数组来处理求Fibonacci数列问题#include void main() { int i; int f[20]={1,1}; for(i=2;i<20;i++) f[i]=f[i-2]+f[i-1]; for(i=0;i<20;i++) { if(i%5==0) printf("\n"); printf("%12d",f[i]);} }f[0]f[1]f[2]f[3]f[4]f[5]f[19]……...11f[19]01452319235运行结果: 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
  • 189. <> C语言程序设计 第七章 数组例7.3 用起泡法对10个数排序(由小到大)排序过程: (1)比较第一个数与第二个数,若a[0]>a[1],则交换;然后比较第二 个数与第三个数;依次类推,直至第n-1个数和第n个数比较为止 ——第一趟起泡排序,结果最大的数被安置在最后一个元素位置上 (2)对前n-1个数进行第二趟冒泡排序,结果使次大的数被安置在第n-1 个元素位置 (3)重复上述过程,共经过n-1趟冒泡排序后,排序结束9 8 8 8 8 8 8 9 5 5 5 5 5 5 9 4 4 4 4 4 4 9 2 2 2 2 2 2 9 0 0 0 0 0 0 98 5 5 5 5 5 8 4 4 4 4 4 8 2 2 2 2 2 8 0 0 0 0 0 85 4 4 4 4 5 2 2 2 2 5 0 0 0 0 54 2 2 2 02 4 0 0 0 42 0 0 2第一轮大数沉底 第二轮 第三轮 第四轮 第五轮 此处:n=6 外层循环j(1~n-1)次 内层循环i (1~n-j)次
  • 190. <> C语言程序设计 第七章 数组输入n 个数给a[1] 到 a[n]for j=1 to n-1for i=1 to n-ja[i]>a[i+1]真假a[i]a[i+1]输出a[1] 到 a[n]#include void main() { int a[10],i,j,t; printf("Input 10 numbers:\n"); for(i=0;i<10;i++) scanf("%d",&a[i]); printf("\n"); for(j=0;j<9;j++) for(i=0;i<9-j;i++) if(a[i]>a[i+1]) {t=a[i]; a[i]=a[i+1]; a[i+1]=t;} printf("The sorted numbers:\n"); for(i=0;i<10;i++) printf("%d ",a[i]); }
  • 191. <> C语言程序设计 第七章 数组例 用简单选择法对10个数排序排序过程: (1)首先通过n-1次比较,从n个数中找出最小的, 将它与第一个数 交换—第一趟选择排序,结果最小的数被安置在第一个元素位置上 (2)再通过n-2次比较,从剩余的n-1个数中找出关键字次小的记录, 将它与第二个数交换—第二趟选择排序 (3)重复上述过程,共经过n-1趟排序后,排序结束初始: [ 49 38 65 97 76 13 27 ]i=1一趟: 13 [38 65 97 76 49 27 ]i=2二趟: 13 27 [65 97 76 49 38 ]三趟: 13 27 38 [97 76 49 65 ]四趟: 13 27 38 49 [76 97 65 ]五趟: 13 27 38 49 65 [97 76 ]六趟: 13 27 38 49 65 76 [97 ]
  • 192. <> C语言程序设计 第七章 数组输入n 个数给a[1] 到 a[n]for i=1 to n-1for j=i+1 to na[j] void main() { int a[11],i,j,k,x; printf("Input 10 numbers:\n"); for(i=1;i<11;i++) scanf("%d",&a[i]); printf("\n"); for(i=1;i<10;i++) { k=i; for(j=i+1;j<=10;j++) if(a[j]
  • 193. <>7.2 二维数组的定义和引用(多维数组) 二维数组的定义 定义的一般形式 类型说明符 数组名[常量表达式][常量表达式]; C语言程序设计 第七章 数组行数列数元素个数=行数*列数例 int a[3][4]; float b[2][5]; int c[2][3][4]; int a[3,4]; ()数组元素的存放顺序 原因:内存是一维的 二维数组:按行序优先 多维数组:最右下标变化最快int a[3][2]a[0][1]a[1][0]a[1][1]a[2][0]a[2][1]014523a[0][0]a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1]int c[2][3][4]0 1 2 34 5 6 7………...20 21 22 23c[0][0][0]c[0][0][1]c[0][0][2]c[0][0][3]c[0][1][0]c[0][1][1]c[0][1][2]c[0][1][3]c[0][2][0]c[0][2][1]c[0][2][2]c[0][2][3]c[1][0][0]c[1][0][1]c[1][0][2]c[1][0][3]c[1][1][0]c[1][1][1]c[1][1][2]c[1][1][3]c[1][2][0]c[1][2][1]c[1][2][2]c[1][2][3]
  • 194. <>二维数组理解 C语言程序设计 第七章 数组例 int a[3][4]; 2016 172018 192020 212022 232008 92010 112012 132014 152000 12002 32004 520006 7a[0][0]a[0][1]a[0][2]a[0][3]a[1][0]a[1][1]a[1][2]a[1][3]a[2][0]a[2][1]a[2][2]a[2][3]每个元素a[i]由包含4个元素 的一维数组组成二维数组a是由3个元素组成a[0]a[1]a[2]行名a[0][1]a[0][2]a[0][3]a[1][0]a[1][1]a[0][0]a[1][3]a[2][0]a[2][1]a[2][2]a[2][3]a[1][2]01452367101189a[0]a[1]a[2]
  • 195. <>二维数组的引用 形式: 数组名[下标][下标] 下标是整型或字符型的常量,变量或表达式。(定义时不能使用变量) 如: a[1][2] a[i][j] 数组元素可出现在表达式中,如: a[1][2]=a[2][2]/2 使用数组元素时,应注意不要超出其定义的范围; 如: int a[2][3]; a[2][3]=5; C语言程序设计 第七章 数组
  • 196. <> C语言程序设计 第七章 数组二维数组的初始化 分行初始化按元素排列顺序初始化 例 int a[2][3]={{1,2,3},{4,5,6}}; a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]123456全部初始化 例 int a[2][3]={{1,2},{4}}; a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]120400部分初始化 例 int a[][3]={{1},{4,5}}; a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]100450第一维长度省略初始化 例 int a[2][3]={1,2,3,4,5,6}; a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]123456全部初始化 例 int a[2][3]={1,2,4}; a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]124000部分初始化 例 int a[][3]={1,2,3,4,5}; a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]123450第一维长度省略初始化
  • 197. <>二维数组程序举例 C语言程序设计 第七章 数组例7.4 将二维数组行列元素互 换,存到另一个数组中#include void main() { int a[2][3]={{1,2,3},{4,5,6}}; int b[3][2],i,j; printf("array a:\n"); for(i=0;i<=1;i++) { for(j=0;j<=2;j++) { printf("%5d",a[i][j]); b[j][i]=a[i][j];} printf("\n"); } printf("array b:\n"); for(i=0;i<=2;i++) { for(j=0;j<=1;j++) printf("%5d",b[i][j]); printf("\n");} } a=1 2 3 4 5 6b=1 4 2 5 3 6
  • 198. <> C语言程序设计 第七章 数组例7.5 求二维数组中最大元素值及其行列号max=a[0][0]for i=0 to 2for j=0 to 3a[i][j]>max真假max=a[i][j] row=i colum=j输出:max和row,colum#include void main() { int a[3][4]={{1,2,3,4}, {9,8,7,6},{-10,10,-5,2}}; int i,j,row=0,colum=0,max; max=a[0][0]; for(i=0;i<=2;i++) for(j=0;j<=3;j++) if(a[i][j]>max) { max=a[i][j]; row=i; colum=j; } printf("max=%d,row=%d, colum=%d\n",max,row,colum); }
  • 199. <> C语言程序设计 第七章 数组例 读入下表中值到数组,分别求各行、各列及表中所有数之和12 4 615 7 9 8 23 3 2 5 1712 4 6 2215 7 9 31 8 23 3 34 2 5 17 2437 39 35 111#include void main() { int x[5][4],i,j; for(i=0;i<4;i++) for(j=0;j<3;j++) scanf("%d",&x[i][j]); for(i=0;i<3;i++) x[4][i]=0; for(j=0;j<5;j++) x[j][3]=0; for(i=0;i<4;i++) for(j=0;j<3;j++) { x[i][3]+=x[i][j]; x[4][j]+=x[i][j]; x[4][3]+=x[i][j]; } for(i=0;i<5;i++) { for(j=0;j<4;j++) printf("%5d\t",x[i][j]); printf("\n"); } }
  • 200. <>7.3 字符数组 字符数组:存放字符数据的数组。 一维字符数组:存放一个字符串(每个数组元素存放一个字符) 二维字符数组:存放多个字符串(行数是字符串的个数) 字符数组的定义 形式: char 数组名[常量表达式] char 数组名[常量表达式][常量表达式] 常量表达式:整数、字符、符号常量 C语言程序设计 第七章 数组例 char c[10], ch[3][4];可以用整型数组存放字符型数据,但浪费存储空间。
  • 201. <>字符数组的初始化 逐个字符赋值 用字符串常量 C语言程序设计 第七章 数组 例 char ch[5]={‘H’,’e’,’l’,’l’,’o’}; ch[0]Hello逐个字符赋值ch[1]ch[2]ch[3]ch[4] 例 char ch[4]={‘H’,’e’,’l’,’l’,’o’}; ch[0]Hello逐个字符赋值ch[1]ch[2]ch[3]ch[4]有问题! 例 char ch[5]={‘B’,’o’,’y’}; ch[0]Boy\0\0逐个字符赋值ch[1]ch[2]ch[3]ch[4] 例 char ch[ ]={‘H’,’e’,’l’,’l’,’o’}; ch[0]Hello逐个字符赋值ch[1]ch[2]ch[3]ch[4] 例 char diamond[][5]={{' ', ' ','*'},{' ','*',' ','*'}, {'*', ' ', ' ', ' ' ,'*'},{' ','*', ' ','*'},{' ', ' ','*'}}; 二维字符数组初始化*\0\0**\0****\0*\0\0diamond[0]diamond[1]diamond[2]diamond[3]diamond[4]
  • 202. <> C语言程序设计 第七章 数组例7.6 输出一个字符串#include void main() { char c[10]={'I',' ','a','m',' ','a',' ','b','o','y'}; int i; for(i=0;i<10;i++) printf("%c",c[i]); printf("\n"); }Iamaboy0123456789字符数组的引用
  • 203. <> C语言程序设计 第七章 数组例7.7 输出一个钻石图形#include void main() { char diamond[ ][5]={{' ',' ','*'},{' ','*',' ','*'},{'*',' ',' ',' ','*'}, {' ','*',' ','*'},{' ',' ','*'}}; int i,j; for(i=0;i<5;i++) {for(j=0;j<5;j++) printf("%c",diamond[i][j]); printf("\n"); } }运行结果: * * * * * * * *
  • 204. <>字符串和字符串结束标志 字符串:用双引号括起的若干字符,如: “china” 可将其存放在一维或两维字符型数组中。 无字符串变量,用字符数组处理字符串 字符串结束标志:‘\0’,(既无动作,又不显示) 字符串的长度:第一个‘\ 0’以前字符的个数 在字符型数组或字符串中遇‘\ 0’,即认为该字符串结束。 系统对字符串常量自动加一个‘\0’作为结束符。 printf(“china”); C语言程序设计 第七章 数组china\0
  • 205. <>用字符串常量初始化字符数组 C语言程序设计 第七章 数组 例 char ch[6]={“Hello”}; char ch[6]=“Hello”; char ch[]=“Hello”; 用字符串常量ch[0]Helloch[1]ch[2]ch[3]ch[4]\0ch[5] 例 char fruit[][7]={”Apple”,”Orange”, ”Grape”,”Pear”,”Peach”}; 二维字符数组初始化fruit[0]fruit[1]fruit[2]fruit[3]fruit[4]Apple\0\0Orange\0Grape\0\0Pear\0\0\0Peach\0\0
  • 206. <>字符数组的输入输出 逐个字符I/O: %c 整个字符串I/O: %s C语言程序设计 第七章 数组例 用%s void main() { char str[5]; scanf(“%s”, str); printf(“%s”, str); }用字符数组名,不要加& 输入串长度<数组维数 遇空格或回车结束 自动加‘\0’用字符数组名, 遇‘\0’结束例 用%c void main() { char str[5]; int i; for(i=0;i<5;i++) scanf(“%c”, &str[i]); for(i=0;i<5;i++) printf(“%c”, str[i]); }输入:China  输出:China 输入:Program  输出: Progr
  • 207. <> C语言程序设计 第七章 数组#include void main() { char a[ ]={'h','e','l','\0','l','o','\0'}; printf("%s",a); }其它注意事项:输出:helh e l \0 l o \0数组中有多个‘\0’时, 遇第一个结束
  • 208. <> C语言程序设计 第七章 数组H o w \0a r e \0y o u ? \0#include void main() { char a[15],b[5],c[5]; scanf("%s%s%s",a,b,c); printf("a=%s\nb=%s\nc=%s\n",a,b,c); scanf("%s",a); printf("a=%s\n",a); }运行情况: 输入:How are you? 输出:a=How b=are c=you? 输入:How are you? 输出:a=Howscanf中%s输入时,遇空格或回车结束运行情况: 输入:How are you?
  • 209. <> C语言程序设计 第七章 数组例 若准备将字符串“This is a string.”记录下来, 错误的输入语句为: (A)char s[20]; scanf(“%20s”,s); (B)for(k=0;k<17;k++) s[k]=getchar(); (C)while((c=getchar())!=‘\n’) s[k++]=c; (D)char a[5],b[5],c[5],d[10]; scanf(“%s%s%s%s”,a,b,c,d);
  • 210. <>字符串处理函数 包含在头文件 string.h 中 字符串输出函数 puts 格式: puts(字符数组) 功能:向显示器输出一个字符串(输出完,换行) 说明:字符数组必须以‘\0’结束。可以包含转义字符。 输出时‘\0’转换成‘\n’,即输出字符后换行。 C语言程序设计 第七章 数组例: #include void main( ) { char a1[ ]=“china\ nbeijing” ; char a2[ ]=“china\ 0beijing” ; puts(a1); puts(a2); puts(“WUHAN” ); }运行结果: china beijing china WUHAN这里是将 ‘\ 0’  ‘\ n’ 因此光标移 到下行
  • 211. <>字符串输入函数gets 格式:gets (字符数组) 功能:从键盘输入一个以回车结束的字符串放入字符 数组中,并自动加‘\0’。 说明:输入串长度应小于字符数组维数 C语言程序设计 第七章 数组例:gets和scanf输入比较 #include void main( ) { char a1[15], a2[15] ; gets(a1); scanf(“%s”,a2); printf (“a1=%s\ n”,a1); printf (“a2=%s\ n”,a2); }输入:china beijing  china beijing  输出:a1=china beijing a2=china在scanf 中遇空格字符串便结束了, 而gets 中,却将空格 作为字符存入字符型 数组中。注意:puts和gets函数只能输入输出一个字符串。 错 puts(str1,str2) gets(str1,str2)
  • 212. <>字符串连接函数strcat 格式:strcat (字符数组1,字符数组2) 功能:把字符数组2连到字符数组1后面 返值:返回字符数组1的首地址 说明:字符数组1必须足够大 连接前,两串均以‘\0’结束;连接后,串1的‘\0’取 消,新串最后加‘\0’。 C语言程序设计 第七章 数组例: #include void main( ) { char str1[30]={“People’s Republic of “}; char str2[]={China”}; printf (“%s\n”,strcat(str1,str2)); }str1: People’s Republic of \0 str2: china\0 str1: People’s Republic of china\0
  • 213. <>字符串拷贝函数strcpy 格式:strcpy(字符数组1,字符串2) 功能:将字符串2,拷贝到字符数组1中去 返值:返回字符数组1的首地址 说明:字符数组1必须足够大,>字符串2 字符数组1必须是数组名形式(str1), 字符串 2可以是字符数组名或字符串常量。 拷贝时‘\0’一同拷贝 ④不能使用赋值语句为一个字符数组赋值 C语言程序设计 第七章 数组例 char str1[20],str2[20]; str1={“Hello!”}; () str2=str1; () ⑤可以只复制字符串2中的前几个字符,来取 代字符数组1的前几个字符。 strcpy(str1,str2,2) —— 复制前2个。
  • 214. <> C语言程序设计 第七章 数组例7 strcpy与strcat应用举例#include void main() { char destination[25]; char blank[] = " ", c[]= "C++", turbo[] = "Turbo"; strcpy(destination, turbo); strcat(destination, blank); strcat(destination, c); printf("%s\n", destination); }Turbo C++Trbo\0u012345678924Trbo\0u012345678924Trbo\0u012345678924C++
  • 215. <>字符串比较函数strcmp 格式:strcmp(字符串1,字符串2) 功能:比较两个字符串 比较规则:对两串从左向右逐个字符比较(ASCII码), 直到遇到不同字符或‘\0’为止。 返回值:返回int型整数。其值是ASCII码的差值 a. 若字符串1< 字符串2, 返回负整数 b. 若字符串1> 字符串2, 返回正整数 c. 若字符串1== 字符串2, 返回零 说明:字符串比较不能用“==”,必须用strcmp, 虽然编译无错,但结果不对 C语言程序设计 第七章 数组if(str1==str2) printf(“yes”);错if(strcmp(str1,str2)==0) printf(“yes”);对
  • 216. <> C语言程序设计 第七章 数组例:字符比较 #include void main( ) { int i,j,k; char a1[ ]=“wuhan”, a2[ ]=“beijing” ; i=strcmp(a1,a2); j=strcmp(“china”, “korea”); k=strcmp(a2, “beijing” ); printf(“i=%d\ nj=%d\ nk=%d\ n”,i,j,k); }运行结果: i=21 i=w-b=119-98=21 j=-8 j=c-k=99-107=-8 k=0 k=b-b=98-98=0
  • 217. <>字符串长度函数strlen 格式:strlen(字符数组) 功能:计算字符串长度 返值:返回字符串实际长度,不包括‘\0’在内 C语言程序设计 第七章 数组例 对于以下字符串,strlen(s)的值为: (1)char s[10]={‘A’,‘\0’,‘B’,‘C’,‘\0’,‘D’}; (2)char s[ ]=“\t\v\\\0will\n”; (3)char s[ ]=“\x69\082\n”; 答案:1 3 1例:测试字符串长度 #include void main( ) { char a1[10]=“ china” ; printf (“%d\ n”,strlen(a1)); printf (“%d\ n”, strlen(“beijing\ 0wuhan”)); }运行结果:5 7
  • 218. <>大写字母转换成小写字母函数strlwr 格式:strlwr(字符串) 小写字母转换成大写字母函数strupr 格式:strupr(字符串) C语言程序设计 第七章 数组例:字符转换 #include void main( ) { char a1[6]=“CHinA”, a2[ ]=“wuHAn” ; printf (“%s\ n”,strlwr(a1)); printf (“%s\ n”,strupr(a2)); }运行结果:china WUHAN
  • 219. <> C语言程序设计 第七章 数组例7.8 输入一行字符,统计其中的单词个数,单词间空格分开。分析:根据题目要求,可以用一个字符数组来存储输入的这行字符。要统计其中单词数,就是判断该字符数组中的各个字符,如果出现非空格字符,且其前一个字符为空格,则新单词开始,计数num加1。 但这在第一个单词出现时有点特殊,因为第一个单词前面可能没有空格,因此在程序里我们可以人为加上一个标志word,并初始化为0。该标志指示前一个字符是否是空格,如果该标志值为0则表示前一个字符为空格。
  • 220. <> C语言程序设计 第七章 数组例 输入:I am a boy. 当前字符是否空格word原值新单词开始否word新值num值Iamaboy.否0是11是1未01否0是12否1未12是1未02否0是13是1未03否0是14否1未14否1未14否1未14当前字符=空格是否未出现新单词,使word=0,num不累加前一字符为空格(word==0),新单词出现, word=1,num加1前一字符为非空格(word==1),未出现新单词,num不变
  • 221. <> C语言程序设计 第七章 数组输入一字符串给 string i=0 num=0 word=0当((c=string[i])!=‘\0’)c=空格真真假假word=0word=1 num=num+1i=i+1输出:numword==0#include void main() {char string[81]; int i,num=0,word=0; char c; gets(string); for(i=0;(c=string[i])!='\0';i++) if(c==' ') word=0; else if(word==0) {word=1; num++;} printf("There are %d words in the line\n",num); }
  • 222. <> C语言程序设计 第七章 数组例7.9 有3个字符串,要求找出其中最大者。H i g h \0str[0]str[1]str[2]H e l l o \0H o w \0#include #include void main() { char string[20],str[3][20]; int i; for(i=0;i<3;i++) gets(str[i]); if(strcmp(str[0],str[1])>0) strcpy(string,str[0]); else strcpy(string,str[1]); if(strcmp(str[2],string)>0) strcpy(string,str[2]); printf("\nThe largest string is:\n%s\n",string); }
  • 223. <> C语言程序设计 第七章 数组例 比较 int a[2][3]={{5,6},{7,8}}; 与 int a[2][3]={5,6,7,8};5 6 0 7 8 05 6 7 8 0 0例 int a[][10]; float f[2][]={1.2 ,2.2};例 int a[5]; a={2,4,6,8,10};例 int a[10]; float i=3; a[i]=10;例 char name[0]; float weight[10.3]; int array[-100]; h e l l o02314 h e l l o \0023145例 char str[]=“Hello”; char str[]={‘H’,‘e’,‘l’,‘l’,‘o’};
  • 224. <>本章要求 数组是程序设计的常用数据结构,字符串(字符数组)在程序中应用普遍,应掌握它们的意义和用法。 数组(一维和二维)名、数组元素的概念。 数组的初始化方法。 数组元素在内存中的存储顺序。 数据排序算法。 字符串的特点(作为数组处理,最后一字节加‘\0’) 字符串处理函数的应用。 skip C语言程序设计 第七章 数组
  • 225. <> C语言程序设计 第七章 数组作业: 数组练习:7.2 7.3 7.4 7.6 字符数组练习:7.10 7.12 7.13 7.14 提高题:7.7 7.8 7.9 上机: 实验6:⑴、⑵、⑶三个程序调试 预习:第8章 函数补充习题: 已知10个学生的成绩求平均分。 有3个学生四门课成绩,求每个学生的平均分,每门课的平均分。 数学 英语 化学 物理 张三 92 85 68 75 李四 54 88 98 45 王五 61 79 81 40
  • 226. <> C语言程序设计 第七章 数组补充例题例 1 接受键盘输入的两个字符串,并将其首尾相接后输出。每个字符串内部不含空格,两个字符串之间以空白符分隔。分析: 数据结构: 字符串的存储需要用字符数组 算法要点: 字符串输入,可以用具有词处理功能的scanf()函数。 字符串拼接方法:先找到第一个字符串的末尾,然后 将第二个串的字符逐个添加到末尾。 注意,要去掉第一个串的结束符‘\0’,但第二个串的 结束符‘\0’要添加进去。
  • 227. <> C语言程序设计 第七章 数组程序1: #include void main() { char str1[50],str2[20]; int i,j; printf("Enter string No.1:\n"); scanf("%s",str1); printf("Enter string No.2:\n"); scanf("%s",str2); i=j=0; while(str1[i]!='\0') i++; /*寻找字符串str1的尾*/ while((str1[i++]=str2[j++])!=‘\0’) ; /*str2加入到str1*/ printf("string No.1->%s\n",str1); }
  • 228. <> C语言程序设计 第七章 数组例 2 从键盘输入若干行文本,每行以回车结束,以 ctrl+z 作为输入结束符,统计其行数。分析: 数据结构: 由于只统计行数,所以不必使用数组存储文本内容, 只须定义一个字符变量暂存读入的字符。 算法要点: 读入字符可以用 getchar() 函数。 每读入一个字符,要判断是否输入结束 要判断读入的是否回车符,定义一个整型变量对回车符 进行计数,以实现统计行数的功能。
  • 229. <> C语言程序设计 第七章 数组程序2: #include void main() { int c,nl; nl=0; while((c=getchar())!=EOF) if(c=='\n') /*如果是换行,则nl加1*/ ++nl; printf("%d\n",nl); }
  • 230. <> C语言程序设计 第七章 数组例 3 把输入的字符串逆序排列,并显示。分析: 数据结构: 输入的字符串用字符数组存放。 算法要点: 逆序排列用交换算法,求出字符串最后一个字符的下标, 然后将第一个和最后一个交换,第二个和倒数第二个交换, ...。
  • 231. <> C语言程序设计 第七章 数组程序3: #include void main() { char str[80]; int temp,i,j; printf("Enter a string:\n"); scanf("%s",str); for(i=0,j=strlen(str)-1;i
  • 232. <> C语言程序设计 第七章 数组例 4 从键盘输入字符,以 ctrl+z 结束,统计输入的数字 0~9、空白符和其它字符的个数。分析: 数据结构: 定义一个具有 10 个元素的整型数组来存放数字 0~9 的个数 定义两个整型变量来存放空白符和其它字符的个数。 算法要点: 计数用的数组和变量要初始化为0。 用循环结构处理字符读入,内嵌分支结构处理计数。
  • 233. <> C语言程序设计 第七章 数组程序4: #include void main() { int c,i,nwhite,nother,ndigit[10]; /*存放相应的计数值*/ nwhite=nother=0; for(i=0;i<10;i++) /*初始化这些计数值*/ ndigit[i]=0; while((c=getchar())!=EOF) if(c>='0'&&c<='9') ++ndigit[c-'0']; /*相应的ndigit[i]加1*/ else if(c==' '||c=='\n'||c=='\t') ++nwhite; else ++nother; for(i=0;i<10;i++) printf("digit '%d':%d\n",i,ndigit[i]); printf("white space:%d\n",nwhite); printf("other character:%d\n",nother); }
  • 234. <> C语言程序设计 第七章 数组例 5 从键盘输入一个字符串(长度不超过20,其中不含空格),将其复制一份,复制时将小写字母都转换成为大写字母)。分析: 数据结构 定义两个数组,存放字符串。 算法要点 将小写字母 转换为大写字母:小写字母-'a'+'A'。
  • 235. <> C语言程序设计 第七章 数组程序5: #include void main() { char a[20],b[20]; int i; printf("Enter a string:\n"); scanf("%s",a); i=0; do { b[i]=(a[i]>='a'&&a[i]<='z')? /*将a数组中小写字母转为*/ a[i]-'a'+'A':a[i]; /*大写并对b数组赋值*/ } while(a[i++]!='\0'); printf("Copyed string:\n%s\n",b); }
  • 236. <> C语言程序设计 第七章 数组例6 从一个三行四列的整型二维数组中查找第一个出现的负数。分析 算法要点: 用两层嵌套的 for 循环来遍历数组元素,判断是否为负数。 当找到第一个负数时就应该退出循环,为此,应定义一个标记变量,用于标记找到与否的状态,并将此标记加入循环控制条件中,以控制循环在适当时候退出。
  • 237. <> C语言程序设计 第七章 数组程序6: #include void main() { int i,j,found,num[3][4]; printf("Enter 12 integers:\n"); for(i=0;i<3;i++) for(j=0;j<4;j++) scanf("%d",&num[i][j]); found=0; for(i=0;i<3 && !found;i++) for(j=0;j<4 && !found;j++) found=num[i][j]<0; if(!found) printf("not found\n"); else printf("minus number num[%d][%d]:%d\n", i-1,j-1,num[i-1][j-1]); }
  • 238. <> C语言程序设计 第七章 数组例7 用筛选法求100以内的素数分析 数据结构 定义一个具有 100 个元素的数组,用来标记整数 1~100是否素数。0表示素数,1表示非素数。 算法要点 本例使用筛选法:1不是素数,从2开始,每找到一个素数,便将其倍数全部标记为非素数,最后剩下的便是素数。
  • 239. <> C语言程序设计 第七章 数组定义及初始化变量将 1 标记为非素数n=1; n<=100; n++n是素数?YN输出 n将 n 的所有倍数都标记为非素数N-S图
  • 240. <> C语言程序设计 第七章 数组程序7: #include #define SIZE 100 #define PWIDTH 10 void main() { char sieve[SIZE]; int i,n,printcol; for(i=0;i=PWIDTH) { putchar('\n'); printcol=0; } for (i=2*n;i<=SIZE;i=i+n) sieve[i-1]=1; } }/*分行打印n值*//*将能被n整除的数都标记为非素数*/
  • 241. 第8章 函数 C语言程序设计 第八章 函数概述函数定义的一般形式函数参数和函数的值函数的调用函数的嵌套调用函数的递归调用数组作为函数参数局部变量和全局变量变量的存储类别内部函数和外部函数运行一个多文件的程序
  • 242. <>本章学习目标: C语言程序设计 第八章 函数认识到函数是一种简化程序结构的重要手段; 理解函数调用和函数调用过程中的参数传递; 理解函数原型(声明)和怎样写函数原型; 能够用前几章的知识实现简单的函数; 能够用return语句实现函数的返回值; 能够理解函数调用过程中形式参数和实际参数的关系,理解数组名作为函数参数时代表的意义; 能够理解函数的嵌套调用和递归调用机制 。
  • 243. <>8.1 概述 函数的概念 C语言程序设计 第八章 函数一个大的程序一般应分为若干个程序模块,每个模块实现一个特定的功能,这些模块称为子程序,在C语言中子程序用函数实现。mainabca1abb1b2不能被调用所有函数都是 平行的,不能 嵌套定义分为: 库函数和 自定义函数
  • 244. <> C语言程序设计 第八章 函数 一、常规方法:各函数包含在一个文件中 例T8-1.c #include void main( ) {void printstar( ); void print_message( ); printstar( ); print_message( ); printstar( ); } void printstar( ) {printf (“***********************\ n” ); } void print_message( ) {printf (“_ _ _ _ _How_do_you_do!\n”) ;} 运行结果: **************************** How do you do! *********************** *****
  • 245. <> C语言程序设计 第八章 函数二、工程的方法 例:某程序由四个文件组成,其中,一个文件包含主函数,两个文件包含两个被调用函数。一个为工程文件,包含这个程序的三个文件名。 操作:Alt+p Project name :T8-1-4.prj Alt +R 结果同上T8-1-1.c main( ) { p1( ) ; p2( ) ; p1( ) ; }T8-1-2.c p1( ) {printf (“*********************\ n”); }T8-1-3.c p2( ) {printf (“ How do you do!\ n”); }T8-1-4.prj T8-1-1 T8-1-2 T8-1-3
  • 246. <> C语言程序设计 第八章 函数三、文件包含的方法 在主函数中使用文件包含预编译命令,将不在本文件而在其它文件中的函数进行预编译处理把各文件中的函数包含到本文件中来,然后一起进行编译、连接、运行。 T8-1-5.c #include “T8-1-2.c” #include “T8-1-3.c” main( ) {p1( ); p2( ) ; p1( ) ; } 运行结果同上
  • 247. <>几点说明: (1)一个源文件由一个或者多个函数组成。 (2)一个C程序由一个或者多个源文件组成。 (3)C程序的执行从main 函数开始。 (4)所有的子函数都是平行的。 (5)从用户的角度看,函数分库函数和自定义函数。 (6)函数形式: ①无参函数:主调函数无数据传送给被调函数,可带或不带返回值。 ②有参函数:主调函数与被调函数间有参数传递,主调函数可将实参传送给被调函数的形参, 被调函数的数据可返回主调函数。 C语言程序设计 第八章 函数
  • 248. 根据(1)(2)(3)可知,逻辑上一个C语言程序是由函数构成的,C语言程序从主函数开始执行,在主函数中调用其他函数,这些函数可能又调用别的函数,主函数执行完毕代表整个程序结束。主函数只能调用不能被调用。物理上一个程序由一个或者若干个文件(源文件)构成,函数分别放置在这些文件中。
  • 249. <>8.2 函数定义的一般形式 无参函数的定义形式 类型标识符: 用于指定函数带回的值的类型,不写时为int型。 不带回值时可以不写。 C语言程序设计 第八章 函数类型标识符 函数名() { 说明部分 语句 }例 无参函数 printstar( ) { printf(“**********\n”); } 或 printstar(void ) { printf(“**********\n”); }合法标识符函数体
  • 250. <>有参函数定义的一般形式 C语言程序设计 第八章 函数类型标识符 函数名(形式参数表列) { 说明部分 语句 }现代风格:函数返回值类型 隐含为int型函数体例 有参函数(现代风格) int max(int x,int y) { int z; z=x>y?x:y; return(z); }例 有参函数(现代风格) int max(int x, y) { int z; z=x>y?x:y; return(z); }
  • 251. <>空函数 为扩充功能预留,在主调函数中先占一个位置。 C语言程序设计 第八章 函数类型标识符 函数名() { }例 空函数 dummy( ) { }函数体为空对形参的声明的传统方式 即把对形参的声明放在函数定义的下一行类型标识符 函数名(形参表) 形参类型说明 { 说明部分 语句 }例 有参函数(传统风格) int max(x,y) int x,y; { int z; z=x>y?x:y; return(z); }
  • 252. <>8.3 函数参数和函数的值 形式参数和实际参数 形式参数:定义函数时函数名后面括号中的变量名 实际参数:调用函数时函数名后面括号中的表达式 C语言程序设计 第八章 函数例8.2比较两个数并输出大者 #include void main() { int max(int x,int y); int a,b,c; scanf("%d,%d",&a,&b); c=max(a,b); printf("Max is %d",c);} max(int x, int y) { int z; z=x>y?x:y; return(z);}形参实参c=max(a,b);(main 函数)(max 函数)max(int x, int y) { int z; z=x>y?x:y; return(z); } 运行:7,8 Max is 8
  • 253. <>几点说明: 实参可以是常量、变量或表达式。必须有确定的值。当函数调用时,将实参的值传递给形参,若是数组名,则传送的是数组首地址。 形参必须指定类型,只能是简单变量或数组,不能是常量或表达式 形参与实参类型一致,个数相同顺序相同。 若形参与实参类型不一致,自动按形参类型转换———函数调用转换 形参在函数被调用前不占内存;函数调用时为形参分配内存;调用结束,内存释放 实参对形参的数据传送是值传送,也是单向传送,当被调函数的形参发生变化时,并不改变主调函数实参的值。形、实参占据的是不同的存储单元 C语言程序设计 第八章 函数
  • 254. <> C语言程序设计 第八章 函数例:形、实参占据的是不同的存储单元 #include void main( ) {int a=2,b=3; printf (“a=%d, b=%d\ n”,a, b); printf(“&a=%x,&b=%x\n” ,&a,&b); add(a,b); printf(“a=%d,b=%d\n”, a,b); printf(“&a=%x,&b=%x\n”, &a,&b); } add(int x,int y) {x=x+8; y=y+12; printf(“x=%d,y=%d\ n”,x,y); printf(“&x=%x,&y=%x\n”,&x,&y); } 2+8=103+12=1523ffd2ffd4ffd6ffd8xayb运行结果: a=2,b=3 &a=ffd6,&b=ffd8 x=10,y=15 &x=ffd2,&y=ffd4 a=2, b=3 &a=ffd6,&b=ffd8
  • 255. <>函数的返回值 返回语句形式: return(表达式);或 return 表达式; 功能:使程序控制从被调用函数返回到调用函数中,同时把返值带给调用函数 C语言程序设计 第八章 函数
  • 256. 说明: 函数的返回值,必须用 return 语句带回。 return 语句只能把一个返值传递给调用函数。 函数中可有多个return语句,执行哪一个由程序执行情况来定。 if(a>b) return(a); else return(b); return 后的值可以是一个表达式,如:return(x > y ? x : y); 返回值的类型为定义的函数类型,不指定的按整型处理。 如: int max(int x, int y) float min(float a,float b) double abc(float d1,float d2)
  • 257. <>若 return 语句中表达式类型与函数类型不一致,则转换为函数类型。 若无return语句,遇}时,自动返回调用函数。可能返回一个不确定或无用的值 。 无返回值的函数,定义为 void 类型。 C语言程序设计 第八章 函数 printstar() { printf("**********"); } main() { int a; a=printstar(); printf("%d",a); }例:无return语句,函数带回不确定值输出:10void printstar() { printf("**********"); } main() { int a; a=printstar(); printf("%d",a); }编译错误!
  • 258. <> C语言程序设计 第八章 函数 void swap(int x,int y ) { int temp; temp=x; x=y; y=temp; }例:无返回值函数例8.3: 函数返回值类型转换#include void main() { int max(float x,float y); float a,b; int c; scanf("%f,%f",&a,&b); c=max(a,b); printf("Max is %d\n",c); } max(float x, float y) { float z; z=x>y?x:y; return(z); }输入:1.5,2.5 输出:Max is 2
  • 259. <>8.4 函数的调用 主调函数:主动去调用其它函数 被调函数:被其它函数所调用 函数调用的一般形式 函数名(实参表列) 说明: 实参表列:有确定值的数据或表达式 实参与形参个数相等,类型一致,按顺序一一对应,当有多个实参时,实参间用“ ,”分隔 实参表求值顺序,因系统而定(Turbo C 自右向左) 调用无参函数时,实参表列为空,但( )不能省 C语言程序设计 第八章 函数
  • 260. <> C语言程序设计 第八章 函数#include void main() { int f(int a,int b); int i=2,p; p=f(i,++i); printf("%d",p); } int f(int a, int b) { int c; if(a>b) c=1; else if(a==b) c=0; else c=-1; return(c); }例8.4 参数求值顺序按自右向左求值 函数调用等于f(3,3) 运行结果:0按自左向右求值 函数调用等于f(2,3) 运行结果:- 1为使程序有通用性:需自右向左求值时, 改为:j=++i; p=f ( j , j ) ;需自左向右求值时, 改为:j = i ; k = ++ i ; p = f ( j , k ) ;Printf(“%d,%d”,i,i++); /*同样存在此情况*/
  • 261. <>函数调用的方式 按函数在程序中出现的位置,有三种调用方式: 函数语句:以独立的语句去调用函数。不要求有返回值,仅完成一定的操作。 例 printstar(); printf(“Hello,World!\n”); 函数表达式: 函数返回一个确定值,以参加表达式的运算。不可用于void 例 m=max(a,b)*2; 函数参数:函数调用作为另一个函数的参数。 例 printf(“%d”,max(a,b)); /*输出大数*/ m=max(a,max(b,c)); /*三数比大小*/ C语言程序设计 第八章 函数
  • 262. <>对被调用函数的声明和函数原型 对被调用函数要求: 必须是已存在的函数 库函数: #include <*.h> 用户自定义函数:如果被调函数定义在主调函数之后,那么在主调函数中对被调函数作声明。 C语言程序设计 第八章 函数
  • 263. 函数声明 一般形式:函数类型 函数名(形参类型 [形参名],….. ); 或 函数类型 函数名(); 作用:告诉编译系统函数类型、参数个数及类型,以便检验 C语言中函数声明称为函数原型。 函数定义与函数声明不同,声明只与函数定义的第一行相同。声明可以不写形参名,只写形参类型。 函数说明位置:程序的数据说明部分(函数内或外)
  • 264. <> C语言程序设计 第八章 函数#include void main() { float add(float x,float y ); /*对被调用函数的声明*/ float a,b,c; scanf("%f,%f",&a,&b); c=add(a,b); printf("sum is %f",c); } float add(float x, float y) /*函数首部*/ { float z; /*函数体 z=x+y; return(z); } float add(float,float);例8.5 对被调用的函数作声明输入:3.6 ,6.5 输出:sum is 10.100000
  • 265. <>说明: 旧版本C中函数声明不采用函数原型,只声明函数名和函数类型。如: float add( ) 函数调用之前,如果未对函数作声明,则编译系统把第一次遇到的函数形式作为函数声明,并默认为int型。即:函数类型是int型可以不作函数声明,最好作声明。 被调用函数的定义(程序)在主调函数之前,可以不加函数声明。 在所有函数定义前,已在函数外部做了函数声明,则在各主调函数中可以不加函数声明。 C语言程序设计 第八章 函数#include float add(float x, float y) { float z; z=x+y; return(z); } main() { float a,b,c; scanf("%f,%f",&a,&b); c=add(a,b); printf("sum is %f",c); }被调函数出现在主调函数 之前,不必函数说明void main() { float a,b; int c; scanf("%f,%f",&a,&b); c=max(a,b); printf("Max is %d\n",c); } max(float x, float y) { float z; z=x>y?x:y; return(z); }int型函数可不作函数说明char letter(char,char); float f(float,float); int I(float,float); main() {……} char letter(char c1,char c2) {……} float f(float x,float y) {……} Int I(float j,float k) {……}在函数外面做函数说明
  • 266. <> C语言程序设计 第八章 函数main() 调fun() 结束fun() 返回①②④⑥⑦保存: 返回地址 当前现场③恢复: 主调程序现场 返回地址⑤函数调用的执行过程
  • 267. <>8.5 函数的嵌套调用 C语言程序设计 第八章 函数 不允许嵌套定义,函数间的关系是平行的、独立的。 C中的函数: 允许嵌套调用,即在调用某函数过程中又调用另一函数。main( )调用函数a结束a函数b函数调用函数b
  • 268. <> C语言程序设计 第八章 函数#include int fun1(int x,int y); void main(void) { int a,b; scanf(“%d%d”,&a,&b); printf(“The result is:%d\n”,fun1(a,b) ); } int fun1(int x,int y) { int fun2(int m); return ( fun2(x)+fun2(y) ); } int fun2(int m) { return (m*m); }例 输入两个整数,求平方和输入: 3 4 输出: The result is: 25
  • 269. <> C语言程序设计 第八章 函数#include int dif(int x,int y,int z); int max(int x,int y,int z); int min(int x,int y,int z); void main() { int a,b,c,d; scanf("%d%d%d",&a,&b,&c); d=dif(a,b,c); printf("Max-Min=%d\n",d); }例 求三个数中最大数和最小数的差值int dif(int x,int y,int z) { return max(x,y,z)-min(x,y,z); } int max(int x,int y,int z) { int r; r=x>y?x:y; return(r>z?r:z); } int min(int x,int y,int z) { int r; r=x
  • 270. <> C语言程序设计 第八章 函数例8.6 用弦截法求方程 的根yxf(x)0x1x2xf(x1)f(x2)1. 取x1,x2两点,求得f(x1), f(x2) 。 异号:x1,x2之间必有一根。 同号:改变x1, x2,直到f(x1), f(x2)异号为止。 2. 连f(x1),f(x2)两点(弦)交x轴于x。 X点的坐标求法: ①求X点的x坐标 ②从x值得f(x)3. 若f(x)与f(x1)同号, 则根必在(x,x2)区间,此时将x1=x; 若f(x)与f(x2)同号, 则根必在(x1,x)区间,此时将x2=x;4. 重复步骤2和3 ,直到| f(x) | < ε为止, 设ε < 10-6 , 则 f(x)≈0
  • 271. <>用三个函数实现各部分的功能: ① 函数f(x): 求x的函数:x3 - 5x2 +16x-80 ② 函数xpoint(x1,x2): 求弦与x轴交点X的x坐标 ③ 函数root(x1, x2) : 求(x1, x2)区间的实根 C语言程序设计 第八章 函数 求弦与x轴的交点x输入x1,x2,求f(x1),f(x2)直到f(x1)与f(x2)异号y=f(x),y1=f(x1)y与y1同号真假x1=x y1=yx2=x直到 |y|<root=x 输出 rootroot函数main( )调用函数root输出根 x 结束root函数xpoint函数调用函数xpoint调用函数ff函数
  • 272. <> C语言程序设计 第八章 函数#include #include float f(float x) { float y; y=((x-5.0)*x+16.0)*x-80.0; return(y); } float xpoint(float x1, float x2) { float y; y=(x1*f(x2)-x2*f(x1))/(f(x2)-f(x1)); return(y);}float root(float x1,float x2) { float x, y, y1; y1=f(x1); do { x=xpoint(x1, x2);y=f(x); if(y*y1 > 0) { y1=y;x1=x;} else x2=x; }while(fabs(y) >=0.0001); return(x); }void main( ) { float x1, x2, f1, f2, x; do { printf(“input x1, x2:\ n”); scanf(“%f%f”,&x1,&x2); f1=f(x1); f2=f(x2); }while(f1*f2 >=0); x=root(x1, x2); printf(“A root of equation is %8.4f\ n”,x); }运行情况: Input x1,x2: 2,6 A root of equation is 5.0000
  • 273. <>8.6 函数的递归调用 递归:在函数调用过程中,直接或间接的调用自身。 递归调用方式 直接递归调用:在函数体内又调用自身 C语言程序设计 第八章 函数f( )调fint f(int x) { int y,z; …… z=f(y); ……. return(2*z); }
  • 274. <>间接递归调用:当函数1去调用另一函数2时,而另一函数2反过来又调用函数1自身。 C语言程序设计 第八章 函数调f2调f1f1( )f2( )int f1(int x) { int y,z; …… z=f2(y); ……. return(2*z); }int f2(int t) { int a,c; …… c=f1(a); ……. return(3+c); }解决无终止递归调用的方法是:确定好结束递归的条件。 条件成立,进行递归 用if语句控制 条件不成立,结束递归
  • 275. <> C语言程序设计 第八章 函数例8.7 有5个人,第5个人比第4个人大2岁,第4个人比第3个人大2岁,……第2个人比第1个人大2岁,第1个人10岁,问第5个人多大? age(5) age(4) age(3) age(2) age(1) =2+age(4) =2+age(3) =2+age(2) =2+age(1) =10 =18 =16 =14 =12 10 n=1 数学模型:age(n)= age(n-1)+2 n>1age(int n) {int c; if(n==1) c=10; else c=2+age(n-1); return(c); } #include void main( ) {printf(“%d\ n”, age(5));}运行结果:18回推递推
  • 276. <>有些问题,可以用递推,也可以用递归的方法解决。 递推:从一个已知的事实出发,按一定规律推出下一个事实,再从已知的新的事实,推出下一个新的事实. C语言程序设计 第八章 函数例 用递推法求n! ,即从1开始, 乘2, 乘3....一直到n #include void main( ) { int i, s=1; for(i=1;i<=5;i++) s=s* i; printf(“s=%d\ n”,s); }运行结果:s=120
  • 277. <>递归:在函数调用自身时,要给出结束递归的条件。 先回推再递推 如:n!, 5!=5 × 4! 4!=4 × 3! 3!=3 × 2! 2!=2 × 1! 1!=1 0!=1 C语言程序设计 第八章 函数 1 (n=0,1) n!= n*(n-1)! (n>1)#include void main() { float fac(int n); int n; float y; printf("Input a integer number:"); scanf("%d",&n); y=fac(n); printf("%d! =%15d",n,y); } float fac(int n) { float f; if(n<0) printf("n<0,data error!"); else if(n==0||n==1) f=1; else f=fac(n-1)*n; return(f);}运行: input a integer number:10 10! = 3628800例8.8 用递归方法求n!
  • 278. <>十九世纪未,欧洲珍奇商店出现一种汉诺塔游戏,推销材料介绍说:古代印度布拉玛庙里的僧侣们正在玩这种游戏,如果游戏结束,世界未日即来临。是一个只能用递归方法解决的问题。 规则及分析: n个盘子从一根针移到另一根针,每次只能移动一个盘子,不允许大盘在小盘上面。 共有三根针,n个盘子由A移到C,需移动的次数是2n -1, 若64个盘子移动的次数为: 264 - 1=18, 446, 744, 073, 709, 551, 600 一年的秒数是:365 x 24 x 60 x 60=31536000 18446744073709511600÷31536000 =58494217355年 即:5849亿年, 从能源角度推算, 太阳系寿命只有150亿年 C语言程序设计 第八章 函数例8.9 Hanoi(汉诺)塔问题 BCA
  • 279. <>方法与步骤 将A上n-1个盘子借助C移到B 。 把A上剩下一个盘子送到C 将n-1个盘子从B借助A移到C C语言程序设计 第八章 函数BCA简化实例:将A上3个盘子移到C 步骤:1. A上两个盘子借助C移到B 2. A上最后一个盘子移到C (可直接完成) 3. B上两个盘子借助A移到C 第一步进一步分解: 1.1 A上一个盘子从AC 1.2 A上一个盘子从AB 1.3 C上一个盘子从CB 第三步进一步分解: 3.1 B上一个盘子从BA 3.2 B上一个盘子从BC 3.3 A上一个盘子从AC共移动7步:23-1次 所以,n个盘要移动2n-1次
  • 280. <>结论:上面三个步骤包含两类操作 步骤1和3都是将n-1个盘子从一个针移到另一个针上(n>1时),这是一个递归的过程;方法一样,只是针的名称不同而已,为使问题一般化,将步骤1和3表示为:将one 针上的n-1个盘子移到two针,借助 three针,只是对应关系不同。 第一步对应关系:one  A two  B three  C 第三步对应关系:one  B two  C three  A 将1个盘子从一个针上移到另一针上。 因此,可以用两个函数分别实现上面两类操作,用hanoi函数实现第一类操作,用move函数实现第2类操作。 hanoi(n,one,two,three) 将n个盘从 one → three借助two move(x,y) 将1个盘从x → y座,x、y根据情况取代ABC座中的1个。 C语言程序设计 第八章 函数
  • 281. <> C语言程序设计 第八章 函数例8.9 用递归方法解决Hanoi(汉诺)塔问题的程序 #include void main() { void hanoi(int n,char one,char two,char three); int m; printf("Input the number of diskes:"); scanf("%d",&m); printf("The step to moving %3d diskes:\n",m); hanoi(m,'A','B','C');} void hanoi(int n,char one,char two,char three) {void move(char x, char y); if(n==1) move(one,three); else { hanoi(n-1,one,three,two); move(one,three); hanoi(n-1,two,one,three); }} void move(char x, char y) { printf("%c--->%c\n",x, y); }运行: input number of diskes: 3 the step to moving 3 diskes: A C A B C B A C B A B C A C
  • 282. <>8.7 数组作为函数参数 数组元素作函数实参——值传递 C语言程序设计 第八章 函数例8.10 两个数组比较大小 a和b为有10个元素的整型数组 比较两数组对应元素 变量n,m,k分别记录a[i]>b[i], a[i]==b[i], a[i]k,认为数组a>b 若n
  • 283. <> C语言程序设计 第八章 函数#include void main() { int large(int x,int y) int a[10],b[10],i,n=0,m=0,k=0; printf("Enter array a:\n"); for(i=0;i<10;i++) scanf("%d",&a[i]); printf("\n"); printf("Enter array b:\n"); for(i=0;i<10;i++) scanf("%d",&b[i]); printf("\n"); for(i=0;i<10;i++) { if(large(a[i],b[i])==1) n=n+1; else if(large(a[i],b[i])==0) m=m+1; else k=k+1; } printf(“a[i]>b[i]%d times\n”,n); printf(“a[i]=b[i]%d times\n”,m); printf(“a[i]k) printf(“array a is larger than array b\n”); else if(ny) flag=1; else if(x b[i] 3 time a[i] = b[i] 1 time a[i] < b[i] 1 time array a is large then array b
  • 284. <>数组名可作函数参数 实参和形参都应用数组名 C语言程序设计 第八章 函数例8.11 求学生的平均成绩 float average(float array[10]) { int i; float aver,sum=array[0]; for( i=1; i<10; i++ ) sum=sum+array[i]; aver=sum/10; return (aver); }#include void main() { float average(float array[10]); float score[10], aver; int i; printf("Input 10 scores: \n"); for( i=0; i<10; i++ ) scanf("%f", &score[i]); printf(“\n”); aver=average(score); printf("Average is: %5.2f", aver); }实参用数组名形参用数组定义float array[ ]..2109score562312….….88array
  • 285. <>几点说明: C语言程序设计 第八章 函数地址传递 调用函数时,对形参数组元素的操作,实际上也是对实参数组元素的操作。 在主调函数与被调函数分别定义数组,且类型应一致 如:array是形参数组名,score是实参数组名。
  • 286. 形参数组大小(多维数组第一维)可不指定 在定义数组时在数组名后面跟一个空的方括弧 C编译对形参数组大小不检查,即使定义了也不起作用。 形参数组名是地址变量 调用时,只是将实参数组的首地址传给形参数组, 因此score[n]和array[n]指的是同一单元
  • 287. <> C语言程序设计 第八章 函数例8.12 求两组学生的平均成绩,形参数组长度缺省 #include void main() { float average(float array[ ],int n); float score_1[5]={98.5,97,91.5,60,55}; float score_2[10]={67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5}; printf(“The average of clase A is %6.2f\n”,average(score_1,5)); printf(“The average of clase B is %6.2f\n”,average(score_2,10)); } float average(float array[ ],int n) { int i; float aver,sum=array[0]; for( i=1; i
  • 288. <>数组名作函数参数时,实参和形参两个数组共占同一段内存单元,形参数组的元素值改变会使实参数组元素的值同时变化。 C语言程序设计 第八章 函数例8.13 用选择法对数组中的10个整数按由小到大排序
  • 289. #include void main() { void sort(int array[ ],int n); int a[10],i; printf(“enter the array\n”); for(i=0;i<10;i++) scanf("%d",&a[i]); sort(a,10); printf(“the sorted array: \n”); for(i=0;i<10;i++) printf("%d ",a[i]); printf("\n");}
  • 290. <> C语言程序设计 第八章 函数void sort(int array[ ],int n) { int i,j,k,t; for(i=0;i
  • 291. <> C语言程序设计 第八章 函数kjjkjkjjjjj0123456789a4968573299927137688array949kk1368i=1void sort(int array[ ],int n) { int i,j,k,t; for(i=0;i
  • 292. <> C语言程序设计 第八章 函数0123456789a9132732495768768899arrayi=8void sort(int array[ ],int n) { int i,j,k,t; for(i=0;i
  • 293. <>用多维数组名作函数参数 可以用多维数组名作实参和形参 形参数组定义时,只能省略第一维的大小说明。 C编译不检查第一维的大小,而且数组名作函数参数是地址传送,所以形参数组第一维大小任意,可以和实参数组的维数不同。 实参数组定义:int score[5][10] 形参数组定义:int array[3][10] 或 int array[8][10] 合法的定义:int array[3][10]; 或 int array[ ][10] 错误的定义:int array[ ][ ]; int array[3][ ]; C语言程序设计 第八章 函数
  • 294. <> C语言程序设计 第八章 函数例8.14 求3×4矩阵中各元素的最大值 #include void main() {int max_value(int array[ ][4]); int a[3][4]={{1,3,5,7},{2,4,6,8},{15,17,34,12}}; printf("max value is %d\n",max_value(a)); } int max_value(int array[3][4]) { int i,j,k,max; max=array[0][0]; for(i=0;i<3;i++) for(j=0;j<4;j++) if(array[i][j]>max) max=array[i][j]; return(max); }多维形参数组第一维维数 可省略,第二维必须相同  int array[][4]
  • 295. <> C语言程序设计 第八章 函数例 求二维数组中各行元素之和get_sum_row(int x[][3], int result[] ,int row, int col) { int i,j; for(i=0;i
  • 296. <>8.8 局部变量和全局变量 变量按其作用域,可分为局部变量和全局变量。 局部变量——内部变量 定义:在函数内定义,只在本函数内有效 说明: main中定义的变量只在main中有效 不同函数中同名变量,占不同内存单元 形参属于局部变量 可定义在复合语句中有效的变量 局部变量可用存储类型:auto register static (默认为auto) C语言程序设计 第八章 函数
  • 297. <> C语言程序设计 第八章 函数float f1(int a) { int b,c; ……. } char f2(int x,int y) { int i,j; …… } main() { int m,n; ……. }a,b,c有效x,y,i,j有效m,n有效例 不同函数中同名变量void main() { int a,b; a=3; b=4; printf("main:a=%d,b=%d\n",a,b); sub(); printf("main:a=%d,b=%d\n",a,b); } sub() { int a,b; a=6; b=7; printf("sub:a=%d,b=%d\n",a,b); }运行结果: main:a=3,b=4 sub:a=6,b=7 main:a=3,b=4
  • 298. <> C语言程序设计 第八章 函数运行结果:5 4 3 2 1例 复合语句中变量#define N 5 void main() { int i; int a[N]={1,2,3,4,5}; for(i=0;i
  • 299. <>全局变量——外部变量 定义:在函数外定义,可为本文件所有函数共用,也叫外部变量。 有效范围:从定义变量的位置开始到本源文件结束,及有extern说明的其它源文件 几点说明: 全局变量的使用,增加了函数间数据联系的渠道,同一文件中的所有函数都能引用全局变量的值,当某函数改变了全局变量的值时,便会影响其它的函数。 C语言程序设计 第八章 函数
  • 300. 习惯上,全局变量名的第一个字母用大写。 使用全局变量可以减少函数的实参和形参个数。 不必要时不要使用全局变量 全局变量在程序执行的全过程都占用存储单元。 不利于程序的移植。程序的可读性变差。 全局与局部变量重名时,在函数内部将屏蔽全局变量。
  • 301. <> C语言程序设计 第八章 函数int p=1,q=5; float f1(a) int a; { int b,c; ……. } int f3() {….. } char c1,c2; char f2(int x,int y) { int i,j; …… } main() { int m,n; ……. }c1,c2的作用范围p,q的作用范围
  • 302. <> C语言程序设计 第八章 函数例 全局变量的作用域及其使用情况int a=1; f1( ) {int b; b=a+3; printf(“f1:a=%d, b=%d\ n”,a, b); } f2( ) {int a, b; a=5; b=a+3; printf(“f2: a=%d, b=%d\ n”,a, b); } f3( ) {int b; a=6; b=a+3; printf(“f3:a=%d, b=%d\ n”,a, b); } void main( ) { int b=3; printf(“1.main : a=%d, b=%d\ n”,a, b); f1( ); printf(“2.main : a=%d, b=%d\ n”,a, b); f2( ); printf(“3.main : a=%d, b=%d\ n”,a, b); f3( ); printf(“4.main : a=%d, b=%d\ n”,a, b); }运行: 1.main:a=1, b=3 f1:a=1, b=4 2.main:a=1, b=3 f2:a=5, b=8 3.main:a=5, b=3 f3:a=6, b=9 4.main:a=6, b=3全局变量增加了函数间传送数据的联系局部变量和全局变量同名,局部变量作用域中外部变量被屏蔽局部变量外部变量
  • 303. <> C语言程序设计 第八章 函数例8.15 一维数组内存放了10个学生成绩,求平均分、最高分和最低分。#include float Max=0,Min=0; void main() { float average(float array[ ],int n); int i; float ave,score[10]; for(i=0;i<10;i++) scanf("%f",&score[i]); ave=average(score,10); printf("max=%6.2f\nmin=%6.2f\n average=%6.2f\n",Max,Min,ave); } float average(float array[], int n) { int i; float aver, sum=array[0]; Max=Min=array[0]; for(i=1;iMax) Max=array[i]; else if(array[i]
  • 304. <> C语言程序设计 第八章 函数例8.16 外部变量与局部变量同名#include int a=3,b=5; void main() { int max(int a, int b); int a=8; printf("max=%d",max(a,b)); } int max(int a, int b) { int c; c=a>b?a:b; return(c); }运行结果:max=8例 外部变量副作用int i; main() { void prt(); for(i=0;i<5;i++) prt(); } void prt() { for(i=0;i<5;i++) printf(“%c”,’*’); printf(“\n”); }运行结果:*****原意输出5行*号,使用外部变量i 后只输出一行*号。局部变量a=8将外部变量a=3屏蔽
  • 305. <>8.9 变量的存储类别 动态存储方式与静态存储方式 变量分类: 按数据类型:整型、实型、字符型 按作用域:全局变量、局部变量 存储方式: 静态存储:程序运行期间分配固定的存储空间。 动态存储:程序运行期间根据需要动态分配存储空间。 内存用户区 C语言程序设计 第八章 函数程序区静态存储区动态存储区全局变量、局部静态变量形参变量 局部动态变量(auto register) 函数调用现场保护和返回地址等生存期: 静态变量:从程序开始执行到程序结束 动态变量:从包含该变量定义的函数开始执行至函数执行结束
  • 306. <>auto变量 函数内部无static声明的局部变量均为动态存储类别,被分配在动态区 。 存储类别为自动时,声明符auto可省;自动变量被 分配在动态区,未赋初值时,其值未定义,每次调用重新赋值。 C语言程序设计 第八章 函数例如: int f(int a) /*定义f函数,a为形参*/ {auto int b,c=3; /*定义b、c为自动变量*/ … } 又如:auto int b,c=3; int b,c=3; /*两者等价*/
  • 307. <> C语言程序设计 第八章 函数例 auto 变量的作用域main() { int x=1; void prt(void); { int x=3; prt(); printf(“2nd x=%d\n”,x); } printf(“1st x=%d\n”,x); } void prt(void) { int x=5; printf(“3th x=%d\n”,x); }运行结果: 3th x=5 2nd x=3 1st x=1x=1作用域x=1作用域x=3作用域x=5作用域
  • 308. <>用static声明局部变量 若希望函数调用结束后,局部变量的值保留,则指定该变量为静态局部变量,用static对变量加以声明。 C语言程序设计 第八章 函数例 局部静态变量值具有可继承性main() { void increment(void); increment(); increment(); increment(); } void increment(void) { int x=0; x++; printf(“%d\n”,x); }运行结果:1 1 1main() { void increment(void); increment(); increment(); increment(); } void increment(void) { static int x=0; x++; printf(“%d\n”,x); }运行结果:1 2 3
  • 309. <> C语言程序设计 第八章 函数例8.17 考察静态局部变量的值#include void main( ) { int f(int) ; int a=2, i; for(i=0; i<3; i++) printf(“%d ”, f(a)); } int f(int a) { auto b=0; static c=3; b=b+1; c=c+1; return(a + b + c); } main( )i a f(a)0 2 f(2)1 2 f(2)2 2 f(2)f(a) a b c return(a+b+c)2 0 3 1 4 return(7)2 0 4 1 5 return(8)2 0 5 1 6 return(9)运行结果:7 8 9对静态局部变量的说明: ⑴分配在静态区,程序运行结束释放存储单元。 ⑵赋初值一次未赋初值时为0,前次结果保留。 ⑶局部动态变量若未赋初值,其值不确定,局部静态变量未赋初值,其值为0或‘\0’(字符变量)。 ⑷静态局部变量在函数调用结束后虽存在,但其它函数不能引用它。
  • 310. <>使用局部静态变量的场合 (1)需要保留上一次调用结束时的值 C语言程序设计 第八章 函数例8.18 打印1到5的阶乘值#include void main( ) {int fac(int n); int i; for(i=1; i<=5; i++) printf(“%d != %d\n”, i, fac(i)); } int fac(int n) { static int f=1; f=f*n; return(f); } main( )i fac(i)1 fac(1)2 fac(2)3 fac(3)4 fac(4)5 fac(5)fac(n) 输出结果 n f=f*n f=1 1 f=1*1 1!=1 2 f=1*2=2 2!=2 3 f=2*3=6 3!=6 4 f=6*4=24 4!=24 5 f=24*5=24 5!=120 (2)初始化后变量只被引用而不改变其值,则用静态局部变量较方便,以免每次调用时重新赋值,但会一直占用内存浪费系统资源。
  • 311. <>register(寄存器型)变量 CPU内有寄存器可用来存放数据,若把数据声明为寄存器类型,则将该类型的数据存放在寄存器中,其优点是:减少数据与内存之间的交换频率,提高程序的效率和速度。 C语言程序设计 第八章 函数CPU 寄存器组内存例8.19 使用寄存器变量#include void main( ) { long fac(long); long i, n; scanf(“%ld”,&n); for(i=1; i<=n; i++) printf(“%ld != %ld\ n”, i, fac(i));} long fac(long n) { register long i, f=1; for(i=1; i<=n; i++) f=f * i; return(f); }运行结果: 1 ! = 1 2 ! = 2 3 ! = 6 4 ! = 24 5 ! = 120
  • 312. <>寄存器类型变量的几点说明: 1. 局部自动变量类型和形参可定义为寄存器变量。 2. 不同C系统对寄存器的使用个数,对register变量的处理方法不同,对寄存器变量的数据类型有限制。 3. 局部静态变量不能定义为寄存器变量。 4. long,double,float不能设为register型,因为超过寄存器长度 C语言程序设计 第八章 函数
  • 313. <>用extern声明外部变量 外部变量也称全局变量,在函数外部定义,其作用域是从变量的定义处开始,到本程序文件的未尾。在定义的作用域内,全局变量可为程序中各个函数所引用。 可以用extern声明外部变量,以扩展外部变量的作用域。 C语言程序设计 第八章 函数在一个文件内声明外部变量 外部变量没在文件开头定义,其作用域为定义处到文件结束。定义处之前的函数要使用,则在引用前用关键字extern作“外部变量声明”。例8.20 用extern声明外部变量,扩展作用域int max(int x, int y) { int z; z=x>y ? x:y; return(z); } main( ) { extern int A,B; printf(“%d”,max(A,B)); } int A=13,B=-8;运行结果: 13可以省略为: extern A,B;一般应将外部变量定义放在程序最前面,从而省去extern声明
  • 314. <> C语言程序设计 第八章 函数例 用extern扩展作用域main() { void gx(),gy(); extern int X,Y; printf(“1: x=%d\ty=%d\n”,X,Y); Y=246; gx(); gy(); } void gx() { extern int X,Y; X=135; printf(“2: x=%d\ty=%d\n”,X,Y); } int X,Y; void gy() { printf(“3: x=%d\ty=%d\n”,X,Y); }运行结果: 1: x=0 y=0 2: x=135 y=246 3: x=135 y=246
  • 315. <>在多文件的程序中声明外部变量 如果一个程序由多个文件组成,而一个外部变量需要在几个文件中引用,此时,可以在任一文件中定义该外部变量,在其它文件中用extern加以声明 若在每个文件中都定义该外部变量,则系统将提示“重定义类型错” C语言程序设计 第八章 函数int global; extern float x; main() { int local; ┇ }extern int global; static int number; func1() { ┇ }float x; static int number; func2() { extern int global; ┇ }file1.cfile2.cfile3.c定义定义声明声明
  • 316. <> C语言程序设计 第八章 函数例8.21 用extern将外部变量的作用域扩展到其它文件程序的作用是给定b的值,输入a和m,求a×b和am的值。#include /*文件file1.c*/ int A; void main() { int power(int); int b=3,c,d,m; printf("Enter the number a and its power m:\n"); scanf("%d,%d",&A,&m); c=A*b; printf("%d*%d=%d\n",A,b,c); d=power(m); printf("%d**%d=%d",A,m,d); }/*文件file2.c*/ extern A; int power(int n) { int i,y=1; for(i=1;i<=n;i++) y*=A; return(y); }
  • 317. <>用static声明外部变量 如果外部变量只允许本文件使用,不允许其它文件引用,则定义时加static声明。称为“静态外部变量” 只在工程方法中有效,在文件包含中则不起作用 常用于多人编同一程序,又使用同名变量时 加或不加static声明的外部变量都是静态存储,但其作用域不同 C语言程序设计 第八章 函数int global; extern float x; main() { int local; ┇ }extern int global; static int number; func1() { ┇ }float x; static int number; func2() { extern int global; ┇ }file1.cfile2.cfile3.c
  • 318. <>⑴在运行file1.c时,无论有无static,其结果都一样。 ⑵如果标识符A在file2.c中无定义, 也可无static,这是因为用文件包含的方法,相当把file2.c包含进file1.c中来,使其成为file1.c的一部分了. (2)若用工程的方法,则在file1.c中去掉#include “file2.c” ,建立工程文件file3.prj C语言程序设计 第八章 函数/*文件file1.c*/ #include “file2.c” static int A; main( ) { A=5; printf(“A1=%d\ n”, A); f1( ); printf(“A4=%d\ n”,A); } /*文件file2.c */ extern int A; f1( ) { printf(“A2=%d\ n”,A); A=A* A;printf(“A3=%d\ n”,A); }说明: A1=5 A2=5 A3=25 A4=25 如果file3.prj内容:file1.c file2.c 此时若有static 则编译指出: A不可被引用
  • 319. <>关于变量的声明和定义 函数:由“声明部分”和“执行语句”组成 声明部分: 对有关的标识符(变量,函数,结构体)的属性进行说明,对于函数,声明和定义区别明显,声明是函数原型,定义是函数本身,是一个独立的程序模块; 变量的声明有两种情况 定义性声明:需建立存储空间,如int a;也称定义。 引用性声明:不建立存储空间,如extern A 外部变量“定义性声明”只能一次,“引用性声明”多次。 广义地讲,声明包括定义,但并非所有的声明都是定义; 如:int A;既包含声明又包含定义; extern A;只是声明,而无定义。 约定:建立存储空间的声明称定义; 不建立存储空间的声明称声明。 C语言程序设计 第八章 函数
  • 320. <>Static定义性声明变量作用二个: 局部变量用static定义性声明,分配的存储空间在程序执行期间始终存在,但作用域 只限定义它的函数或分程序。 全局变量用static定义性声明,变量的作用域仅限本文件模块 Auto,register,static是在定义变量的基础上加上这些关键字,不能单独作用。 C语言程序设计 第八章 函数
  • 321. <>存储类别小结 C语言程序设计 第八章 函数局部变量默认为auto型 register型变量个数受限,且不能为long, double, float型 局部static变量具有全局寿命、局部可见性和可继承性 extern不是变量定义,可扩展外部变量作用域静态动态存储方式程序整个运行期间函数调用开始至结束生存期编译时赋初值,只赋一次每次函数调用时赋初值自动赋初值0或空字符不确定未赋初值静态存储区动态区存储区寄存器局部变量外部变量作用域定义变量的函数或复合语句内本文件其它文件register局部staticauto外部static外部存储类别
  • 322. <> C语言程序设计 第八章 函数例 文件file1.c int a; main( ) { ……. ……. f2; ……. f1; ……. } f1( ) { auto int b; ……… f2; …….. } f2( ) { static int c; ……… }c作用域b作用域a作用域mainf2f1mainf1f2mainb生存期:c生存期:a生存期:
  • 323. <>8.10 内部函数和外部函数 根据函数能否被其它源文件调用,将函数分为内部函数和外部函数。 内部函数——静态函数 只能被本文件中其它函数所调用 定义形式: static 类型标识符 函数名(形参表) 如: static int fun(int a, int b) 内部函数,其作用域仅限于定义它的所在文件。此时,在其它的文件中可以有相同的函数名,它们相互之间互不干扰。 C语言程序设计 第八章 函数
  • 324. <>外部函数 能被其它文件中的函数所调用 定义形式: extern 类型标识符 函数名(形参表) 如:extern int fun(int a, int b) 省略extern,隐含为外部函数 调用此函数的文件中也要用extern声明所用函数是外部函数 skip C语言程序设计 第八章 函数例8.22 有一个字符串,内有若干个字符,今输入一个字符, 要求程序将字符串中该字符删去。用外部函数实现。分析:该问题可以用四个函数解决。 主函数main( ) , 删除字符函数delete_char( ) , 输入字符串函数enter_str( ) ,输出新字符串函数print_str( ) , 将各函数放入四个文件,用extern声明实现各文件中函数的调用。
  • 325. <> C语言程序设计 第八章 函数/*文件file1.c*/ #include"file2.c" #include"file3.c" #include"file4.c" #include void main() { extern enter_string(char str[80] ), extern delete_string(char str[],char ch ), extern print_string(char str[ ] ); char c; char str[80]; enter_string(str); scanf(“%c”,&c); delete_string(str,c); print_string(str); }初始 删除后a a str[0]b b str[1]c d str[2]c \0 str[3]c c str[5]d d str[4]\0 \0 str[6]┇   ┇   ┇\0 \0 str[79]i j str[i] !=‘c’ str[i] ← str[j++]0 0 str[0] !=‘c’ str[0] ← str[0]=a 11 2 str[1] !=‘c’ str[1] ← str[1]=b2 str[2] !=‘c’ 3 str[3] !=‘c’ 4 3 str[4] !=‘c’ str[2] ← str[4]=d5 str[5] !=‘c’ ┇┇ ┇79 str[79] !=‘c’ str[3] ← ‘\0’
  • 326. <> C语言程序设计 第八章 函数/*文件file2.c*/ #include “stdio.h” void enter_string(char str[80]) { gets(str); } /*文件file3.c*/ #include void delete_string(char str[ ],char ch) { int i, j; for(i=j=0; str[i] !='\0' ; i++) if(str[i] != ch) str[j++]=str[i]; str[j]='\0'; }/*文件file4.c*/ #include void print_string(char str[ ]) { printf(“%s”,str);}初始 删除后a a str[0]b b str[1]c d str[2]c \0 str[3]c c str[5]d d str[4]\0 \0 str[6]┇   ┇   ┇\0 \0 str[79]i j str[i] !=‘c’ str[i] ← str[j++]0 0 str[0] !=‘c’ str[0] ← str[0]=a 11 2 str[1] !=‘c’ str[1] ← str[1]=b2 str[2] !=‘c’ 3 str[3] !=‘c’ 4 3 str[4] !=‘c’ str[2] ← str[4]=d5 str[5] !=‘c’ ┇┇ ┇79 str[79] !=‘c’ str[3] ← ‘\0’输入: abccdc c  输出:abd
  • 327. <>8.11 如何运行一个多文件的程序 用Turbo C集成环境 工程方法 建立工程文件名.prj,其中包含一个程序的各文件名 如:file1.c file2.c file3.c file4.c 在工程菜单项中设立工程文件名 运行工程文件,按F9编译,再ctrl+F9运行。 文件包含方法 在主函数的头部将本程序各文件用#include “文件名.c” 运行该程序 C语言程序设计 第八章 函数
  • 328. <>本章小结 C语言程序设计 第八章 函数函数包含一系列程序语句,它们被集中在一起并给它们起一个名字; 每一个函数在被调用之前必须声明; 每一个函数都必须有一个相应于其原型的函数实现,给出该函数的具体细节; 一个有返回值的函数一定要返回一个与其声明时类型相匹配的值; 一个void型的函数没有任何返回值; 在函数内部定义的变量,包括函数的形式参数都是局部变量,它们在函数的外部是不可见的; 当函数返回时,它精确地回到它被调用的那一点; 一般运用逐步求精的方法,从主函数开始逐步实现各个功能函数。
  • 329. <> C语言程序设计 第八章 函数作业: 第一次: 8.1(不用全局变量) 8.2 8.3 补充:1. 用max函数的方法求三个数中最大数。 2. 用函数调用的方法求下面公式前20项的和。 第二次:8.4 8.5 8.1(用全局变量) 第三次:8.6 8.8 8.9 8.11 8.13 提高题:8.12 8.17 8.18 上机: 练习运行例8.22多文件程序,用Trbao C 预习:第9章 预处理命令
  • 330. 第9章 预处理命令 C语言程序设计 第九章 预处理命令宏定义“文件包含”处理条件编译
  • 331. <>编译:对源程序进行词法、语法分析,生成代码,优化等。 作用:在编译之前,对源程序中的特殊命令做一些处理,生成扩展C源程序 种类: 宏定义 #define 文件包含 #include 条件编译 #if #else #endif等 格式: “#”开头 占单独书写行 语句尾不加分号 C语言程序设计 第九章 预处理命令
  • 332. <>9.1 宏定义 不带参数的宏定义 一般形式: #define 标识符 字符串 功能:用指定标识符(宏名)代替字符串序列(宏体) C语言程序设计 第九章 预处理命令宏定义命令宏体可缺省,表示宏名 定义过或取消宏体如 #define YES 1 #define NO 0 #define PI 3.1415926 #define OUT printf(“Hello,World”);定义位置:任意(一般在函数外面) 作用域:从定义命令到文件结束 #undef可终止宏名作用域 格式: #undef 宏名例 #define YES 1 main() { …….. } #undef YES #define YES 0 max() {…….. }YES原作用域YES新作用域
  • 333. <> C语言程序设计 第九章 预处理命令例9.1 使用不带参数的宏定义 #include #define PI 3.1415926 void main() { float l,s,r,v; printf("input radius : "); scanf("%f",&r); l=2.0*PI*r; s=PI*r*r; v=4.0/3.0*PI*r*r*r; printf("l=%10.4f\ns=%10.4f\nv=%10.4f\n",l,s,v); }运行: input radius: 4 l=25.1328 s=50.2655 v=150.7966宏名一般用大写字母,与变量区别。 使用宏便于修改变量值,提高程序通用性。例 #define ARRAY_SIZE 1000 int array[ARRAY_SIZE] ;
  • 334. <>宏展开:预编译时,用宏体替换宏名---不作语法检查 C语言程序设计 第九章 预处理命令如 if(x==YES) printf(“correct!\n”); else if (x==NO) printf(“error!\n”); 展开后: if(x==1) printf(“correct!\n”); else if (x==0) printf(“error!\n”);引号中的内容与宏名相同也不置换例 #define PI 3.14159 printf(“2*PI=%f\n”,PI*2); 宏展开:printf(“2*PI=%f\n”,3.14159*2);宏定义中使用必要的括号()例 #define WIDTH 80 #define LENGTH (WIDTH+40) var=LENGTH*2; 宏展开:var= (80+40) *2;
  • 335. <> C语言程序设计 第九章 预处理命令例9.2 在宏定义中引用已定义的宏名 #include #define R 3.0 #define PI 3.1415926 #define L 2*PI*R #define S PI*R*R void main() { printf("L=%f\nS=%f\n",L,S);}运行: L=18.849556 S=28.274333宏定义可嵌套,不能递归例 #define MAX MAX+10 ()例 #define WIDTH 80 #define LENGTH WIDTH+40 var=LENGTH*2; 宏展开:var= 80+40 *2;
  • 336. <>带参数的宏定义 一般形式: #define 宏名(参数表) 宏体 功能:进行字符串替换,并进行参数替换 C语言程序设计 第九章 预处理命令不能加空格例 #define S(a,b) a*b ……….. area=S(3,2); 宏展开: area=3*2;宏展开:形参用实参换,其它字符保留 宏体及各形参外一般应加括号()例 #define S (r) PI*r*r 相当于定义了不带参宏S,代表字符串“(r) PI*r*r” 例 #define POWER(x) x*x x=4; y=6; z=POWER(x+y); 宏展开:z=x+y*x+y; 一般写成: #define POWER(x) ((x)*(x)) 宏展开: z=((x+y)*(x+y));
  • 337. <>带参宏定义与函数的区别 函数调用时,先求实参表达式的值,再带入形参。 宏只进行简单字符替换,不求值。 函数调用在程序运行时处理和分配临时内存单元。 宏展开在编译时进行,不分配内存单元,无值传递和返值。 函数要定义形实参且类型一致,宏无类型,其参数无类型。 函数只有一个返回值,宏可以设法得到几个结果。 C语言程序设计 第九章 预处理命令例9.3 使用带参数的宏 #include #define PI 3.1415926 #define S(r) PI*r*r void main() { float a,area; a=3.6; area=S(a); printf("r=%f\narea=%f\n",a,area); }运行: r=3.600000 area=40.715038
  • 338. <>9.1 数组作为函数参数 在函数调用过程中,直接或间接的调用自身。 递归调用方式 直接递归调用:在函数体内又调用自身 C语言程序设计 第九章 预处理命令例9.4 使用宏带回几个结果 #include #define PI 3.1415926 #define CIRCLE(R,L,S,V) L=2*PI*R;S=PI*R*R; V=4.0/3.0*PI*R*R*R void main() { float r,l,s,v; scanf("%f",&r); CIRCLE(r,l,s,v); printf("r=%6.2f,l=%6.2f,s=%6.2f,v=%6.2f\n",r,l,s,v); } 宏展开后: void main() { float r,l,s,v; scanf("%f",&r); l=2*3.1415926*r;s=3.1415926*r*r;v=4.0/3.0*3.1415926*r*r*r; printf("r=%6.2f,l=%6.2f,s=%6.2f,v=%6.2f\n",r,l,s,v);}运行: 3.5  r=3.50,l=21.99,s=38.48,v=179.59
  • 339. <>宏展开使源程序变长,函数调用源程序不变长。 宏替换不占运行时间,只占编译时间。 函数调用占运行时间。 C语言程序设计 第九章 预处理命令#define MAX(x,y) (x)>(y)?(x):(y) ……. main() { int a,b,c,d,t; ……. t=MAX(a+b,c+d); …… } 宏展开:t=(a+b)>(c+d)?(a+b):(c+d);int max(int x,int y) { return(x>y?x:y); } main() { int a,b,c,d,t; ……. t=max(a+b,c+d); ……… }例 用宏定义和函数实现同样的功能
  • 340. <> C语言程序设计 第九章 预处理命令例9.5 用宏代表输出格式 #include #define PR printf #define NL "\n" #define D "%d" #define D1 D NL #define D2 D D NL #define D3 D D D NL #define D4 D D D D NL #define S "%s"运行结果: 1 12 123 1234 CHINA void main() { int a,b,c,d; char string[]="CHINA"; a=1;b=2;c=3;d=4; PR(D1,a); PR(D2,a,b); PR(D3,a,b,c); PR(D4,a,b,c,d); PR(S,string); }
  • 341. <>9.2 “文件包含”处理 功能:一个源文件可将另一个源文件的内容全部包含进来 一般形式: #include “文件名” 或 #include <文件名> 处理过程:预编译时,用被包含文件的内容取代该预处理命令,再将“包含”后的文件作为一个源文件单位进行编译,得目标文件.obj C语言程序设计 第九章 预处理命令#include “file2.c”file1.cfile2.cfile1.cfile2.cABA<> 直接按标准目录搜索 “ ” 先在当前目录搜索,再搜索标准目录 可指定路径
  • 342. <> C语言程序设计 第九章 预处理命令例9.6 将例9.5改为文件包含 ⑴ 格式宏做成头文件format.h #define PR printf #define NL "\n" #define D "%d" #define D1 D NL #define D2 D D NL #define D3 D D D NL #define D4 D D D D NL #define S "%s"运行结果: 1 12 123 1234 CHINA ⑵ 主文件file1.c #include #include "format.h" void main() { int a,b,c,d; char string[]="CHINA"; a=1;b=2;c=3;d=4; PR(D1,a); PR(D2,a,b); PR(D3,a,b,c); PR(D4,a,b,c,d); PR(S,string); }
  • 343. <>被包含文件内容 源文件(*.c) 头文件(*.h) C语言程序设计 第九章 预处理命令文件包含可嵌套宏定义 数据结构定义 函数说明等#include “file2.c”file1.cAfile3.cC#include “file3.c”file2.c B#include “file3.c” #include “file2.c”file1.cAfile2.c Bfile3.cC预编译后已成为一个文件,因此file2.c中的全局静态变量在file1.c中有效,不必再用extern声明。
  • 344. <>9.3 条件编译 功能:当文件中的部分内容在满足一定条件才进行编译 几种形式: 形式1: 标识符已被#define命令 定义过,则编译程序段1, 反之编译程序段2 C语言程序设计 第九章 预处理命令#ifdef 标识符 程序段1 #else 程序段2 #endif可以没有例 适应16位或32位计算机 #ifdef COMPUTER_A #define INTEGER_SIZE 16 #else #define INTEGER_SIZE 32 #endif例 调试信息的输出 #define DEBUG ┆ #ifdef DEBUG printf("x=%d,y=%d,z=%d\n",x,y,z); #endif
  • 345. <>形式2: 与形式1相反,标识符未被#define命令定义过,则编译程序段1,反之编译程序段2 C语言程序设计 第九章 预处理命令#ifndef 标识符 程序段1 #else 程序段2 #endif形式3: 表达式为真,则编译程序段1,反之编译程序段2 #if 表达式 程序段1 #else 程序段2 #endif
  • 346. <> C语言程序设计 第九章 预处理命令#include #define LETTER 1 /* 1大写,0小写 */ void main() { char str[20]="C Language",c; int i=0; while((c=str[I])!='\0') { i++; #if LETTER if(c>='a'&&c<='z') c=c-32; #else if(c>='A'&&c<='Z') c=c+32; #endif printf("%c",c);} printf(“\n"); }例9.7 输入字符串,根据需要设置条件编译, 使字母改为大写或小写
  • 347. <>本章要求 熟悉宏定义与宏展开的区别,宏与函数的区别。 熟悉文件包含命令#include的作用及预处理方法。 熟悉条件编译的使用。 课后作业 9.1,9.10,(读9.6题答案) 9.5,9.9 上机:实验8 预习:第10章 指针(重点、难点) C语言程序设计 第九章 预处理命令
  • 348. 第10章 指针 C语言程序设计 第十章 指针地址和指针的概念变量的指针和指向变量的指针变量数组与指针字符串与指针指向函数的指针返回指针值的函数指针数组和指向指针的指针有关指针的数组类型和指针运算的小结
  • 349. <>本章学习目标: 认识到用地址作为一种数据类型的重要性。 理解指针包括地址和类型两种属性。 掌握指针运算符&和*。 能够通过地址引用调用在被调函数与主调函数之间共享数据。 理解指针和数组的关系。 理解指向函数的指针的用法。 C程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存,直接访问内存地址 得到多于一个的函数返回值 C语言程序设计 第十章 指针
  • 350. <>10.1 地址和指针的概念 C语言程序设计 第十章 指针内存用户数据区变量 i变量 j变量 i_pointer362000200020023010在程序中定义一个变量,在编译时就给 这个变量分配一个内存单元,同时根据 变量的类型决定这个内存单元的大小。 如:整型2字节,实型4字节。内存中每一个字节都有一个编号, 就是“地址”。对每一个变量,它在内存中都有一个 存储位置,这个位置就是该变量的地址, 对变量值的存取是通过地址进行。 在C语言中这个地址被形象化地称为“指针”。指针:一个变量的地址。 指针变量:存放另一变量的地址(即指针)。
  • 351. <>10.2 变量的指针和指向变量的指针变量 定义一个指针变量 指针变量在使用前必须定义,使其指向特定类型的变量,指针变量存放地址,必须定义为“指针类型”。 定义的一般形式:基类型 *指针变量名; 基类型:用来指定指针变量可以指向的变量的类型。 将决定指针移动和运算时的移动量。 构成:[存储类型] 数据类型 * :表示该变量为指针类型 C语言程序设计 第十章 指针例 int *p1,*p2; float *q ; static char *name;注意: 1、int *p1, *p2; 与 int *p1, p2; 2、指针变量名是p1,p2 ,不是*p1,*p2 3、指针变量只能指向定义时所规定类型的变量 4、指针变量定义后,变量值不确定,应用前必须先赋值
  • 352. <>进一步理解&与*运算符: 含义 C语言程序设计 第十章 指针两者关系:互为逆运算 理解取地址运算符 含义: 取变量的地址 单目运算符 优先级: 2 结合性:自右向左指针运算符(“间接访问”运算符) 含义: 取指针所指向变量的内容 单目运算符 优先级: 2 结合性:自右向左…...…...2000200420062005整型变量i10变量i_pointer2001200220032000指针变量i_pointer-----指针变量,它的内容是地址量 *i_pointer----指针的目标变量,它的内容是数据 &i_pointer---指针变量占用内存的地址200010i_pointer*i_pointer&i_pointerii_pointer &i &(*i_pointer) i *i_pointer *(&i)i_pointer = &i = &(*i_pointer) i = *i_pointer = *(&i)
  • 353. <>指针变量的初始化 一般形式:[存储类型] 数据类型 *指针名=初始地址值; C语言程序设计 第十章 指针赋给指针变量, 不是赋给目标变量例 int i; int *p=&i;变量必须已说明过 类型应一致例 int *p=&i; int i;例 int i; int *p=&i; int *q=p;用已初始化指针变量作初值例 main( ) { int i; static int *p=&i; .............. } ()不能用auto变量的地址 去初始化static型指针指针变量赋值: int i, j; int *p1, *p2; p1=&i; p2=&j ; i=3; *p1=5; j=6; *p2=8;3 56 8┇20002002ijp1p220002002
  • 354. <>指针变量的引用 C语言程序设计 第十章 指针例10.1 通过指针变量访问整型变量 #include void main( ) {int a, b, *p1, *p2 ; a=100; b=10; p1=&a; p2=&b; printf(“a=%d, b=%d\ n”,a, b); printf(“* p1=%d, * p2=%d\ n”, *p1, * p2); printf(“&a=%x,& b=%x\ n”,&a, &b); printf(“p1=%x, p2=%x\ n”, p1, p2); printf(“& p1=%x, &p2=%x\ n”, &p1, & p2); }运行结果: a=100, b=10 *p1=100, *p2=10 &a=ffd4, &b=ffd6 p1=ffd4, p2=ffd6 &p1=ffd8, &p2=ffda10010ffd4ffd6abp1p2ffd4ffd6ffd8ffda
  • 355. <>关于 & 和 * 运算符的进一步说明: * 、&:优先级同为2级, 结合性:从右向左。 1.若已执行: int a, b, * p1, * p2; p1=&a; p2=&b; a=100; b=10; 则 ① &* p1  &a (p1) &* p2  &b (p2) ②p2=&* p1  p2=&a C语言程序设计 第十章 指针&a&bp1p210100ba&a&ap2p110100ba2. * & a:先进行&a得a的地址,再对a的地址进行* 运算 即指向a地址所指向的变量,就是a ,其值是100 3. 运算符 * ,++ :优先级为2, 结合性:从右到左 (* p1)++  a++ * p1++  * (p1++) 意即: p1原指向a , 现在指向下一个地址了。
  • 356. <> C语言程序设计 第十章 指针例10.2 输入a和b两个整数,用指针方法按先大后小顺序输出 #include void main( ) {int *p1, *p2, *p, a, b; scanf(“%d%d”,&a,&b); p1=&a;p2=&b; if(a
  • 357. <>指针变量作为函数参数——地址传递 特点:共享内存,“双向”传递 C语言程序设计 第十章 指针例10.3a 将数从大到小输出 #include void swap(int x,int y) { int temp; temp=x; x=y; y=temp; } void main() { int a,b; scanf("%d,%d",&a,&b); if(a
  • 358. <> C语言程序设计 第十章 指针例10.3 将数从大到小输出 (使用指针变量作函数参数) #include void main() { void swap(int *p1, int *p2); int a,b; int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a
  • 359. <> C语言程序设计 第十章 指针例10.3b 将数从大到小输出 void swap(int *p1, int *p2) { int *temp; *temp=*p1; *p1=*p2; *p2=*temp; } void main() { int a,b; int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a
  • 360. <> C语言程序设计 第十章 指针例10.3c 将数从大到小输出 void swap(int x,int y) { int temp; temp=x; x=y; y=temp; } void main() { int a,b; int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a
  • 361. <> C语言程序设计 第十章 指针例10.3d 将数从大到小输出 #include void swap(int *p1, int *p2) { int *p; p=p1; p1=p2; p2=p;} void main() { int a,b; int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a
  • 362. <> C语言程序设计 第十章 指针例10.4 输入a,b,c3个整数,按从大到小输出 #include void main( ) {void exchange(int *q1, int *q2, int *q3); int a,b,c,*p1,*p2,*p3; scanf(“%d,%d,%d”,&a,&b,&c); p1=&a; p2=&b; p3=&c; exchange(p1, p2, p3); printf(“\n%d, %d, %d\ n”,a, b, c);} void exchange(int *q1, int *q2, int *q3) {void swap(int *pt1, int *pt2); if(*q1 < *q2) swap(q1, q2); if(*q1 < *q3) swap(q1, q3); if(*q2 < *q3) swap(q2, q3);} void swap(int *pt1, int *pt2) {int temp; temp=*pt1; *pt1=*pt2; *pt2=temp;} ffbcffc2ffc4ffcaffccffceffd0ffd2ffd4ffd6ffd8ffdatemppt1pt2q2q1q3abcp1p2p3ffd09 10 10ffd2ffd49 0ffd0 ffd2ffd4 ffd4ffd00 0 910 9 0ffd2ffd4运行情况: 9 , 0 , 10  10 , 9 , 0
  • 363. <>10.3 数组与指针 数组的指针:指数组的起始地址。 数组元素的指针:指数组元素的地址。 数组的地址指针变量,指针变量就指向该数组了。 引用数组元素: ⑴下标法:a[3] ⑵指针法:用指针变量指向所找的数组元素。 占内存少,运行速度快。 C语言程序设计 第十章 指针
  • 364. <>指向数组元素的指针 例:int a[10]; int *p; p=&a[0]; 或 p=a; /*定义后赋值,两者等价*/ 定义指针变量时赋初值: 例:int *p=&a[0]; int *p=a; C语言程序设计 第十章 指针如 int i, *p; p=1000; () i=p; ()不能把一个整数p,也不能把p的值整型变量
  • 365. <>通过指针引用数组元素 如果: int a[10]; int *p; p=&a[1]; /* p指向数组元素a[1] */ 则: *p=1 表示对p当前指向的数组元素a[1]赋予值1 而:p+1指向同一数组的下一个元素a[2]。 p的值(地址)加了2个字节,p+1=p+1×d(整型,d=2;实型,d=4;字符型d=1)指针变量所指数组元素的地址的计算,与数组数据类型有关。 设 p=&a[0] 则 ⑴ p+i和a+i就是a[i]的地址a+i×d ⑵ *(p+i)或*(a+i)是p+i或a+i指向的数组元素a[i] ⑶ 指向数组的指针变量可带下标,p[i]与*(p+i)等价 C语言程序设计 第十章 指针
  • 366. <>表示数组元素的两种方法: C语言程序设计 第十章 指针a[0]a[1]a[2]a[3]a[9]...aa+9a+1a+2地址元素下标法a[0]a[1]a[2]a[9]a[0]a[1]a[2]a[3]a[9]...pp+9p+1p+2地址元素指针法*p*(p+1)*(p+2)*(p+9)[] 变址运算符 a[i]  *(a+i)a[i]  p[i]  *(p+i) *(a+i)*a*(a+1)*(a+2)*(a+9)p[0]p[1]p[2]p[9]
  • 367. <> C语言程序设计 第十章 指针⑴ 下标法: #include void main() {int a[10]; int i; for(i=0; i<10; i++) scanf("%d",&a[i]); printf("\n"); for(i=0; i<10; i++) printf("%d",a[i] );}运行情况: 1 2 3 4 5 6 7 8 9 0  1 2 3 4 5 6 7 8 9 0例10.5 用三种方法输出数组中全部元素的值⑵ 用数组名: #include void main() {int a[10]; int i; for(i=0; i<10; i++) scanf("%d",&a[i]); printf("\n"); for(i=0; i<10; i++) printf("%d",*(a+i));}⑶ 指针法: #include void main() {int a[10]; int *p,i; for(i=0; i<10; i++) scanf("%d",&a[i]); printf("\n"); for(p=a; p<(a+10); p++) printf("%d",*p );}⑷ 指针法和指针下标: #include void main() {int a[10]; int *p,i; for(i=0; i<10; i++) scanf("%d",&a[i]); printf("\n"); for(p=a,i=0; i<10; i++) printf("%d",*(p+i));}使用指针变量时要注意的问题: ⑴ p++: 合法,因为p是指针变量,++只能用于变量。 a++: 不合法,因为a是数组名,其值是数组元素的首地址,是常量,程序运行期间值固定不变。 ⑵ 指针变量使用时要注意当前值(见例10.6).
  • 368. <> C语言程序设计 第十章 指针例10.6 用指针变量输出元素 #include void main() { int *p,i,a[10]; p=a; for(i=0;i<10;i++) scanf(“%d”,p++); printf(“\n”); for(i=0;i<10;i++,p++) printf(“%d”,*p); printf(“\n”); }运行情况: 1 2 3 4 5 6 7 8 9 0  22153 234 0 0 30036 25202 11631 8259 8237 28483例10.6 用指针变量输出元素 #include void main() { int *p,i,a[10]; p=a; for(i=0;i<10;i++) scanf(“%d”,p++); printf(“\n”); p=a; /*或者p=&a[0]*/ for(i=0;i<10;i++,p++) printf(“%d”,*p); printf(“\n”); }能正确输出吗?运行情况: 1 2 3 4 5 6 7 8 9 0  1 2 3 4 5 6 7 8 9 0原因?
  • 369. <> C语言程序设计 第十章 指针使用指针变量时要注意的问题: ⑶ 从上例可知,指针变量p可以指向数组以后的内存单元编 译不作检查。 ⑷ 指针变量运算时要注意的几个问题:如果p=a ① p++(或p+=1),使p指向下一元素a[1]。则*p值成为a[1]。 ② ++和* 优先级同为2,结合性从右向左,则*p++等价于*(p++), 即先得到p指向的变量的值*p,再使p=p+1。例10.6可改为:例10.6 用指针变量输出元素 #include void main() { int *p,i,a[10]; p=a; for(i=0;i<10;i++) scanf(“%d”,p++); printf(“\n”); p=a; for(i=0;i<10;i++) printf(“%d”,*p++); printf(“\n”); } ③ *(p++)与*(++p)作用不同: *(p++)先取*p值,再p加1;*(++p)是p先加1,再取*p 若p初值&a[0],则*(p++)得a[0]值,*(++p)得a[1]值。 ④ (*p)++表示p所指向的元素值加1。 ⑤ 如果p指向a[i]元素,则: *(p--)相当于a[i--],先对p进行 * 运算,再使p自减(加)。 *(++p)相当于a[++i],先使p自加(减),再作 * 运算。 *(--p)相当于a[--i],先使p自减(加),再作 * 运算。例10.6 用指针变量输出元素 #include void main() { int *p,i,a[10]; p=a; for(i=0;i<10;i++) scanf(“%d”,p++); printf(“\n”); p=a; /*或者p=&a[0]*/ for(i=0;i<10;i++,p++) printf(“%d”,*p); printf(“\n”); }例 输出a数组100个元素 p=a; p=a; while(p
  • 370. <>用数组名作函数参数 C语言程序设计 第十章 指针 数组名作函数参数,是地址传递 当用数组名做函数实参时相当于将数组的首地址传给被调函数的形参,此时,形参数组和实参数组占用的是同一段内存,所以当在被调函数中对形参数组元素进行修改时,实参数组中的数据也将被修改,因为它们是同一个地址。数组名作函数参数 void main( ) {f(int arr[ ], int n); int array[10]; ┆ f(array, 10); ┆ } void f(int arr[ ], int n) { ┆ }arr[0] array[0]┋arr[1] array[1]arr[9] array[9]编译时arr按指针变量处理,所以,此句与f(int *arr , int n)等价。
  • 371. <> C语言程序设计 第十章 指针例10.7 将数组a中n个整数按相反顺序存放。 思路:数组元素头尾对调。四种调用方式。ij 3 7 9 11 0 6 7 5 4 20 1 2 3 4 5 6 7 8 9ijijijji11760594723m=4⑴ 实参与形参均用数组 #include void main() {void inv(int x[ ], int n); int i,a[10]={3,7,9,11,0,6,7,5,4,2}; printf("The original array:\n"); for(i=0;i<10;i++) printf("%d,"a[i]); printf("\n"); inv(a,10); printf("The array has been inverted:\n"); for(i=0;i<10;i++) printf("%d,",a[i]); printf("\n"); } void inv(int x[ ], int n) { int temp,i,j,m=(n-1)/2; for(i=0;i<=m;i++) { j=n-1-i; temp=x[i]; x[i]=x[j]; x[j]=temp; } return; }
  • 372. <> C语言程序设计 第十章 指针⑵ 实参用数组,形参用指针变量 #include void main() {void inv(int *x, int n); int i,a[10]={3,7,9,11,0,6,7,5,4,2}; printf("The original array:\n"); for(i=0;i<10;i++) printf("%d,"a[i]); printf("\n"); inv(a,10); printf("The array has been inverted:\n"); for(i=0;i<10;i++) printf("%d,",a[i]); printf("\n"); } void inv(int *x, int n) { int temp,*p,*i,*j,m=(n-1)/2; i=x; j=x+n-1; p=x+m; for(;i<=p;i++,j--) { temp=*i; *i=*j; *j=temp; } return; }37911067542a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]xp=x+ma数组60711594723ijijijjiji
  • 373. <> C语言程序设计 第十章 指针⑶例10.8 实参与形参均用指针变量 #include void main() {void inv(int *x, int n); int i,arr[10],*p=arr; printf("The original array:\n"); for(i=0;i<10;i++,p++) scanf("%d",p); p=arr; inv(p,10); printf("The array has been inverted:\n"); for(p=arr;p
  • 374. <> C语言程序设计 第十章 指针⑷ 实参用指针变量,形参用数组 #include void main() {void inv(int x[ ], int n); int i,a[10],*p=a; for(i=0;i<10;i++,p++) scanf("%d",p); p=a; inv(p,10); printf("The array has been inverted:\n"); for(p=arr;p
  • 375. <> C语言程序设计 第十章 指针例 从10个数中找出其中最大值和最小值 为了得到两个结果值,用两个全局变量max和min。⑴ 实参和形参均用数组 int max, min; /* 全局变量*/ void max_min_value(int array[ ],int n) { int *p, *array_end; array_end=array+n; /*指向数组最后一个元素的后面 */ max=min=*array; /* 相当于max=min=array[0] */ for(p=array+1; p max) max=*p; else if(*p
  • 376. <> C语言程序设计 第十章 指针⑵ 实参和形参均用指针变量 int max, min; /* 全局变量*/ void max_min_value(int *array,int n) { int *p, *array_end; array_end=array+n; /*指向数组最后一个元素的后面 */ max=min=*array; /* 相当于max=min=array[0] */ for(p=array+1; p max) max=*p; else if(*p
  • 377. <> C语言程序设计 第十章 指针归纳:用数组做函数参数有如下四种情况: 1、实参形参都用数组名: int a[10]; inv(int x[ ],int n) inv(a,10) { …... } 2、实参用数组名,形参用指针变量: int a[10]; inv(int *x,int n) inv(a,10) { …... } 3、实参形参都用指针变量: int a[10]; inv(int *x,int n) int *p=a; {……} inv(p,10) 4、实参用指针变量,形参用数组名: int a[10]; inv(int x[ ],int n) int *p=a; {…...} inv(p,10)
  • 378. <>一级指针变量与一维数组的关系 int *p 与 int q[10] 数组名是指针(地址)常量 p=q; p+i 是q[i]的地址 数组元素的表示方法:下标法和指针法, 即:若p=q, 则:p[i]  q[i]  *(p+i)  *(q+i) 形参数组实质上是指针变量。 即:int q[ ]  int *q 在定义指针变量(不是形参)时,不能把int *p 写成int p[]; 系统只给p分配能保存一个指针值的内存区(一般2字节);而给q分配2*10字节的内存区 C语言程序设计 第十章 指针
  • 379. <> C语言程序设计 第十章 指针⑴ 实参用指针变量,形参用数组 #include void main() {void sort(int x[ ], int n); int *p,i,a[10]; p=a; for(i=0;i<10;i++) scanf("%d",p++); p=a; sort(p,10); for(p=a,i=0;i<10;i++) {printf("%d ",*p); p++;} } void sort(int x[ ], int n) { int i,j,k,t; for(i=0;i<=n-1;i++) { k=i; for(j=i+1;jx[k]) k=j; if(k!=i) {t=x[i];x[i]=x[k];x[k]=t;} } }例10.9 用选择法对10个整数排序⑵ 实参和形参均用指针变量 void sort(int *x, int n) { int i,j,k,t; for(i=0;i<=n-1;i++) { k=i; for(j=i+1;j*(x+k)) k=j; if(k!=i) {t=*(x+i);*(x+i)=*(x+k);*(x+k)=t;} } }
  • 380. <>多维数组与指针 多维数组的地址(以二维数组为例) 如:int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}}; 多维数组数据存储按先行后列顺序。 每行都是一个一维数组,a[0],a[1],a[2]是一维数组名。 每个一维数组含4个元素. C语言程序设计 第十章 指针a= = =2321191715131197531a[2]a[1]a[0]a数组a (2000) a+2 (2016) a+1 (2008)a[2]a[1]a[0]行地址a:二维数组首地址,0行首地址。 a+1:第1行首地址为: a+1×4×2=2008 a+2:第2行首地址为: a+2×4×2=2016a+i:第i行首地址为: a+i×4×2
  • 381. <> C语言程序设计 第十章 指针数组名可以代表数组首地址,所以a[0]代表0行0列地址,&a[0][0]。a[1]的值是&a[1][0],a[2]的值是&a[2][0]. a, a[0], a[1] ,a[2]本身不占内存,不存放数据,仅表示一个地址。a[2]+02000 12002 32004 52006 72008 92010 112012 132014 152016 172018 192020 212022 23a[0]+0a[0]+1a[0]+2a[0]+3 a+0a+1a+2a[1]+3列元素地址行地址列元素地址:a[1]+3  *(a+1)+3  &a[1][3]a[i]  *(a+i) 等价:第i行第0列的元素地址&a[i][0]a[i]+j  *(a+i)+j等价:第i行第j列的元素地址&a[i][j]列元素值:*(a[i]+j)  *(*(a+i)+j)  a[i][j]列元素地址的表示:用地址法表示列元素的值列元素值:*(a[2]+3)  *(*(a+2)+3)  a[2][3]
  • 382. <>■行指针与列指针 行指针前加*转换为列指针:a→*a,a+1→*(a+1) 列指针前加&转换为行指针:a[0]→&a[0] ■ a+i=&a[i]=a[i]=*(a+i) =&a[i][0],值相等,含义不同。 C语言程序设计 第十章 指针int a[3][4];a[0][0]a[0][1]a[1][0]a[1][1]a[2][0]a[2][1]a[0][2]a[0][3]a[1][2]a[1][3]a[2][2]a[2][3]二维数组元素内容表示: (1)a[1][2] (2)*(a[1]+2) (3)*(*(a+1)+2) (4)*(&a[0][0]+1*4+2)地址表示: (1) a+1 (2) &a[1][0] (3) a[1] (4) *(a+1)行指针列指针地址表示: (1) &a[1][2] (2) a[1]+2 (3) *(a+1)+2 (4) &a[0][0]+1*4+2a+i  &a[i],表示第i行首地址,指向行 a[i]  *(a+i)  &a[i][0],表示第i行第0列元素地址,指向列
  • 383. <> C语言程序设计 第十章 指针表示形式含义地址a二维数组名,数组首地址a[0],*(a+0),*a第0行第0列元素地址a+1第1行首地址a[1],*(a+1)第1行第0列元素地址a[1]+2,*(a+1)+2,&a[1][2]第1行第2列元素地址*(a[1]+2),*(*(a+1)+2),a[1][2]第1行第2列元素值2000200020082008201213
  • 384. <> C语言程序设计 第十章 指针例10.10 输出二维数组有关的值 #include void main() { int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; printf("%d,%d\n",a,*a); printf("%d,%d\n",a[0],*(a+0)); printf("%d,%d\n",&a[0],*&a[0][0]); printf("%d,%d\n",a[1],a+1); printf("%d,%d\n",&a[1][0],*(a+1)+0); printf("%d,%d\n",a[2],*(a+2)); printf("%d,%d\n",&a[2],a+2); printf("%d,%d\n",a[1][0],*(*(a+1)+0)); }运行结果: 158,158 158,158 158,158 166,166 166,166 174,174 174,174 9,9
  • 385. <>指向多维数组的指针变量 指向数组元素的指针变量 C语言程序设计 第十章 指针例10.11 用指针变量输出数组元素的值 #include void main() { static int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int *p; for(p=a[0];p
  • 386. <> C语言程序设计 第十章 指针由此可见:顺序输出数组元素方法简单 而指定输出数组元素则要进行地址的计算 如二维数组为 n × m (n为行, m 为列) 首元素地址为 a[0] a[i][j]在数组中相对位置的计算公式: i * m + j ( m为每行元素个数) 位移量的计算: a[1][1]=1*4+1=5 a[2][3]=2*4+3=11 若初值: p=a[0] 则: *(p+1*4+1)=*(p+5) a[1][1] *(p+2*4+3)=*(p+11) a[2][3] 数组下标从0开始便于计算相对位置a[2][3]mi=2nj=3a[1][1]
  • 387. <>指向由m个元素组成的一维数组的指针变量 定义形式: 数据类型 (*指针名)[一维数组维数]; 例 int (*p)[4]; C语言程序设计 第十章 指针( )不能少 int (*p)[4]与int *p[4]不同p的值是一维数组的 首地址,p是行指针可让p指向二维数组某一行 如 int a[3][4], (*p)[4]=a;一维数组指针变量维数和 二维数组列数必须相同int a[3][4];a[0][0]a[0][1]a[1][0]a[1][1]a[2][0]a[2][1]a[0][2]a[0][3]a[1][2]a[1][3]a[2][2]a[2][3]aa+1a+2pp+1p+2p[0]+1或 *p+1p[1]+2或 *(p+1)+2*(*p+1)或 (*p)[1] *(*(p+1)+2)
  • 388. <> C语言程序设计 第十章 指针例10.12 输出二维数组任一行任一列元素的值 #include void main() { static int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int (*p)[4], i, j; p=a; scanf(“i=%d, j=%d”, &i, &j); printf(“a[%d][%d]=%d\ n”, i, j, *(*(p+i)+j)); }运行结果: i=1, j=2 a[1][2]=13 1 3 57911131517192123a,a+0,p+0 a+1,p+1 a+2,p+2
  • 389. <>多维数组的指针作函数参数 用指向变量的指针变量 用指向一维数组的指针变量 用二维数组名 C语言程序设计 第十章 指针实参形参数组名int x[][4]指针变量int (*q)[4]数组名int x[][4]指针变量int (*q)[4]数组名a数组名a指针变量p1指针变量p1若int a[3][4]; int (*p1)[4]=a; int *p2=a[0];指针变量p2指针变量int *q
  • 390. <> C语言程序设计 第十章 指针例10.13 3个学生各学4门课,计算总平均分,输出第n个学生成绩#include void main() { void average(float *p,int n); void search(float (*p)[4],int n); float score[3][4]= {{65,67,79,60},{80,87,90,81}, {90,99,100,98}}; average(*score,12); search(score,2); }void average(float *p,int n) { float *p_end, sum=0,aver; p_end=p+n-1; for(;p<=p_end;p++) sum=sum+(*p); aver=sum/n; printf("average=%5.2f\n",aver); } void search(float (*p)[4], int n) { int i; printf("score of No.%d :\n",n); for(i=0;i<4;i++) printf("%5.2f ",*(*(p+n)+i)); }列指针行指针函数说明float p[][4]6552796080879081909910098pp p[n][i]
  • 391. <> C语言程序设计 第十章 指针例10.14 3个学生各学4门课,计算总平均分,并查找一门以上 课程不及格学生, 输出其各门课成绩void search(float (*p)[4], int n) { int i,j,flag; for(j=0;j void main() { void search(float (*p)[4], int n); float score[3][4]={{...},{...},{...}}; search(score,3); }6552796080879081909910098p p[j][i]
  • 392. <>总结:二维数组与一维数组指针变量的关系 如 int a[5][10] 与 int (*p)[10]; 二维数组名是一个指向有10个元素的一维数组的指针常量 p=a+i 使 p指向二维数组的第i行 *(*(p+i)+j)  a[i][j] 二维数组形参实际上是一维数组指针变量, 即 int x[ ][10]  int (*x)[10] 变量定义(不是形参)时两者不等价 系统只给p分配能保存一个指针值的内存区(一般2字节);而给a分配2*5*10字节的内存区 C语言程序设计 第十章 指针
  • 393. <>10.4 字符串与指针 字符串的表示形式 字符串: 用双引号括起的一串字符。 可赋给字符型的数组或指针变量, 可通过字符型数组名或字符型指针变量输出。 用字符数组实现 C语言程序设计 第十章 指针例10.15 定义字符数组 #include void main( ) { char string[]=“I love China!”; printf("%s\n",string); printf("%s\n",string+7); }IloveChistring[0]string[1]string[2]string[3]string[4]string[5]string[6]string[7]string[8]string[9]stringstring[10]string[11]string[12]string[13]n!a\0数组名,数组首地址string[4]  *(string+4)此句输出?string+7输出: I love Chine! Chine!
  • 394. <>用字符指针实现 字符串的指针就是字符串的首地址,即第一个字符的地址, 可以使用字符指针变量来保存这个地址。 使用字符指针可以处理字符串 字符指针的定义及使用 定义和初始化。 例: char *string="I love China!"; 在程序中可以直接把字符串常量赋给 一个指针变量。 例:char *string; string="I love China!"; C语言程序设计 第十章 指针例10.16 定义字符指针 #include void main( ) { char *string=“I love China!”; printf(“%s\n”,string);}IloveChistringn!a\0
  • 395. <> C语言程序设计 第十章 指针改动后的例10.16 #include void main( ) { char *string=“I love China!”; printf(“%s\n”,string); string+=7; while(*string) { putchar(string[0]); string++; } }IloveChistringn!a\0string*string!=‘\0’输出: I love Chine! Chine!
  • 396. <>用下标法存取字符串中的字符 C语言程序设计 第十章 指针例10.17 将字符串a复制为字符串b #include void main( ) { char a[ ]="I am boy.",b[20]; int i; for(i=0;*(a+i)!='\0';i++) *(b+i)=*(a+i); *(b+i)='\0'; printf("string a is: %s\n",a); printf("string b is: "); for(i=0;b[i]!='\0';i++) printf("%c",b[i]); printf("\n"); }运行结果: string a is: I am boy. string b is: I am boy.*(a+i) = a[i] b[i]=a[i]地址访问: a[ ]复制到b[ ]下标法输出
  • 397. <> C语言程序设计 第十章 指针例10.18 用指针变量实现例10.17 #include void main( ) { char a[ ]=“I am boy.”,b[20]; char *p1=a,*p2=b; int i; for( ; *p1!=‘\0’ ; p1++,p2++) {*p2=*p1;} *p2='\0'; printf(“string a is: %s\n”, a ); printf(“string b is: %s\n”, b ); }运行结果: string a is: I am boy. string b is: I am boy.Iamab0yp1.\0abp2p1p2p1 p2运行结果: string a is: string b is:p1=a; p2=b;
  • 398. 字符指针作函数参数 C语言程序设计 第十章 指针例10.19 用函数调用实现字符串的复制⑴用字符数组作参数 #include void main() {void copy_string(char from[],char to[]); char a[ ]="I am a teacher."; char b[ ]="You are a student."; printf("string_a=%s\n string_b=%s\n",a,b); printf(“copy string_a to string_b: \n"); copy_string(a,b); /* 数组名作参数是地址传递*/ printf(“\nstring_a=%s\nstring_b=%s\n",a,b); } void copy_string(char from[],char to[]) { int i=0; while(from[i]!='\0') { to[i]=from[i]; i++; } to[i]='\0'; }aIamateaceh\0r.fromabyuarasutndetoboet.\0Iaaeceh\0r.t.\0mta
  • 399. <> C语言程序设计 第十章 指针⑵字符指针变量作形参 #include void main() { void copy_string(char *from,char *to); char *a="I am a teacher."; char *b="You are a student."; printf("string_a=%s\n string_b=%s\n",a,b); printf(“copy string_a to string_b: \n"); copy_string(a,b); printf(“\nstring_a=%s\nstring_b=%s\n",a,b); } void copy_string(char *from,char *to) { for(;*from!='\0';from++,to++) {*to=*from;} *to='\0'; }运行结果: string_a is: I am a teacher. string _b is: You are a student. copy string a to string b: string_a is: I am a teacher. string _b is: I am a teacher.⑶对copy_string函数的6种简化 请同学自行理解
  • 400. <>对使用字符指针变量和字符数组的讨论 char *cp; 与 char str[20]; 的区别 str由若干元素组成,每个元素放一个字符;而cp中存放字符串首地址 赋值方式: 字符数组只能对元素赋值。 char str[20]; str=“I love China!”; () 字符指针变量可以用: char *cp; cp=“I love China!”; () 赋初值:char *cp="China!"; 等价 char *cp; cp=“China!”; char str[14]={"China"};不等价char str[14]; str[ ]="China" () C语言程序设计 第十章 指针
  • 401. 字符指针变量接受键入字符串时,必须先开辟存储空间(赋地址)。 C语言程序设计 第十章 指针例 char str[10]; scanf(“%s”,str); () 而 char *cp; scanf(“%s”, cp); ()char *cp , str[10]; cp=str; scanf(“%s”,cp); ()数组名str代表的是地址常量不能改变; 指针变量cp是地址变量,值可以改变。 例10.20 () #include void main( ) { char *a="I love China!"; a=a+7; printf("%s",a);}改为: () #include void main( ) { char str[ ]={"I love China!"}; str=str+7; printf("%s",str);}例10.21 用下标法引用指针变量所指的字符串中的字符 #include void main( ) { char *a="I love China!"; int i; printf("The sixth charcter is %c\n",a[5]); for(i=0;a[i]!='\0';i++) printf("%c",a[i]); printf("\n");}
  • 402. <>用指针变量指向的格式字符串代替printf中的格式字符串(可变格式输出函数) char *format; format="a=%d,b=%f\n"; printf(format,a,b); 相对于: printf("a=%d,b=%f\n"a,b); 可以用字符数组实现: char format[ ]="a=%d,b=%f\n"; printf(format,a,b); C语言程序设计 第十章 指针
  • 403. <>判断和修正: C语言程序设计 第十章 指针char str[]={“Hello!”}; () char str[]=“Hello!”; () char str[]={‘H’,‘e’,‘l’,‘l’,‘o’,‘!’}; () char *cp=“Hello”; () int a[]={1,2,3,4,5}; () int *p={1,2,3,4,5}; ()char str[10],*cp; int a[10],*p; str=“Hello”; () cp=“Hello!”; () a={1,2,3,4,5}; () p={1,2,3,4,5}; ()int *p=&a;str[10]=“Hello”;a[10]={1,2,3,4,5};p=&a;
  • 404. <>10.5 指向函数的指针 用函数指针变量调用函数。 函数指针:函数在编译时被分配的入口地址,用函数名表示。函数指针指向的是程序代码存储区。 C语言程序设计 第十章 指针max…...指令1指令2函数指针变量定义形式: 数据类型 (*指针变量名)( ); 如 int (*p)();函数返回值的数据类型专门存放函数入口地址 可指向返回值类型相同的不同函数( )不能省 int (*p)() 与 int *p()不同函数指针变量赋值:如 p=max;函数调用形式: c=max(a,b);  c=(*p)(a,b); 对函数指针变量pn, p++, p--无意义函数指针变量指向的函数必须有函数说明
  • 405. <> C语言程序设计 第十章 指针例10.22 求a和b中的大者⑴一般方法: #include void main() { int max(int ,int); int a,b,c; scanf("%d,%d",&a,&b); c=max(a,b); printf("a=%d,b=%d,max=%d\n",a,b,c); } int max(int x,int y) { int z; if(x>y) z=x; else z=y; return(z);}⑵通过指针变量访问函数 #include void main() { int max(int , int); int (*p)(int , int); int a,b,c; p=max; scanf("%d,%d",&a,&b); c=(*p)(a,b); printf("a=%d,b=%d,max=%d\n",a,b,c); } int max(int x,int y) { int z; if(x>y) z=x; else z=y; return(z);}
  • 406. <>用指向函数的指针作函数参数(了解) 函数指针变量通常用途是将指针作为参数传递到其他函数,实现对不同函数的调用。 C语言程序设计 第十章 指针例10.23 用函数指针变量作参数,求最大值、最小值和两数之和#include void main() {int max(int,int),min(int,int),add(int,int); void process(int,int,int (*fun)(int,int)); int a,b; printf("enter a and b:"); scanf("%d,%d",&a,&b); process(a,b,max); process(a,b,min); process(a,b,add); } process(int x,int y,int (*fun)(int,int)) { int result; result=(*fun)(x,y); printf("%d\n",result); }max(int x,int y) { printf(“max=”); return(x>y?x:y); } min(int x,int y) { printf(“min=”); return(x
  • 407. 10.6 返回指针值的函数 函数定义形式: 类型标识符 *函数名(参数表); 例 int *f(int x, int y) C语言程序设计 第十章 指针例10.24:有若干学生成绩,要求输入学生序号后,能输出 该学生全部成绩。用指针函数实现。#include void main() { float score[ ][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}}; float *search(float (*pointer)[4],int n); float *p; int i,m; printf("Enter the number of student:"); scanf("%d",&m); printf("The scores of No.%d are:\n",m); p=search(score,m); for(i=0;i<4;i++) printf("%5.2f\t",*(p+i)); printf("\n");} float *search(float (*pointer)[4], int n) { float *pt; pt=*(pointer+n); return(pt);}pointerpointer+1347890665689678860708090score数组pppp形参指向一维数组的指针变量指向实型变量的指针变量接受search函数返回的指向某学生0门课程地址的指针变量
  • 408. <> C语言程序设计 第十章 指针例10.25 找出例10.24中有不及格课程的学生及其学号 #include void main() { float score[ ][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}}; float *search(float (*pointer)[4]); float *p; int i,j; for(i=0;i<3;i++) { p=search(score+i); if(p==*(score+i)); { printf("No. %d scores: ",i); for(j=0;j<4;j++) printf("%5.2f\t",*(p+j));} } } float *search(float (*pointer)[4]) { int i; float *pt; pt=*(pointer+1); for(i=0;i<4;i++) if(*(*pointer+i)<60 {pt=*pointer;break;} return(pt); }pointerscore+1 pointer347890665689678860708090score数组*pointerpt (当有不及格时)*(pointer+1)pt (当无不及格时)
  • 409. <> C语言程序设计 第十章 指针例 写一个函数,求两个int型变量中居于较大值的变量的地址main() { int a=2,b=3; int *p; p=f1(&a,& b); printf("%d\n",*p); } int *f1(int x,int y) { if(x>y) return x; else return y; }…...20002008200A20022004200623 指针变量y 指针变量x(f1)20022000COPY变量a 变量b(main) 指针变量p**2002
  • 410. <> C语言程序设计 第十章 指针例 写一个函数,求两个int型变量中居于较大值的变量的地址main() { int a=2,b=3; int *p; p=f3(a,b); printf("%d\n",*p); } int *f3(int x,int y) { if(x>y) return & x; else return & y; }COPY…...20002008200A20022004200623 变量y 变量x(f3)32变量a 变量b(main) 指针变量p**200A不能返回形参或局部变量 的地址作函数返回值
  • 411. <>10.7 指针数组和指向指针的指针 用于处理二维数组或多个字符串 指针数组的概念 定义:数组中的元素均为指针变量 定义形式:[存储类型] 类型名 *数组名[数组长度]; 例 int *p[4]; C语言程序设计 第十章 指针指针所指向变量的数据类型指针本身的存储类型区分int *p[4]与int (*p)[4]指针数组赋值与初始化赋值: main() { int b[2][3],*pb[2]; pb[0]=b[0]; pb[1]=b[1]; ┊ }int *pb[2]pb[0]pb[1]int b[2][3]123246初始化: main() { int b[2][3],*pb[ ]={b[0],b[1]}; …….. }int *pb[2]pb[0]pb[1]int b[2][3]123246
  • 412. <>指针数组赋值与初始化 C语言程序设计 第十章 指针L i s p \0F o r t r a n \0B a s i c \0p[0]p[1]p[2]p[3]0赋值: main() { char a[]="Fortran"; char b[]="Lisp"; char c[]="Basic"; char *p[4]; p[0]=a; p[1]=b; p[2]=c; p[3]=NULL; …….. }或: main() { char *p[4]; p[0]= "Fortran"; p[1]= "Lisp"; p[2]= "Basic"; p[3]=NULL; …….. }初始化: main() { char *p[]={"Fortran", "Lisp", "Basic",NULL}; …….. }L i s p \0F o r t r a n \0B a s i c \0p[0]p[1]p[2]p[3]0
  • 413. <>二维数组与指针数组区别: C语言程序设计 第十章 指针 char name[5][9]={“gain”,“much”,“stronger”, “point”,“bye”}; char *name[5]={“gain”,“much”,“stronger”, “point”,“bye”};g a i n \0s t r o n g e r \0p o i n t \0m u c h \0name[0]name[1]name[2]name[3]name[4]b y e \0g a i n \0s t r o n g e r \0p o i n t \0m u c h \0b y e \0二维数组存储空间固定 字符指针数组相当于可变列长的二维数组 分配内存单元=数组维数*2+各字符串长度指针数组元素的作用相当于二维数组的行名 但指针数组中元素是指针变量 二维数组的行名是地址常量
  • 414. <> C语言程序设计 第十章 指针例 用指针数组处理二维数组main() { int b[2][3],*pb[2]; int i,j; for(i=0;i<2;i++) for(j=0;j<3;j++) b[i][j]=(i+1)*(j+1); pb[0]=b[0]; pb[1]=b[1]; for(i=0;i<2;i++) for(j=0;j<3;j++,pb[i]++) printf("b[%d][%d]:%2d\n",i,j,*pb[i]); }int *pb[2]pb[0]pb[1]int b[2][3]b[0][0] *pb[0]b[0][1] *(pb[0]+1)b[0][2] *(pb[0]+2)b[1][0] *pb[1]b[1][1] *(pb[1]+1)b[1][2] *(pb[1]+2)123246
  • 415. <> C语言程序设计 第十章 指针例10.26 对字符串排序(简单选择排序) #include #include void main() { void sort(char *name[ ],int n); void print (char *name[ ],int n); char *name[]={"Follow me","BASIC", "Great Wall","FORTRAN","Computer design"}; int n=5; sort(name,n); print(name,n); } void sort(char *name[ ],int n) { char *temp; int i,j,k; for(i=0;i0) k=j; if(k!=i) { temp=name[i]; name[i]=name[k]; name[k]=temp;} } }name[0]name[1]name[2]name[3]name[4]nameGreat WallFORTRANComputerFollow meBASICkjki=0jjjvoid print(char *name[ ], int n) { int i ; for(i=0; i
  • 416. <> C语言程序设计 第十章 指针FORTRAN例10.26 对字符串排序(简单选择排序) #include #include void main() { void sort(char *name[ ],int n); void print (char *name[ ],int n); char *name[]={"Follow me","BASIC", "Great Wall","FORTRAN","Computer design"}; int n=5; sort(name,n); print(name,n); } void sort(char *name[ ],int n) { char *temp; int i,j,k; for(i=0;i0) k=j; if(k!=i) { temp=name[i]; name[i]=name[k]; name[k]=temp;} } }void print(char *name[ ], int n) { int i ; for(i=0; i
  • 417. 例10.26 对字符串排序(简单选择排序) #include #include void main() { void sort(char *name[ ],int n); void print (char *name[ ],int n); char *name[]={"Follow me","BASIC", "Great Wall","FORTRAN","Computer design"}; int n=5; sort(name,n); print(name,n); } void sort(char *name[ ],int n) { char *temp; int i,j,k; for(i=0;i0) k=j; if(k!=i) { temp=name[i]; name[i]=name[k]; name[k]=temp;} } }void print(char *name[ ], int n) { int i ; for(i=0; i C语言程序设计 第十章 指针name[0]name[1]name[2]name[3]name[4]nameGreat WallFORTRANComputerFollow meBASICkki=2jj
  • 418. 例10.26 对字符串排序(简单选择排序) #include #include void main() { void sort(char *name[ ],int n); void print (char *name[ ],int n); char *name[]={"Follow me","BASIC", "Great Wall","FORTRAN","Computer design"}; int n=5; sort(name,n); print(name,n); } void sort(char *name[ ],int n) { char *temp; int i,j,k; for(i=0;i0) k=j; if(k!=i) { temp=name[i]; name[i]=name[k]; name[k]=temp;} } }void print(char *name[ ], int n) { int i ; for(i=0; i C语言程序设计 第十章 指针name[0]name[1]name[2]name[3]name[4]nameGreat WallFORTRANComputerFollow meBASICkki=3j
  • 419. 例10.26 对字符串排序(简单选择排序) #include #include void main() { void sort(char *name[ ],int n); void print (char *name[ ],int n); char *name[]={"Follow me","BASIC", "Great Wall","FORTRAN","Computer design"}; int n=5; sort(name,n); print(name,n); } void sort(char *name[ ],int n) { char *temp; int i,j,k; for(i=0;i0) k=j; if(k!=i) { temp=name[i]; name[i]=name[k]; name[k]=temp;} } }void print(char *name[ ], int n) { int i ; for(i=0; i C语言程序设计 第十章 指针name[0]name[1]name[2]name[3]name[4]nameGreat WallFORTRANComputerFollow meBASIC
  • 420. <>指向指针的指针—多级指针(了解) 一级指针:指针变量中存放目标变量的地址 C语言程序设计 第十章 指针例 int *p; int i=3; p=&i; *p=5;&i3P(指针变量)i(整型变量)一级指针单级间接寻址p1&p2&i3P2(指针变量)i(整型变量)例 int **p1; int *p2; int i=3; p2=&i; p1=&p2; **p1=5;二级指针一级指针目标变量二级间接寻址二级指针:指针变量中存放一级指针变量的地址
  • 421. <>如果:char *name[ ]={"Follow me"……}; char **p; p=name+2; 则:printf("%s\n",*p); 输出:Great Wall C语言程序设计 第十章 指针name[0]name[1]name[2]name[3]name[4]nameGreat WallFORTRANComputerFollow meBASICnamep定义形式:[存储类型] 数据类型 **指针名; 如:char **p指针本身的存储类型最终目标变量的数据类型
  • 422. <> C语言程序设计 第十章 指针例10.27 用指向指针的指针处理字符串 #include void main( ) { char *name[ ]={"Follow me","BASIC", "Great Wall","FORTRAN","Computer design"}; char **p; int i; for(i=0;i<5;i++) { p=name+i; printf("%s\n",*p); } }*p是name[i]的值,即第i个字符串的起始地址运行结果: Follow me BASIC FORTRAN Great Wall Computer design
  • 423. <> C语言程序设计 第十章 指针例10.28 用指向指针的指针处理整型数据 #include void main( ) { int a[5]={1,3,5,7,9}; int *num[5]={&a[0],&a[1],&a[2],&a[3],&a[4]}; int **p, i; p=num; for(i=0;i<5;i++) { printf("%d ",**p); p++; } printf("\n"); }*p是p间接指向对象的地址 **p是p间接指向对象的值运行结果: 1 3 5 7 9
  • 424. <> C语言程序设计 第十章 指针二级指针与指针数组的关系 int **p 与 int *q[10] 指针数组名是二级指针常量 p=q; p+i 是q[i]的地址 指针数组作形参,int *q[ ]与int **q完全等价;但作为变量定义两者不同 系统只给p分配能保存一个指针值的内存区;而给q分配10块内存区,每块可保存一个指针值
  • 425. <>指针数组作main函数的形参(掌握) main函数的一般调用形式: main( ) main函数的有参数调用形式 : main( int argc , char *argv[ ] ) 其中( int argc , char *argv[ ] 是形参,可以多个: int argc; 命令名和所有参数个数之和 char *argv[ ]; 各元素是指针,分别指向各参数字符串 在实际运行程序时,实参和命令名(C程序编译和连接后得到的可执行文件名)以命令行形式给出: 命令名 参数1 参数2 …… 参数n [回车] C语言程序设计 第十章 指针
  • 426. <> C语言程序设计 第十章 指针例 用命令行参数方式运行程序/*test.c*/ main(int argc, char *argv[]) { while(argc>1) { ++argv; printf("%s\n",*argv); --argc; } }main(int argc, char *argv[]) { while(argc-->0) printf("%s\n",*argv++); }1. 编译、链接test.c,生成可执行文件test.exe 2. 在DOS状态下运行(test.exe所在路径下)例如: C:\TC> test[.exe] hello world!运行结果:hello world!运行结果:test hello world!argv[0]argv[1]argv[2]char *argv[]worldtesthelloargvargc=3
  • 427. <>10.8 有关指针的数据类型和指针运算的小结 有关指针的数据类型的小结 C语言程序设计 第十章 指针定 义含 义int i;定义整型变量iint *p ;p为指向整型数据的指针变量int a[n] ;定义有n个元素的整型数组aint *p[n] ;定义由n个指向整型数据的指针元素组成的指针数组pint (*p)[n] ;p为指向含n个元素的一维数组的指针变量int *p( ) ;p为返回一个指针的函数,该指针指向整型数据int (*p)( ) ;p为指向函数的指针,该函数返回一个整型值int **p ;p为一个指针变量,它指向一个指向整型数据的指针变量int f( ) ;f为可返回整型函数值的函数
  • 428. <>指针运算小结 ⑴ 指针变量加(减)一个整数 如:p++;p--;p+i;p-i;p+=i;p-=i等,加减的值与类型有关。 ⑵ 指针变量赋值 p=&a (将变量a的地址赋给p) p=array;(将数组array首地址赋给p) p=&array[i];(将数组array第i个元素的地址赋给p) p=max;(max为已定义的函数,将max函数的入口地址赋给p) p1=p2;(p1和p2都是指针变量,将p2的值赋给p1) (3) 指针变量不指向任何变量,即取空值。表示为:p=NULL; (4) 两个指针变量可以相减 如果两个指针变量指向同一个数组为元素,则两个指针变量值之差是 两个指针之间的元素个数。但p1+p2并无实际意义。 (5) 两个指针变量比较 如果两个指针变量指向同一个数组为元素,则可以进行地址比较。 C语言程序设计 第十章 指针
  • 429. <> C语言程序设计 第十章 指针例 下列定义的含义 ⑴ int *p[3]; ⑵ int (*p)[3]; ⑶ int *p(int); ⑷ int (*p)(int); ⑸ int *(*p)(int); ⑹ int (*p[3])(int); ⑺ int *(*p[3])(int);函数指针数组,函数返回int型指针指针数组指向一维数组的指针返回指针的函数指向函数的指针,函数返回int型变量函数指针数组,函数返回int型变量
  • 430. <>void指针类型 定义时不指定指向哪一类数据 用动态存储分配函数时返回void指针 它的值赋给另一指针变量时,要强制类型转换 例:char *p1; void *p2; ┊ p1=(char *)p2; 或p2=(void *)p1; void *fun(char ch1,char ch2) 返回“空类型”地址 P1=(char *)fun(ch1,ch2); 引用时要类型转换 C语言程序设计 第十章 指针
  • 431. <>本章作业: 10.1,10.3~10.5 10.8,10.11,10.17 10.7,10.9,10.14 本章上机:实验9 (2)~(4) 课后预习:第11章 结构体与共用 C语言程序设计 第十章 指针
  • 432. 第11章 结构体与共用体 掌握 C语言程序设计 第十一章 结构体与共用体概述定义结构体类型变量的方法结构体变量的引用结构体变量的初始化结构体数组指向结构体类型数据的指针用指针处理链表共用体枚举类型用typedef定义类型
  • 433. <>本章学习目标 理解结构体的概念和它对于编程的重要性; 理解定义结构体类型和定义结构体变量的区别; 能够用“ . ”和“->”分量运算符操作结构体变量和指向结构体的指针变量; 能够定义并使用结构体数组; 了解共用体数据类型 ; 自学了解枚举类型的使用; 了解用typedef定义数据类型。 C语言程序设计 第十一章 结构体与共用体
  • 434. <>11.1 概述 数据的基本类型:整、实、字符。 数组是构造类型:每个元素为同一类型 有些问题仅用基本类型和数组来描述,无法反映其内在联系,如学生情况: C语言程序设计 第十一章 结构体与共用体numnamesexagescoreaddr整字符串字符整实字符串11001Zhang xinm1996. 5Shang hai12001Wang lif2098. 5Bei jing 上述数据互相独立又相互关联,如:均与学号和姓名关联。需要将其组合成一个有机的整体,C语言可以将由不同类型数据组成的这种数据结构组织成一个组合项,称为结构体(structure)。
  • 435. <>结构体 结构体是一种构造数据类型。 与其他高级语言中的“记录”类似。 定义:由相互关联的不同数据类型的数据组成的有机整体。 用途:为处理复杂的数据结构提供了手段。 为函数间传递不同类型的参数提供了便利。 关键字:struct 结构体类型定义 C语言程序设计 第十一章 结构体与共用体struct [结构体名] { 类型标识符 成员名1; 类型标识符 成员名2; ……………. };成员类型可以是 基本型或构造型struct是关键字, 不能省略合法标识符 可省:无名结构体;不能省略注意:这只是声明一种数据类型并没有定义变量。
  • 436. <> C语言程序设计 第十一章 结构体与共用体struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }; namenumsexagescoreaddr2字节2字节20字节1字节4字节30字节……..结构体类型定义仅描述结构体的组成,不分配内存空间
  • 437. <>11.2 定义结构体类型变量的方法 声明结构体类型时不分配存储单元,使用该类型定义变量时才分配存储单元。定义变量方法3种: 先声明结构体类型,再定义结构体变量 C语言程序设计 第十一章 结构体与共用体struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }; struct student stu1,stu2; 定义结构体 类型定义结构体变量真正可以使用的变量struct 结构体名 { 类型标识符 成员名; 类型标识符 成员名; ……………. }; struct 结构体名 变量名表列;
  • 438. <>声明结构体类型的同时定义结构体变量 C语言程序设计 第十一章 结构体与共用体只有在定义了结构体变量后系统才为其分配内存。struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; } stu1,stu2 ; 定义结构体类型定义结构体变量struct 结构体名 { 类型标识符 成员名; 类型标识符 成员名; ……………. }变量名表列;
  • 439. <>直接定义结构体类型变量 C语言程序设计 第十一章 结构体与共用体用无名结构体直接定义变量只能一次struct { 类型标识符 成员名; 类型标识符 成员名; ……………. }变量名表列;struct { int num; char name[20]; char sex; int age; float score; char addr[30]; } stu1,stu2 ;
  • 440. <>说明 结构体类型与结构体变量概念不同 类型:不分配内存; 变量:分配内存 类型:不能赋值、存取、运算; 变量:可以 结构体变量中的成员可单独使用,方法如普通变量; 结构体可嵌套 C语言程序设计 第十一章 结构体与共用体struct date { int month; int day; int year; }; struct student { int num; char name[20]; struct date birthday; }stu;numnamebirthdaymonthdayyearprintf ("%d ", sizeof (stu) ); struct student { int num; char name[20]; struct date { int month; int day; int year; }birthday; }stu;结果:28结构体成员名与程序中变量名可相同
  • 441. <>结构体成员名与程序中变量名可相同,两者不代表同一个对象。 C语言程序设计 第十一章 结构体与共用体struct student { int num; char name[20]; float score; }stu; int num;stu. numnum
  • 442. <>11.3 结构体变量的引用 引用规则 结构体变量不能整体引用,只能引用变量成员 C语言程序设计 第十一章 结构体与共用体结构体变量名.成员名 成员(分量)运算符 优先级: 1 结合性:从左向右struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2; stu1.num=10; stu1.age++;stu1.score=85.5; stu1.score+=stu2.score;
  • 443. <> C语言程序设计 第十一章 结构体与共用体main() { struct student { int No; float score; } stu1,stu2; }scanf(“%d,%f”,&stu1); ()scanf(“%d,%f”,&stu1.No, &stu1.score); (√) printf(“%d,%f”,stu1); ()printf(“%d,%f” , stu1.No, stu1.score); (√) stu2=stu1; (√)
  • 444. <>结构体成员本身又是一个结构体类型,则需要找到最低一级的成员。 C语言程序设计 第十一章 结构体与共用体struct student { int num; char name[20]; struct date { int month; int day; int year; }birthday; }stu1,stu2;numnamebirthdaymonthdayyearstu1.birthday.month=12;结构体变量的成员与普通变量用法相同。
  • 445. 11.4 结构体变量的初始化 形式一 C语言程序设计 第十一章 结构体与共用体struct 结构体名 { 类型标识符 成员名1; 类型标识符 成员名2; ……………. }; struct 结构体名 结构体变量={初始数据};struct stu { int num; char name[20]; int age; char addr[30]; }; struct stu a={112,“Wang Lin”, 19, “200 Beijing Road”};
  • 446. <>形式二 C语言程序设计 第十一章 结构体与共用体struct 结构体名 { 类型标识符 成员名1; 类型标识符 成员名2; ……………. } 结构体变量={初始数据};struct stu { int num; char name[20]; int age; char addr[30]; } a={112,“Wang Lin”, 19, “200 Beijing Road”};
  • 447. <>形式三 C语言程序设计 第十一章 结构体与共用体struct { 类型标识符 成员名; 类型标识符 成员名; ……………. }结构体变量={初始数据};struct { int num; char name[20]; char sex; int age; char addr[30]; }stu1={112,“Wang Lin”,‘M’,19, “200 Beijing Road”};
  • 448. <> C语言程序设计 第十一章 结构体与共用体#include void main() { struct student { long int num; char name[20]; char sex; char addr[20]; }a={89031,“Li Lin”,‘M’, “123 Beijing Road”}; printf("No. :%ld\nname:%s\nsex:%c\naddress:%s\n", a.num,a.name,a.sex,a.addr); }例11.1 对结构体变量初始化运行结果:No. :89301 name:Li Lin sex:M address:123 Beijing Road
  • 449. <>11.5 结构体数组 具有相同结构的结构体也可以组成数组 定义结构体数组:3种形式 C语言程序设计 第十一章 结构体与共用体形式一:间接定义 struct student { int num; char name[20]; char sex; int age; }; struct student stu[2];numnamesexagenumnamesexagestu[0]stu[1]25B形式二:直接定义 struct student { int num; char name[20]; char sex; int age; }stu[2];形式三:直接定义 struct { int num; char name[20]; char sex; int age; }stu[2];
  • 450. <>结构体数组初始化 struct 结构名 结构数组名[数组长度]={初始数据}; C语言程序设计 第十一章 结构体与共用体定义数组时初始化: struct student { int num; char name[20]; char sex; int age; }; struct student stu[3]={{100,“Wang Lin”,‘M’,20}, {101,“Li Gang”,‘M’,19}, {110,“Liu Yan”,‘F’,19}}; 全部初始化时维数可省按顺序定义时: 内层括号可以省略声明结构体时,对结构体数组初始化: struct student { int num; char name[20]; char sex; int age; } stu[3]={{100,“Wang Lin”,‘M’,20}, {101,“Li Gang”,‘M’,19}, {110,“Liu Yan”,‘F’,19}}; 全部初始化时维数可省按顺序定义时: 内层括号可以省略
  • 451. <>结构体数组应用 C语言程序设计 第十一章 结构体与共用体struct student { int num; char name[20]; char sex; int age; }; struct student stu[ ]={{100,“Wang Lin”,‘M’,20}, ……}; stu[0].age++; strcpy(stu[0].name, “ ZhaoDa”);
  • 452. #include #include struct person { char name[20]; int count; }leader[3]={“Li”,0,“Zhang”,0,”Wang“,0}; void main() { int i,j; char leader_name[20]; for(i=1;i<=10;i++) { scanf("%s",leader_name); for(j=0;j<3;j++) if(strcmp(leader_name,leader[j].name)==0) leader[j].count++; } printf("\n"); for(i=0;i<3;i++) printf("%5s:%d\n",leader[i].name,leader[i].count);} C语言程序设计 第十一章 结构体与共用体例11.2 统计候选人选票全局结构体数组“.”成员运算符优先于“++”,所以Leader[j].count++相当于(learer[j].count)++namecountLiZhangWang000namecountLiZhangWang433
  • 453. <>11.6 指向结构体类型数据的指针 存放结构体首地址 结构指针的运算按照C语言的地址运算原则进行. 例如,结构指针加一将指向内存中下一个结构体。 指向结构体变量的指针 定义形式: struct 结构体名 *结构体指针名; 例 struct student *p; C语言程序设计 第十一章 结构体与共用体存放结构体变量在内存的起始地址numnamesexagestupstruct student { int num; char name[20]; char sex; int age; }stu; struct student *p=&stu;
  • 454. <>使用结构体指针变量引用成员形式 C语言程序设计 第十一章 结构体与共用体例 int n; int *p=&n; *p=10;  n=10struct student stu1; struct student *p=&stu1; stu1.num=101;  (*p).num=101以下三种形式等价: 结构体变量名.成员名 stu.num =101; (*结构体指针名).成员名 (*p).num=101 结构体指针名成员名 pnum =101指向运算符 优先级: 1 结合方向:从左向右( )不能少!
  • 455. <> C语言程序设计 第十一章 结构体与共用体#include #include void main() { struct student { long int num; char name[20]; char sex; float score; }stu_1,*p; p=&stu_1; stu_1.num=89101; strcpy(stu_1.name,"Li Lin"); (*p).sex='M'; pscore=89.5; printf("\nNo:%ld\nname:%s\nsex:%c\nscore:%f\n", (*p).num,pname,stu_1.sex,pscore);}例11.3 指向结构体变量的指针的应用
  • 456. <>注意区分以下三种运算 C语言程序设计 第十一章 结构体与共用体①p >n ② p >n++ ③ ++p >nstruct s { int x; int y; }data[4]={10,100,20,200,30,300,40,400}; main( ) { struct s *pointer=data; printf(“%d\n”, ++pointerx); printf(“%d\n”,(++pointer)y); printf(“%d\n”, (pointer++)x); printf(“%d\n”, (pointer)y++); }运行结果: 11 200 20 300 取x值加1后输出地址加1后再取y值先取x值地址再加1y值输出后再加1
  • 457. 指向结构体数组的指针 结构体数组及其元素可用指针变量来指向 数组首地址赋给指向结构体类型的指针变量时,当指针变量增1时,指向下一个数组元素。 C语言程序设计 第十一章 结构体与共用体#include struct student { int num; char name[20]; char sex; int age; } stu[3]={{10101,"Li Lin",'M',18}, {10102,"Zhang Fun",'M',19}, {10104,"Wang Min",'F',20}}; void main() { struct student *p; for(p=stu;p
  • 458. <>用结构体变量和指向结构体的指针作函数参数 将一个结构体变量的值传递给另一函数 ,方法有3种: 用结构体变量的成员作函数实参----值传递 注意形、实的类型要一致。 用指向结构体变量或数组的指针作实参----地址传递 传递的是结构体变量的地 址。 用结构体变量作参数----多值传递,效率低 将结构体变量所占的内存单元的内容全部顺序传递给形参,要求形参与实参同类型。函数调用是单值传递,且形参占用内存单元,若形参的值被改变,不会返回主调函数。 C语言程序设计 第十一章 结构体与共用体
  • 459. <> C语言程序设计 第十一章 结构体与共用体#include #include #define FORMAT "%d\n%s\n%f\n%f\n%f\n" struct student /*定义为外部结构体类型*/ { int num; char name[20]; float score[3];}; void main() { void print(struct student); struct student stu; /*定义为局部结构体类型变量*/ stu.num=12345; strcpy(stu.name,"Li Li"); stu.score[0]=67.5;stu.score[1]=89;stu.score[2]=78.6; print(stu); /*结构体变量作实参*/ } void print(struct student stu) { printf(FORMAT,stu.num,stu.name,stu.score[0],stu.score[1],stu.score[2]); printf(“\n”);}例11.5 结构体变量stu有学号、姓名和3门课成绩, 在main函数中赋值,在print函数中打印输出。 /* 对成员赋值也可以改为scanf函数输入*/ scanf("%d%s%f%f%f",&stu.num,stu.name, &stu.score[0],&stu.score[1],&stu.score[2]);无"&"
  • 460. C语言程序设计 第十一章 结构体与共用体#include #define FORMAT "%d\n%s\n%f\n%f\n%f\n" struct student /*定义为外部结构体类型*/ { int num; char name[20]; float score[3]; }; stu={12345, "Li Li",67.5,89,78.6}; void main() { void print(struct student * ); /*形参指向结构体的指针变量*/ print(&stu); /*实参为stu的起始地址*/ } void print(struct student *p) { printf(FORMAT,pnum,pname,pscore[0],pscore[1], pscore[2]); /*用指针变量调用成员之值*/ printf(“\n”); }例11.6 例11.5改为用结构体变量的指针作实参
  • 461. <>11.7 用指针处理链表 链表概述 数组:静态分配存储单元,容易造成内存浪费。 链表:是重要的数据结构,它根据需要,动态分配内存单元 。 C语言程序设计 第十一章 结构体与共用体head1249135614751021A 1356B 1475C 1021D Null1249特征:头指针变量,存放链表首地址,链表中每个元素称结点,其内容: 数据部分:可有若干项(整、实、字符、结构体类型等) 指针变量:下一结点的地址,最后一个结点(表尾)的地址部分为NULL。
  • 462. <>链表各结点的特点: 在内存中可以不连续,访问某结点应找上一结点提供的地址,每一结点有一指针变量存放下一结点的地址。 链表的每个结点实际上是一个结构体变量,它有若干成员组成,包括的内容有两部分: 数据部分:整、实、字符、结构体等类型。 指针变量:通常具有指向自身结构体类型的指针变量,此指针变量用来存放下一结点的地址,以便一环扣一环而形成链表。 C语言程序设计 第十一章 结构体与共用体struct student { int num; float score; struct student *next; };其中:next是成员名,是指针类型, 它指向struct student数据类型. 9910189. 599103909910785NULLnumscorenext
  • 463. 简单链表 C语言程序设计 第十一章 结构体与共用体#include #define NULL 0 struct student {long num; float score; struct student *next; }; void main( ) {struct student a,b,c,*head,*p; a.num=99101;a.score=89.5; b.num=99102;b.score=90; c.num=99103;c.score=85; head=&a;a.next=&b;b.next=&c; c.next=NULL; p=head; do { printf(“%ld %5.1f\n”,pnum,pscore); p=pnext; }while(p!=NULL); }例11.7 建立简单链表,它由3个学生数据的结点组成。 输出各结点中的数据。
  • 464. <> C语言程序设计 第十一章 结构体与共用体每个结点都属于struct student类型,它的next成员存放下一个结点的地址,这样一环扣一环,将各结节紧密的扣在一起,最后一次循环,将p=pnext是将c结点的地址赋给p,这时p指向c结点,然后将c结点的num,score输出,之后将p=pnext实际上是将c结点的next内容,即NULL赋给p 再进行判断, P!=NULL条件不成立,循环结束。 本例所有结点是在程序中定义的,不是临时开辟的,用完也不能释放,这种链表称“静态链表”。
  • 465. <>处理动态链表所需的函数 为处理动态链表,C提供了开辟和释放存储单元的函数: malloc函数 函数原型:void *malloc(unsigned int size); 作用:在动态区分配一个长度为size的连续空间,函数返回值是一个指向分配域起始地址的指针,如内存空间不足,返回空指针NULL。 (此处:void为无确定类型) C语言程序设计 第十一章 结构体与共用体calloc函数 函数原型:void *calloc(unsigned n,unsigned size); 作用:在内存动态区分配n个长度为size的连续空间,函数返回指向分配域起始地址的指针,若分 配不成功,返回NULL值。
  • 466. <>free函数 函数原型:void free(void *p); 作用:释放由p指向的内存区,使这部分内存区能被其它变量使用。P所指向的是最近一次calloc或malloc分配的存储区域。 free函数无返回值。 C语言程序设计 第十一章 结构体与共用体注:旧版本提供的malloc和calloc函数得到的是指向字符型数据的指针。 ANSI C提供的malloc和calloc函数规定为void *类型,这并不是说该函数调用后无返回值,而是返回一个结点的地址,该地址的类型为void(无类型或类型不确定),即一段存储区的首址,其具体类型无法确定,只有使用时根据各个域值数据再确定。
  • 467. <>建立动态链表 建立动态链表:是指在程序执行过程中从无到有地建立起一个链表,即一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。 C语言程序设计 第十一章 结构体与共用体例11.8 写一函数建立一个有3名学生数据的单向动态链表。 思路: ⑴ 设置3个指针变量head、p1、p2 head:指向链表头的指针变量,初始化head=NULL。 p1:指向后继结点的首地址的指针变量 p2:指向结点成员next的指针变量。 next的值是下一个结点的首地址。 ⑵ 循环方式用malloc函数开辟第1个结点。n=1 p1、p2指向第1结点首地址(见下页插图) 输入数据,如果p1num !=0, 则head=p1结点链入链表,反之不链入。
  • 468. <>⑶ 开辟第2个结点:n=2 p1指向第2结点首地址。 输入数据。 如果p1num !=0,链入2结点, 方法: p2next=p1 C语言程序设计 第十一章 结构体与共用体(n=1)99101 89.5 headp1p2⑷ 为建立第3个结点做准备: p2=p1,腾出p1 。(a) (n=2)headp2p199101 89.5 99103 90 headp2p199101 89.5 99103 90 (b) (n=2)headp2p199101 89.5 99103 90 (c) (n=2)
  • 469. <>⑸ 重复⑶⑷两步开辟第3个结点,并链入链表。 C语言程序设计 第十一章 结构体与共用体99101 89.5 99103 90 headp2p199107 85 (a) n=399101 89.5 99103 90 headp2p199107 85 (b) n=3n=n+1n==1 head=p1 p2next=p1 真 假(把p1所指结点作为第一个结点)(把p1所指结点连接到表尾)p2=p1 (p2移到表尾)再开辟一个新结点,使p1指向它读入一个学生数据给p1所指结点 表尾结点的指针变量置NULL开辟一个新结点,并使p1, p2指向它读入一个学生数据给p1所指向的结点head=NULL, n=0当读入的p1  num 不是零
  • 470. <> C语言程序设计 第十一章 结构体与共用体⑹ 再开辟新结点,由于num数据为0,退出循环。 并使p2next=NULL,虽然p1指向新结点但没有链入链表。 99101 89.5 99103 90 p2p199107 85 (a) n=3head0 0 0 0 99101 89.5 99103 90 p2p199107 85 NULL(b) n=3head
  • 471. <> C语言程序设计 第十一章 结构体与共用体#include “stdio.h” #include “malloc.h” #define NULL 0 #define LEN sizeof (struct student) struct student {long num; float score; struct student *next; }; int n; struct student *creat(void) { struct student *head; struct student *p1, *p2; n=0; p1=p2=(struct student *) malloc(LEN); scanf(“%ld,%f”,&p1  num, &p1  score); head=NULL; while(p1  num !=0) {n=n+1; if(n==1)head=p1; else p2  next=p1; p2=p1; p1=(struct student *)malloc (LEN); scanf(“%ld,%f”,&p1  num, & p1  score); } p2  next=NULL; return(head); }
  • 472. <> C语言程序设计 第十一章 结构体与共用体#include “stdio.h” /*改进后*/ #include “stdlib.h” #define NULL 0 #define LEN sizeof (struct student) struct student {long num; float score; struct student *next; }; int n; struct student *creat(void) { struct student *head; struct student *p1, *p2; flot s; n=0; p1=p2=(struct student *) malloc(LEN); scanf(“%ld,%f”,&p1  num,&s); p1  score=s; head=NULL; while(p1  num !=0) {n=n+1; if(n==1)head=p1; else p2  next=p1; p2=p1; p1=(struct student *)malloc (LEN); scanf(“%ld ,%f”,&p1  num,&s); p1  score=s; } p2  next=NULL; return(head); }
  • 473. <>输出链表 思路: 设一个指针变量p,找到链表第1个结点的地址(head的值),p指向该结点,输出结点各成员的数据,再p后移指向下一结点。 C语言程序设计 第十一章 结构体与共用体NULLheadPP’P=head,使p指向第一个结点 P指向的不是尾结点 真 假输出p所指向的结点p=p  next当p指的不是表尾
  • 474. <> C语言程序设计 第十一章 结构体与共用体例11.9 写一个输出链表的函数print。 void print( struct student *head) { struct student *p; printf(“\n Now, these %d records are :\n”, n); p=head; if(head) !=NULL) do { printf(“%ld, %5.2f\n”, p  num, p  score); p=p  next; } while(p !=NULL); }n从例11.8程序来
  • 475. <>对链表的删除操作 并不真从内存中抹掉,只是把它分离,再前后结点相链接。 C语言程序设计 第十一章 结构体与共用体例11.10 写一函数删除动态链表中指定的结点。 思路:本例以学号作为删除结点的标志(查找对象)。 ⑴ 设两个指针变量p1和p2。从head开始,p1依次指向各结点查找num值是否等于要删除结点的学号。每次下移前使p2=p1。学号相等删除该结点,直至查到表尾。99101 headp199103 99107 NULL(a) 初始状态p2(b) 下移一个结点 headp199107 NULL99101 99103 p2=p1
  • 476. <>⑵找到要删除的结点后: ①如果要删除的是第1结点,则head=p1next 。head指向第二结点,第一结点脱离。 C语言程序设计 第十一章 结构体与共用体head=p1  nextheadp1(c) 选中第一个结点99101 99107 NULL99103 ②如果要删除的不是第1结点,则p2next=p1next 。P1指向的结点脱离。 ③还要考虑链表为空和链表中没有要删除的结点的情况。headp2p1p2 next=p1  next (d) 第二个结点被删除99107 NULL99101 99103
  • 477. <> C语言程序设计 第十一章 结构体与共用体 p1是要删除的结点 是 否 链表是一个空表 真 假输出 空表p1=head 当num≠ p1  num 以及p1 所指的结点不是表尾结点p2=p1 (p2后移一个位置) p1 = p1  next (p1后移一个位置)输出“找不 到”的信息 P1所指是头结点 是 否head=p1 next (删除头结点)p2next=p1next (删除一个结点)
  • 478. <> C语言程序设计 第十一章 结构体与共用体struct student *del(struct student *head,long num) { struct student *p1,*p2; if(head = = NULL) {printf(“\n list null ! \n”); goto end; } p1=head; while(num !=p1  num && p1  next != NULL) { p2=p1; p1=p1  next; } if(num == p1  num) { if(p1 = = head) head=p1  next; else p2  next = p1  next; printf(“delete: %d\n”,num); n=n-1; } else printf(“%ld not been found ! \n”,num); return(head); }
  • 479. <>对链表的插入操作 假设结点按成员的学号从小到大排列,按排序顺序插入结点。 思路:找到插入点后,将该点的next值指向新结点,并使新结点的next值等于断点后面结点的首地址。 ⑴ 设置p0、p1、p2三个指针变量。创建一个新结点,p0指向其起始位置地址。p1指向第1个结点。 C语言程序设计 第十一章 结构体与共用体head99101 99103 99107 NULL99102 p0p1(a)准备将p0插入链表中
  • 480. <>⑵ 如果p0num大于p1num,则p2=p1,然后p1后移一个结点。直至p0num小于或等于p1num。这时p0所指结点插在p1所指结点之前。 C语言程序设计 第十一章 结构体与共用体head99101 99103 99107 NULL99102 p0p1p2(b) 插入点位于链表中间 p0num>p1num p2=p1, p1=p1next⑶ 如果插入点在链表中间,则p2next=p0,p0next=p1,新结点插入了链表。99103 99107 NULLp1head99101 99102 p0p2(c) 链接新结点 p0num ≤p1num p2next=p0, p0next=p1
  • 481. <>⑷ 如果插入点位于最前面,则head=p0,p0 next=p1。 C语言程序设计 第十一章 结构体与共用体99107 NULLhead99100 99103 99101 p0p1(d) 结点插在表首 p0num < p1num head=p0, p0next=p1⑸ 如果插入点位于最后面,则p1不再后移,p1next=p0, p0next=NULLp199101 99107 99103 99109 NULLp0(e) 结点插在表尾 p1next = p0 p0next = NULLhead
  • 482. <>将一个结点插入到链表中算法: C语言程序设计 第十一章 结构体与共用体p1=head, p0=stud 原来的链表是空表 是 否当p0  num > p1  num 以及p1所指的不是表尾结点 p2=p1 p1=p1  next p0  num ≤p1  num 真 假 P0指向头结点 是 否head=p0 p0  next=p1 (插到表头之前)p2  next=p0 p0  next=p1 (插到表中间)p1  next=p0 p0  next=NULL (插到表尾之后)将p0所 指的结 点作为 唯一结 点 n=n+1
  • 483. C语言程序设计 第十一章 结构体与共用体struct student *insert(struct student *head, struct student *stud) { struct student *p0, *p1, *p2; p1=head; /*使p1指向第一个结点*/ p0=stud; /*p0指向要插入的结点*/ if(head = = NULL) /*原来的链表是空表*/ {head=p0; p0next=NULL; } /*使p0指向的结点作为头结点*/ else { while((p0num > p1num) && (p1next != NULL)) { p2=p1; /*使p2指向刚才p1指向的结点*/ p1=p1  next; } /*p1后移一个结点*/ if(p0num <= p1num) { if(head == p1) head=p0; /*插到原来第一个结点之前 */ else p2next=p0; /*插到p2指向的结点之后*/ p0next = p1; } else {p1next=p0; p0next=NULL; } /*插到最后的结点之后*/ } n=n+1; /*结点数加1*/ return(head); }
  • 484. <>对链表的综合操作 用main函数作主调函数,调用前述建立、输出、删除、插入结点的函数。 C语言程序设计 第十一章 结构体与共用体void main( ) { struct student *head, *stu; long del_num; printf(“input records: \n”); head=creat(); /*建立链表,返回头指针*/ print(head); /*输出全部结点*/ printf(“\n input delete number:”); scanf(“%ld”, &del_num); /*输入要删除的学号*/ while(del_num !=0) { head=del(head,del_num); /*删除后链表的头地址*/ print(head); /*输出全部结点*/ printf(“input the delete number:”); scanf(“%ld”, &del_num); /*输入要删除的学号*/ }
  • 485. <> C语言程序设计 第十一章 结构体与共用体 printf(“\n input the inserted record:”); stu=(struct student *) malloc(LEN); scanf(“%ld,%f”, &stunum, &stuscore); /*输入要插入的结点*/ while(stunum !=0) { head=insert(head,stu); /*插入新结点,返回地址*/ print(head); /*输出全部结点*/ printf(“input the inserted record:”); stu=(struct student *) malloc(LEN); scanf(“%ld,%f”, &stunum, &stuscore); } }
  • 486. <>11.8 共用体(了解) 共用体概念 构造数据类型,也叫联合体 用途:使几个不同类型的变量共占一段内存(相互覆盖) 类型定义形式: C语言程序设计 第十一章 结构体与共用体union 共用体名 { 类型标识符 成员名; 类型标识符 成员名; ……………. };例 union data { int i; char ch; float f; };fchi类型定义不分配内存
  • 487. <>共用体变量的定义 C语言程序设计 第十一章 结构体与共用体形式一: union data { int i; char ch; float f; } a,b;形式二: union data { int i; char ch; float f; }; union data a,b,c,*p,d[3];形式三: union { int i; char ch; float f; } a,b,c;fchifchiab共用体变量定义分配内存, 长度=最长成员所占字节数共用体变量任何时刻 只有一个成员存在
  • 488. <>共用体变量的引用方式 3种方式等价: 共用体变量名.成员名 共用体指针名成员名 (*共用体指针名).成员名 C语言程序设计 第十一章 结构体与共用体union data { int i; char ch; float f; }; union data a,b,c,*p,d[3];a.i a.ch a.fp->i p->ch p->f(*p).i (*p).ch (*p).fd[0].i d[0].ch d[0].f引用规则 不能引用共用体变量, 只能引用其成员printf("%d",a) ; () printf("%d",a.i); (√)
  • 489. <>共同体类型数据的特点 ⑴ 同一个内存段可以用来存放几种不同类型的成员,但在每 一瞬时只能存放其中一种,而不是同时存放几种。 ⑵ 共用体变量中起作用的成员是最后一次存放的成员 C语言程序设计 第十一章 结构体与共用体例 a.i=1; a.ch=‘a’; a.f=1.5; printf(“%d”,a.i); (  编译通过,运行结果不对) printf("%f",a.f); (√)⑶ 共用体变量和它的各成员的地址都是同一地址。
  • 490. <>⑷ 不能对共用体变量名赋值,也不能在定义共用体变量时初始化。但可以用一个共用体变量为另一个变量赋值 C语言程序设计 第十一章 结构体与共用体例:union { int i; char ch; float f; }a={1,’a’,1.5}; () a=1; () m=a; ()⑸ 不能把共用体变量作为函数参数,也不能使函数带回共用体变量,但可以使用指向共用体变量的指针(与结构体变量的这种用法相仿)。 ⑹共用体类型可出现在结构体类型定义中,也可以定义共用体数组。反之,结构体也可出现在共用体类型定义中,数组也可作为共用体的成员。例:float x; union { int i; char ch; float f; }a,b; a.i=1; a.ch=‘a’; a.f=1.5; b=a; () x=a.f; ()
  • 491. <> C语言程序设计 第十一章 结构体与共用体例11.12 设有若干个人员的数据,其中有学生和教师。学生的数据中包括:姓名、号码、性别、职业、班级。教师的数据包括:姓名、号码、性别、职业、职务。现要求把它们放在同一表格中算法: 循环n次输出“输入错”读入positionjob=‘t’ 真 假 输出:姓名、号码、 性别、职业、职务 输出:姓名、号码 、 性别、职业、班级job=‘s’ 真 假 读入class职业job=‘s’ 真 假读入姓名、号码、性别、职业 循环n次
  • 492. <>程序: C语言程序设计 第十一章 结构体与共用体#include struct { int num; char name[10]; char sex; char job; union { int banji; char position[10]; } category; } person[2];proftm2085Wang501sf1011Lijobsexnumname
  • 493. C语言程序设计 第十一章 结构体与共用体void main( ) { int n,i; for(i=0;i<2;i++) { scanf(“%d,%s,%c,%c”,&person[i].num,&person[i].name,&person[i].sex, &person.job); if(person[i].job==‘s’) scanf(“%d”,&person[i].category.banji); else if(person[i].job==‘t’) scanf(“%s”,&person[i].category.position); else printf(“input error”); } printf(“\n”); printf(“No. Name sex job class/position\n”); for(i=0;i<2;i++) { if(person[i].job==‘s’) printf(“%-6d %-10s %-3c %-3c %-6d\n”,person[i].num,person[i].name, person[i].sex, person[i].job, person[i].category.banji); else printf(“%-6d %-10s %-3c %-3c %-6s\n”,person[i].num,person[i].name, person[i].sex, person[i].job, person[i].category.position); } }
  • 494. <>11.9 枚举类型 枚举类型是ANSI C新标准所增加的。 如果一个变量只有几种可能的值,可以定义为枚举类型。所谓“枚举是指将变量的值一一列举出来,变量的值只限于列举出来的值的范围内。 C语言程序设计 第十一章 结构体与共用体枚举类型及其变量的定义形式: enum 枚举类型名 {枚举元素列表} 枚举变量列表; 可以先声明类型再定义变量,或同时进行或直接定义变量。enum weekday {sun,mon,tue,wed,thu,fri,sat}; enum weekday workday,week_end;enum weekday {sun,mon,tue,wed,thu,fri,sat} workday,week_end;enum {sun,mon,tue,wed,thu,fri,sat} workday,week_end;
  • 495. <> 其中sun, mon, … , sat等称为枚举元素或枚举常量。它们是用户定义的标识符。 说明: 在编译中,对枚举元素按常量处理,它们不是变量,不能对它们赋值。 枚举元素作为常量,它们是有值的,语言编译按定义时的顺序使它们的值为0,1,2,…。 枚举值可以用来做判断比较。如: if(workday = = mon)… if(workday > sun)… 一个整数不能直接赋给一个枚举变量。应先进行强制类型转换才能赋值。如: workday = (enum ewwkday)2; C语言程序设计 第十一章 结构体与共用体
  • 496. <> C语言程序设计 第十一章 结构体与共用体例11.13 口袋中有红、黄、蓝、白、黑5种颜色的球若干个。每次从口袋中先后取出3个球,问得到3种不同色的球的可能取法,打印出每种排列的情况。要判断各球是否同色,应用枚举类型变量处理。设取出的球为i, j, k。根据题意,i、j、k分别是5种色球之一,并要求i≠j≠k。可以用穷举法,即一种可能一种可能地试,看哪一组符合条件。 n = 0n = n + 1输出一种取法 i≠j和 k ≠j 真 假 k从red变到black i≠j 真 假 j从red变到black输出取法的总数n i从red变到blackloop由1到3loop的值1 2 3i prii prii pripri的值 redyellowbluewhiteblack 打印 “red” 打印 “yellow” 打印 “blue”打印 “white” 打印 “black”
  • 497. <> C语言程序设计 第十一章 结构体与共用体#include void main( ) {enum color{red,yellow,blue,white,black}; enum color i,j,k,pri; int n,loop; n = 0; for(i=red;i<=black;i++) for(j=red;j<=black;j++) if(i != j) {for(k=red;k<=black;k++) if((i != j) && (k != j)) {n=n+1; printf(“%-4d”,n); for(loop=1;loop<=3;loop++) {switch(loop) {case 1: pri=i;break; case 2: pri=j;break; case 3: pri=k;break; default: break; } switch(pri) { case red: printf(”%-10s”,”red”);break; case yellow: printf(”%-10s”,”yellow”); break; case blue: printf(”%-10s”,”blue”); break; case white: printf(”%-10s”,”white”); break; case black: printf(”%-10s”,”black”); break; default: break; } } printf(”\n”); } } printf(”\ntotal:%5d\n”,n); }
  • 498. <>11.10 用typedef定义类型 功能:用自定义名字为已有数据类型命名 类型定义简单形式: typedef type name; C语言程序设计 第十一章 结构体与共用体类型定义语句关键字已有数据类型名用户定义的类型名例 typedef int INTEGER;例 typedef float REAL;类型定义后,与已有类型一样使用例 INTEGER a,b,c; REAL f1,f2; int a,b,c; float f1,f2; 说明: 1.typedef 没有创造新数据类型 2.typedef 是定义类型,不能定义变量 3.typedef 与 define 不同 define typedef 预编译时处理 编译时处理 简单字符置换 为已有类型命名
  • 499. <>typedef定义类型步骤 ① 按定义变量方法写出定义体 如 int i; ② 将变量名换成新类型名 如 int INTEGER; ③ 最前面加typedef 如 typedef int INTEGER; ④ 用新类型名定义变量 如 INTEGER i,j; C语言程序设计 第十一章 结构体与共用体类型定义可嵌套例 定义数组类型 int a[100]; int ARRAY[100]; typedef int ARRAY[100]; ARRAY a,b,c;  int a[100],b[100],c[100];例 定义指针类型 char *str; char *STRING; typedef char *STRING; STRING p,s[10];  char *p; char *s[10];例 定义函数指针类型 int (*p)(); int (*POWER)(); typedef int (*POWER)(); POWER p1,p2;  int (*p1)(),(*p2)();例 定义结构体类型 typedef struct date { int month; int day; int year; }DATE;例 定义结构体类型 struct date { int month; int day; int year; }DATE;例 定义结构体类型 struct date { int month; int day; int year; }d;例 定义结构体类型 DATE birthday, *p; struct date { int month; int day; int year; }birthday, *p;例 typedef struct club { char name[20]; int size; int year; }GROUP; typedef GROUP *PG; PG pclub;  GROUP *pclub;  struct club *pclub;GROUP为结构体类型 PG为指向GROUP的指针类型
  • 500. <>本章作业 11.3 11.4 11.8 上机作业:实验10 预习:第13章 文件 C语言程序设计 第十一章 结构体与共用体
  • 501. 第13章 文件 C语言程序设计 第十章 指针C文件概述文件类型指针文件的打开与关闭文件的读写文件的定位出错的检测文件输入输出小结
  • 502. <>本章学习目标 理解文本文件和二进制文件的区别; 理解 FILE *fp 文件指针; 能够用函数fopen和fclose打开和关闭文件; 掌握常用的文件读/写函数; C语言程序设计 第十三章 文件
  • 503. <>13.1 C文件概述 文件:存储在外部介质上数据的集合,是操作系统数据管理的单位。 C语言程序设计 第十三章 文件使用数据文件的目的 1、数据文件的改动不引起程序的改动——程序与数据分离。 2、不同程序可以访问同一数据文件中的数据——数据共享。 3、能长期保存程序运行的中间数据或结果数据。文件分类 按文件的逻辑结构: 记录文件:由具有一定结构的记录组成(定长和不定长) 流式文件:由一个个字符(字节)数据顺序组成
  • 504. <>按存储介质: 普通文件:存储介质文件(磁盘、磁带等) 设备文件:非存储介质(键盘、显示器、打印机等) 按数据的组织形式: 文本文件: ASCII文件,每个字节存放一个字符的ASCII码 二进制文件:数据按其在内存中的存储形式原样存放 C语言程序设计 第十三章 文件C语言的文件是流式文件。 所谓流就是一系列的字节或者字符,输入输出数据流的开始和结束仅受程序控制,而不受物理符号(如回车符)的控制。这种文件称为流式文件。1000000100111000100000011000100110000001100000011000000110000ASCII文件0010011100010000二进制文件
  • 505. <> C语言程序设计 第十三章 文件如 int型数100000010011100010000内存存储形式0010011100010000二进制形式0011000100110000001100000011000000110000ASCII形式文本文件特点: 存储量大、速度慢、便于对字符操作二进制文件特点: 存储量小、速度快、便于存放中间结果
  • 506. <>文件处理方法 缓冲文件系统:高级文件系统,系统自动为正在使用的文件开辟内存缓冲区。可减少主机和外部设备频繁交换数据的次数 非缓冲文件系统:低级文件系统,由用户在程序中为每个文件设定缓冲区 C语言程序设计 第十三章 文件磁盘文件输出文件缓冲区输入文件缓冲区程序数据区a缓冲文件系统:缓冲区指令区程序用户数据区磁盘非缓冲文件系统:
  • 507. <>13.2 文件类型指针 文件结构体类型FILE 缓冲文件系统为每个正使用的文件在内存开辟文件信息区 文件信息用系统定义的名为FILE的结构体描述 Turbo C在stdio.h文件中有以下的文件类型声明: C语言程序设计 第十三章 文件typedef struct { short level; /*缓冲区“满”或“空”的程度*/ unsigned flags; /*文件状态标志*/ char fd; /*文件描述符*/ unsigned char hold; /*如无缓冲区不读取字符*/ short bsize; /*缓冲区的大小*/ unsigned char *buffer; /*数据缓冲区的位置*/ unsigned ar *curp; /*指针,当前的指向*/ unsigned istemp /*临时文件,指示器*/ short token; /*用于有效性检查*/ }FILE;
  • 508. <>定义文件类型变量 存放文件的信息 如:定义FILE类型数组,存放若干文件信息:FILE f[5]; 定义文件型指针变量,指向FILE类型结构体变量,通过该结构体变量中的文件信息访问文件。 如:FILE *fp; 用法: 文件打开时,系统自动建立文件结构体,并把指向它的指针返回来,程序通过这个指针获得文件信息,访问文件 如:fp=fopen("a1","r"); 文件关闭后,它的文件结构体被释放 C语言程序设计 第十三章 文件经过定义的文件指针,就可以用来指向一个文件!
  • 509. <>13.3 文件的打开与关闭 C文件操作用库函数实现,包含在stdio.h 文件使用方式:打开文件→文件读/写→关闭文件 系统自动打开和关闭三个标准文件: 标准输入------键盘 stdin 标准输出------显示器 stdout 标准出错输出-----显示器 stderr C语言程序设计 第十三章 文件文件的打开(fopen函数) 函数原型: FILE *fopen(char *name,char *mode) 调用方式:fopen("文件名","使用文件方式") 例:FILE *fp; fp=fopen("d:\\user\\myfile.txt","r");为什么 \\ Read
  • 510. <>返回值:正常打开,返回指向文件结 构体的指针;打开失败,返回 NULL C语言程序设计 第十三章 文件FILE *fp; fp=fopen(“aa.c”,“w”); if(fp==NULL) { printf(“File open error!\n”); exit(0); /*关闭所有文件终止调用*/ }方式处理方式指定文件不存在文件存在 r 只读 出错 正常 w 只写 建立新文件 原内容丢失 a 追加 建立新文件 在原内容后追加 r+/w+ 读写 出错 正常r:读方式; w:写方式; a:追加方式; rb/wb/ab:二进制方式; +:既可读又可写
  • 511. <>文件的关闭(fclose函数) 作用:使文件指针变量与文件“脱钩”,释放文件结构体和文件指针 C语言程序设计 第十三章 文件FILE *fp; fp=fopen(“a.txt”,“r”); fclose(fp);返回值:用于表示文件是否被正确地关闭,如果文件顺利关闭,该值为0,否则为-1(EOF)。 返回值可以用ferror函数测试
  • 512. <>13.4 文件的读写 文件打开之后,就可以对它进行读与写的操作了。 读/写文件中的一个字符 fputc函数(putc函数) 函数原型:int fputc(int c, FILE *fp) 功能:把一字节代码c写入fp指向的文件中 返值:正常,返回c;出错,为EOF(-1) C语言程序设计 第十三章 文件fgetc函数(getc函数) 函数原型:int fgetc(FILE *fp) 功能:从fp指向的文件中读取一字节代码 返值:返回读到的代码值;读到文件尾或出错为EOF(-1)feof函数 调用方式:feof(fp) 功能:对于二进制文件读取时判断文件是否结束。 返值:结束-1;反之0。字符常量或变量文件指针变量文件指针变量
  • 513. <>文件I/O与终端I/O的关系 C语言程序设计 第十三章 文件#define putc(ch,fp) fputc(ch,fp) #define getc(fp) fgetc(fp) #define putchar( c ) fputc(c,stdout) #define getchar( ) fgetc(stdin)文本文件: FILE *fp; fp=fopen(“a.txt”,“r”); ch=fgetc(fp); while(ch!=EOF) { putchar(ch); ch=fgetc(fp); } fclose(fp);二进制或文本文件: FILE *fp; fp=fopen(“a1”,“r”); ch=fgetc(fp); while(!feof(fp)) { putchar(ch); ch=fgetc(fp); } fclose(fp);
  • 514. <> C语言程序设计 第十三章 文件例13.1 从键盘输入一些字符,逐个把它们送到磁盘上去,直到输入一个“#”为止。#include #include void main() { FILE *fp; char ch , filename[10]; scanf("%s“, filename); if((fp=fopen(filename,"w"))==NULL) { printf("cannot open file\n"); exit(0); } /*终止程序*/ ch=getchar(); /*接收执行scanf时最后输入的回车符*/ ch=getchar(); /*第一个输入的字符被赋给变量ch*/ while(ch!='#') { fputc(ch,fp); /*字符被写入filename表示的文件中*/ putchar(ch); /*字符被输出到显示器*/ ch=getchar(); } putchar(10); /*向屏幕输出一个换行符*/ fclose(fp); } /*关闭文件*/
  • 515. <> C语言程序设计 第十三章 文件例13.2 将一个磁盘文件中的信息复制到另一个磁盘文件中。#include #include void main() { FILE *in, *out; char ch,infile[10],outfile[10]; printf("Enter the infile name:\n"); scanf("%s",infile); /*输入文件的文件名*/ printf("Enter the outfile name:\n"); scanf("%s",outfile); /*输出文件的文件名*/ if ((in = fopen(infile, "r"))== NULL) { printf("Cannot open infile.\n");exit(0); } if ((out = fopen(outfile, "w"))== NULL) { printf("Cannot open outfile.\n");exit(0); } while (!feof(in)) fputc(fgetc(in), out); fclose(in); fclose(out); }二进制文件时:“ rb ”和“ wb ”
  • 516. <> C语言程序设计 第十三章 文件例 用main参数,在输入命令行时把两个文件名一起输入。#include #include void main(int argc,char *argv[ ]) { FILE *in, *out; char ch; if(argc!=3) { printf("You forgot to enter a filename\n"); exit(0); } if ((in = fopen(argv[1], "r"))== NULL) { printf("Cannot open infile.\n"); exit(0); } if ((out = fopen(argv[2], "w"))== NULL) { printf("Cannot open outfile.\n"); exit(0); } while (!feof(in)) fputc(fgetc(in), out); fclose(in); fclose(out); }当可执行文件名是:a.exe 输入命令行:C:\>a file1.c file2.c 则:file1中内容复制到file2文件中
  • 517. <>数据块输入输出函数:fread与fwrite 一般调用形式: fread(buffer,size,count,fp ); fwrite(buffer,size,count,fp ); 参数说明: buffer: 要读入的数据块的存放首地址或要输出的数据块的起始地址。 size: 每个要读/写的数据块的大小(字节数) count: 要读/写的数据块的个数 fp: 要读/写的文件指针 返值:成功,返count的值;出错或文件尾,0值。 fread与fwrite 一般用于二进制文件的输入/输出 若文件以二进制形式打开,用fread或fwrite 可读写任何类型的数据。如: fread(f, 4, 2, fp) C语言程序设计 第十三章 文件
  • 518. <> C语言程序设计 第十三章 文件#include #define SIZE 4 struct student_type { char name[10]; int num; int age; char addr[15]; }stud[SIZE]; void main() { int i; for(i=0;i
  • 519. <> C语言程序设计 第十三章 文件void save() { FILE *fp; int i; if((fp=fopen("d:\\stu_list","wb"))==NULL) { printf("cannot open file\n"); return; } for(i=0;i
  • 520. <> C语言程序设计 第十三章 文件例13.3b 将4个学生的数据,从磁盘文件stu_dat调入,然后输出到stu_list文件中,并在屏幕上显示磁盘文件的内容。#include #define SIZE 4 struct student_type { char name[10]; int num; int age; char addr[15]; }stud[SIZE]; main() { load(); save(); display(); }void load() { FILE *fp; int i; if((fp=fopen("d:\\stu_dat","rb"))==NULL) { printf("cannot open file\n"); return;} for(i=0;i
  • 521. <>按指定格式读写文件的函数:fprintf和fscanf 一般调用格式:fscanf(fp,格式字符串,输入列表); fprintf(fp,格式字符串,输出列表); 返值:成功,返回I/O的个数;出错或文件尾,返回EOF 由于输入输出时要进行ASCII码和二进制形式的转换,费时较多。 C语言程序设计 第十三章 文件fscanf( fp,“%d,%f”,&i,&t); /*若文件中有 3 , 4.5 ,则将3读出送入 i , 4.5读出送入t*/ fprintf(fp,“%d,%6.2f”,i,t); /*将i和t按 %d, %6.2f 格式写入到 fp文件*/
  • 522. <> C语言程序设计 第十三章 文件void save() { FILE *fp; int i; if((fp=fopen("d:\\stu_list","w"))==NULL) { printf("cannot open file\n"); return; } for(i=0;i
  • 523. <>其它读写函数 1. putw和getw函数 作用:以二进制形式,对磁盘文件读写一个 int 型的整数,2个字节。 返值:成功:所写的整数值;失败:EOF。 如:putw(10,fp); i=getw(fp); C语言程序设计 第十三章 文件2. fgets 和fputs函数 形式:fgets(str,n,fp); (str字符数组,n-1个字符) fputs(字符串,fp); ("\0"不输出) 作用:从fp指向的文件读/写一个字符串 返值: fgets正常时返回字符串的首地址;出错或文件尾,NULL fputs正常时返回写入的最后一个字符;出错为EOF
  • 524. <> C语言程序设计 第十三章 文件例 从键盘读入字符串存入文件,再从文件读回显示#include void main() { FILE *fp; char string[81]; if((fp=fopen("file.txt","w"))==NULL) { printf("cann't open file");exit(0); } while(strlen(gets(string))>0) { fputs(string,fp); fputs("\n",fp); } fclose(fp); if((fp=fopen("file.txt","r"))==NULL) { printf("cann't open file");exit(0); } while(fgets(string,81,fp)!=NULL) fputs(string,stdout); fclose(fp); }
  • 525. <>13.5 文件的定位 几个概念 文件位置指针-----指向当前读写位置的指针,具体位置由文件打开方式确定。 “r”“w”:指向文件头 “a”:指向文件尾 读写方式 顺序读写:位置指针按字节位置顺序移动。 随机读写:位置指针按需要移动到任意位置。 C语言程序设计 第十三章 文件
  • 526. <>rewind函数 函数原型: void rewind(FILE *fp) 功能:重置文件位置指针到文件开头 返值:无 C语言程序设计 第十三章 文件例13.4 对一个磁盘文件进行显示和复制两次操作#include void main() { FILE *fp1,*fp2; fp1=fopen("c:\\tc\\user\\ch12_4.c","r"); fp2=fopen("d:\\tc\\user\\ch12_41.c","w"); while(!feof(fp1)) putchar(getc(fp1)); rewind(fp1); while(!feof(fp1)) putc(getc(fp1),fp2); fclose(fp1); fclose(fp2); }
  • 527. fseek函数和随机读写 调用形式:fseek(文件类型指针,位移量,起始点) 功能:改变文件位置指针的位置 返值:成功,返回0;失败,返回非0值 C语言程序设计 第十三章 文件位移量(以起始点为基点,移动的字节数) >0 向后移动,<0 向前移动起始点 文件开始 SEEK_SET 0 文件当前位置 SEEK_CUR 1 文件末尾 SEEK_END 2例 fseek(fp,100L,0); fseek(fp,50L,1); fseek(fp,-10L,2); 例13.5 文件内存有10个学生数据,将单数学生数据输入计算机并在屏幕上显示void main() { FILE *fp; int i; if((fp=fopen("stud_dat","rb"))==NULL) { printf("cannot open file\n"); exit(0);} for(i=0;i<10;i+=2) { fseek(fp,i*sizeof(struct student_type),0); fread(&stud[i],sizeof(struct student_type), 1,fp); printf("%s %d %d %c\n",stud[i].name,stud[i].num, stud[i].age,stud[i].sex); } fclose(fp); }#include #include struct student_type { char name[10]; int num; int age; char sex; }stud[10];
  • 528. <>ftell函数 函数原型: long ftell(FILE *fp) 功能:得到流式文件中位置指针当前位置(用相对于文件开头的位移量表示) 返值:返回当前位置指针位置;失败,返回-1L C语言程序设计 第十三章 文件例 求文件长度 #include"stdio.h" main() { FILE *fp; char filename[80]; long length; gets(filename); fp=fopen(filename,"rb"); if(fp==NULL) printf("file not found!\n"); else { fseek(fp,0L,SEEK_END); length=ftell(fp); printf("Length of File is %1d bytes\n",length); fclose(fp); } }
  • 529. <>13.6 出错的检测 ferror函数:测试文件是否出现错误 调用形式: ferror(fp); 返值:未出错,0;出错,非0 说明 每次调用文件输入输出函数,均产生一个新的ferror函数值,所以应及时测试 fopen打开文件时,ferror函数初值自动置为0 C语言程序设计 第十三章 文件clearerr函数 调用形式: clearerr(fp); 功能:使文件错误标志置为0,无返值。 说明:出错后,错误标志一直保留,直到对同一文件调clearerr(fp)或rewind或任何其它一个输入输出函数
  • 530. <> C语言程序设计 第十三章 文件例 ferror()与clearerr()举例 #include int main(void) { FILE *stream; stream = fopen("DUMMY.FIL", "w"); getc(stream); if (ferror(stream)) { printf("Error reading from DUMMY.FIL\n"); clearerr(stream); } if(!ferror(stream)) printf("Error indicator cleared!"); fclose(stream); return 0; }
  • 531. <>13.7 文件输入输出小结 在使用文件时,首先要定义一个文件指针:FILE *fp;然后通过该指针来操作相应的文件; 通过fopen这个函数,使文件指针fp和相应的文件建立了联系,通过fclose函数将fp和文件的联系切断; 文件可以以文本的方式打开(默认或“t”),也可以以二进制方式打开(“b”); 如果以一次一个字符的方式处理文件,需要用fgetc或者fputc函数; 如果以一次一行的方式处理文件,可以用函数fgets或者fputs; 如果以一次一个结构体的方式处理文件,可以用函数fread和fwrite(多为二进制文件); fscanf和fprintf函数使用很广泛,应重点掌握。 C语言程序设计 第十三章 文件
  • 532. <> C语言程序设计 第十三章 文件本章作业 13.4 13.6 13.7 13.12 上机: 实验12
  • 533. <>13.1 概述 在函数调用过程中,直接或间接的调用自身。 递归调用方式 直接递归调用:在函数体内又调用自身 C语言程序设计 第十三章 文件

关键词

C/C++开发 试题 C# C/C++ Basic

相关PPT

 C语言教程
 C语言入门教程
 C语言开发实例教程
 最基础的c语言教程
 C 语言概述
 C语言语法
 c语言课件
 C语言 预处理
 C语言指针讲解
 c语言编程规范
社区
项目
问答
文库
代码
经验
资讯
  • 安卓开发专栏
  • 开发者周刊
  • Android Studio 使用推荐
  • Android开发推荐
帮助中心
  • 文档上传须知
关于我们
  • 关于深度开源
  • 免责声明
  • 联系我们
深度开源© 2006-2019 深度开源 —— 开源项目,开源代码,开源文档,开源新闻,开源社区  杭州精创信息技术有限公司  

  浙公网安备 33018302001163 号  浙ICP备09019653号-31