Presentation is loading. Please wait.

Presentation is loading. Please wait.

C++语言.

Similar presentations


Presentation on theme: "C++语言."— Presentation transcript:

1 C++语言

2 课程介绍 课程简介 任课教师 授课内容及授课时间 参考资料 学习建议

3 课程简介 课程信息 授课地点 授课时间 实验课 实验地点 实验时间 实验助教 课程名称 《C++程序设计》 软件园5区407d 1-12周上
第一次课 9月7日(周一),最后一次课11月16号 实验课 第5周开始实验 5-12周上 实验地点 实验楼203 实验时间 周四9-10节,17:30-19:30 实验助教 李慧宇(QQ: ) 秦溥(QQ: )

4 任课教师 杨义军 副教授 联系方式 研究方向: 网格参数化以及屏幕校正
办公室:高性能三楼实验室 研究方向: 网格参数化以及屏幕校正

5 授课内容 序号 时间 内容 1 9月7日 C++的初步知识 2 9月14日 数据类型 3 9月21日 表达式 4 9月28日 循环语句 5
10月5日 条件语句 6 10月12日 函数 7 10月19日 预处理 8 10月26日 数组 9 11月2日 自定义数据类型 10 11月9日 运算符重载 11 11月16日 对象指针 12 11月23日 函数指针

6 参考材料 作者 谭浩强 部分c语言知识 入门教材

7 参考材料 Author Stanley B. Lippman Barbara E. Moo Josée LaJoie 不适合入门

8 参考资料 Author Stephen Prata 最好的C++入门书 太厚

9 参考资料 The C++ Programming Language, Special Edition Author
Bjarne Stroustrup C++之父

10 参考资料 C程序设计语言 Author Brian W.Kernighan Dennis M.Ritchie 标准C语言教材

11 学习建议 任何一本书都可以读 关键是编程实践 自己找小题目 自己实现小算法 有明确的目标

12 第一章C++概述 C++语言发展历史 自从1946年第一台电子数字计算机ENIAC问世以来,随着计算机应用领域的不断扩大,促进了计算机技术的高速发展,尤其是近年来计算机的硬件和软件都是日新月异。作为应用计算机的一种工具—程序设计语言,得到不断的充实和完善。每年都有新的程序设计语言问世,老的程序设计语言不断地更新换代。

13 20世纪60年代,Martin Richards为计算机软件人员在开发系统软件时,作为记述语言使用而开发了BCPL语言(Basic Combined Programming Language)。1970年,Ken Thompson在继承BCPL语言的许多优点的基础上发明了实用的B语言。到了1972年,贝尔实验室的Dennis Ritchie和Brian kernighan在B语言的基础上,作了进一步的充实和完善,设计出了C语言。当时,设计C语言是为了编写UNIX操作系统的。以后,C语言经过多次改进,并开始流行。C++是在C语言的基础上发展和完善的,而C是吸收了其它语言的优点逐步成为实用性很强的语言。

14 C语言的主要特点是: 1、C语言是一种结构化的程序设计语言,语言本身简洁、使用灵活方便。既适用于设计和编写大的系统程序,又适用于编写小的控制程序,也适用科学计算。 2、它既有高级语言的特点,又具有汇编语言的特点。运算符丰富,除了提供对数据的算术逻辑运算外,还提供了二进制的位运算。并且也提供了灵活的数据结构。用C语言编写的程序表述灵活方便,功能强大。用C语言开发的程序,其结构性好,目标程序质量高,程序执行效率高。

15 3、程序的可移植性好。用C语言在某一种型号的计算机上开发的程序,基本上可以不作修改,而直接移植到其它型号和不同档次的计算机上运行。
4、程序的语法结构不够严密,程序设计的自由度大。这对于比较精通C语言的程序设计者来说,可以设计出高质量的非常通用的程序。但对于初学者来说,要能比较熟练运用C语言来编写程序,并不是一件容易的事情。与其它高级语言相比而言,调试程序比较困难。往往是编好程序输入计算机后,编译时容易通过,而在执行时还会出错。但只要对C语言的语法规则真正领会,编写程序及调试程序还是比较容易掌握的。

16 随着C语言应用的推广,C语言存在的一些缺陷或不足也开始流露出来,并受到大家的关注。如:C语言对数据类型检查的机制比较弱;缺少支持代码重用的结构;随着软件工程规模的扩大,难以适应开发特大型的程度等等。

17 为了克服C语言本身存在的缺点,并保持C语言简洁、高效,与汇编语言接近的特点,1980年,贝尔实验室的Bjarne Stroustrup博士及其同事对C语言进行了改进和扩充,并把Simula 67中类的概念引入到C中。并在1983年由Rick Maseitti提议正式命名为C++(C Plus Plus)。后来,又把运算符的重载、引用、虚函数等功能加入到C++中,使C++的功能日趋完善。 当前用得较为广泛的C++有:VC++ (Visual C Plus Plus)、 BC++(Borland C Plus Plus)、AT&T C++等。

18 简单的C++程序介绍 高级语言编译过程 库文件 (各种函数) 可执行文件 (二进制文件) *.EXE 源程序 (文本文件) *.CPP 目标文件 (二进制文件) *.OBJ 编译 连接 compile link F7 在Vitual C++系统中,可直接从源程序编译连接至可执行程序,但依然要生成*.OBJ及*.EXE这两个文件。

19 #include<iostream.h>
void main(void ) { cout<<“I am a student.\n”; //输出字符串 } 包含文件 函数体开始 主函数 分号,一条完整语句的结束符 输出流,在屏幕上打印引号内的字符串 函数体结束 注释或说明 本程序编译执行后,在DOS屏幕上打印出 I am a student.

20 编译过程: 1)启动Visual C++,选择“文件”菜单中的“新建”命令,选择“文件”标签中的“C++ Source File”选项。 2)选择源程序存放的目录和输入源程序名,单击“确定”。 3)在编辑器中编写源程序。 4)单击F7或“编译”中的“重建全部”编译源程序,若编译通过,单击“执行”,在DOS屏上看结果,任按一键返回编辑器。

21 启动VC++编译系统

22 单击“File”菜单中“New”命令 VC++编译系统界面

23 选择“Files”选项卡 输入文件名 选择C++源文件命令 输入文件存放位置 单击选择驱动器 选择驱动器或目录

24 输入C++源代码 C++源文件编辑界面

25 可以将此源代码另起文件名存盘

26 选择编译命令,将源文件.cpp生成.obj文件

27 如果编译出错,会出现提示信息,指出错误的位置及种类
错误所在行 错误的原因 如果编译出错,会出现提示信息,指出错误的位置及种类

28 光标移到该行 双击错误所在行

29 生成可执行文件 通过后单击该命令运行程序

30 注意:不可以在软盘上运行程序!应该把保存在软盘中的源文件拷贝到硬盘的目录中再运行!
运行结果显示在DOS屏上

31 未编译前,只有一个源程序 源程序所在目录

32 编译运行后,出现众多附加文件 同时,产生一个子目录Debug

33 Debug目录中,有obj和EXE文件

34 另一个例子 #include <iostream.h> void main(void) { cout << “i=”; //显示提示符 int i; //说明变量i cin >>i; //从键盘上输入变量i的值 cout << “i的值为:” <<i<<’\n’; // 输出变量i的值 }

35 第二章 数据类型、运算符与表达式

36 用一个字节表示整数,范围为-128~127;用两个字节表示整数,范围为-32768~ 32767。一般用四个字节表示整数。(举例)
data Program CPU 内存 外存 硬盘 软盘 运算器 2000H 2001H 2002H 2003H 2004H 3 3+5=? (2000H)+(2002H) 5 8 内存 用一个字节表示整数,范围为-128~127;用两个字节表示整数,范围为-32768~ 32767。一般用四个字节表示整数。(举例)

37 有符号数 无符号数 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 1 32767 32767 1 32766 32766 …… …… 1 1 1 1 -1(补码) 65535 1 -2 65534 …… …… 1 -32767 32769 1 -32768 32768

38 常量与变量 常量:在程序运行过程中,其值一直保持不变的量为常量。 常量也区分不同的类型:30,40 为整型,30.0,40.0为实型,编辑器只是根据其表面形式来判断其类型。 变量:在程序运行过程中,其值可以改变的量为变量。 变量在程序的执行中能够赋值,发生变化。变量有一个名字,并在使用之前要说明其类型,一经说明,就在内存中占据与其类型相应的存储单元。

39 #include<iostream.h>
#define PRICE //常量,在程序中保持不变 void main(void) { int num, total; //定义变量,在内存中开辟区间 num=10; //变量赋值,10为常量 total=num*PRICE; cout<<“total=“<<total; //输出结果 } num total 10 300 PRICE 30 其中:num=10 total=num*PRICE 是赋值号,不同于数学意义上的等号。

40 C++中有多种数据类型,均有常量与变量之分,各占不同的内存空间,正确定义与使用数据是编写程序的基本前提。

41 变量名的命名方法: 变量名、数组名、函数名…称为标识符。 标识符只能由字母、数字、下划线这三种字符组成,且第一个字符必须为字母或下划线,长度不大于247个字符,大小写不通用。(关键字不能作为标识符)。 关键字即是VC++的语法要求中使用的字。 如 int if while 等。 正确的标识符:INT, sum , de12, SUM等。变量必须使用前定义,以分配空间。 举例说明

42 abc English 2xy x-y if Else b(3) def Chine_bb b3y AbsFloat float
一般变量都是用匈牙利命名法命名的。 int nCount; char chChoice;

43 整型数据 整型常量: 常量是根据其表面形式来判定,整型量即是没有小数点的整数,范围:-231~(231-1) ,有三种形式: 1)十进制(默认方式) 2)八进制 以0开头 , 056, 011 3)十六进制 以0x开头 x xa x xdf(举例说明)

44

45 #include<iostream.h>
void main(void) { int int10,int8,int16; //定义3个整型变量 int10=10; //默认为十进制 int8=010; //八进制 int16=0x10; //十六进制 cout<<"int10="<<int10<<endl; cout<<"int8="<<int8<<endl; cout<<"int16="<<int16<<endl; } 输出 int10=10 int8=8 int16=16

46 整型变量: 分为有符号型与无符号型。 有符号型: short 在内存中占两个字节,范围为-215~(215-1) int 在内存中占四个字节,范围为-231~(231-1) long在内存中占四个字节,范围为-2-31~231-1 无符号型:最高位不表示符号位 unsigned short 在内存中占两个字节,范围为0~216-1 unsigned int 在内存中占四个字节,范围为0~232-1 unsigned long在内存中占四个字节,范围为0~232-1

47 1)整型常量亦有长短之分,常量中无unsigned型,但一个非负的整型常量可以赋给unsigned型的变量。
2)若一个常量定义为长整型数,则在其后加l或L进行区分。 如:32l 32L L等,内存为其分配四个字节存储。 一个数在内存中为 1 1 当这个数为有符号数时,是-1;为无符号数时,是232-1 内存中的数是以补码的形式存放的。(举例说明)

48 不同类型的整型数据间的赋值归根到底就是一条:按存储单元中的存储形式直接传送。
#include <iostream.h> void main() { unsigned short a; short int b= -1; a=b; cout<<"a="<<a<<endl; } 不同类型的整型数据间的赋值归根到底就是一条:按存储单元中的存储形式直接传送。 unsigned short a; a 1 结果:65535 b 1

49 实型数据 实型数又称浮点数,有两种表示方式: 1)十进制形式: 23.0 24.5 3.56789
1)十进制形式: 指数形式: 23E e e1 e前有数字,后面必须是整数。 实型变量分单精度 float 和双精度 double 两种形式: float:占四个字节,提供7位有效数字。 double: 占八个字节,提供16位有效数字。 举例说明

50 #include<iostream.h>
void main(void) { float a, b; double c, d; a=0.01; b= e-2; c= e-2; d=9.7654e-5; cout<<"a="<<a<<'\t'<<"b="<<b<<endl; cout<<"c="<<c<<'\t'<<"d="<<d<<endl; } a=0.01 b= c= d=9.7654e-005 Press any key to continue

51 实数是既有整数又有小数的数。 实数可以表示成:N=S×RJ S 称为尾数,尾数决定有效数字,即数字的精度。 J 表示指数(阶码)。 R 是基数,可取2,4,8,16等,对具体机器而言,基数取好后,就不能再变了。 数有正有负, 所以设置数符; 阶码亦有正负, 所以设置阶符 如果为实数,则用浮点数的形式在内存存储,表示如下: Jt J Sf S 阶符 阶码 数符 尾数

52 一般用4个字节表示一个浮点数,也有用8个字节表示的。
字长一定,尾数越多,精度越高;阶码越多,范围越大。 当计算机中出现小于机器所能表示的最小数时,机器只能当零来处理,当出现超过机器所能表示的最大数时,出现溢出现象,一旦出现溢出,就会停止运算。定点数,浮点数均会出现溢出现象。

53 字符型数据(char) 1 字符型数据实际上是作为整型数据在内存中存储的。
计算机是以字符编码的形式处理字符的,因此,我们在计算机内部是以ASCII码的形式表示所有字符的。所以7位二进制数即可表示出一个字符,我们用一个字节的容量(8位)存储一个字符。 例如:字符A的ASCII码为0x41或65,在内存中表示为: 1 在程序中表示为: char grade ;//定义一个字符型的变量空间(1个字节) grade=‘A’; //必须用‘ ’表示,否则易与标识符混同 ‘ ’内括起来的字符表示该字符的ASCII码。

54 1 进一步,由于在内存中的形式与整型数据相同,所以,可以直接用其整型值给变量赋值。 char grade; grade=65;
以下的赋值形式均是等同的。 grade='A'; grade=65 ; grade=0x41; grade=0101; #include<iostream.h> void main(void) { char a,b; a=‘A’; //输入ASCII码 b=65; //输入十进制数 cout<<"a="<<a<<endl; cout<<"b="<<b<<endl; } 输出: a=A b=A 即在内存中的表示均是相同的 1

55 非打印字符 有些ASCII的字符代表某些操作,不能打印出来,如回车、退格等,可用两种方式表示这些字符。 1)用ASCII码的形式 char re=13; 2)用转义字符 char re=‘\n’;(p15)

56 转义字符 含 义 ASCII代码 \a 响铃 7 \n 换行,将当前位置移到下一行开头 10 \t 水平制表(跳到下一个tab位置) 9 \b 退格,将当前位置移到前一列 8 \r 回车,将当前位置移到本行开头 13 \f 换页,将当前位置移到下页开头 12 \ v 竖向跳格 \\ 反斜杠字符“\” 92 \′ 单引号(撇号)字符 39 \" 双引号字符 34 \0 空字符 \ddd 1到3位8进制数所代表的字符 \xhh 1到2位16进制数所代表的字符

57 转义字符虽然包含2个或多个字符,但它只代表一个字符。编译系统在见到字符“\”时,会接着找它后面的字符,把它处理成一个字符,在内存中只占一个字节。

58 典型转义字符 : ‘\n’换行 ‘\b’ 退格 '\t' 下一个输出区 若输出中包含这些特定格式,则再加一个\ 输出 c:\tc\tc 表示为cout<<"c:\\tc\\tc"; 可以用转义字符表示任一一个ASCII字符 ‘\ddd’ (八进制) ‘\xhh‘ (十六进制) '\101' '\x41' '\x61' '\141'

59 #include<iostream.h>
void main(void) { char c1,c2,c3,c4; char n1,n2; c1='a'; //字符常量 c2=97; //十进制 c3='\x61'; //转义字符 c4=0141; //八进制 cout<<"c1="<<c1<<'\t'<<"c2="<<c2<<endl; cout<<"c3="<<c3<<'\t'<<"c4="<<c4<<endl; n1=‘\n’; //转义字符:回车 n2=‘\t’; //转义字符:下一个输出区(Tab) cout<<"使用转义字符\n"; cout<<"c1="<<c1<<n2<<"c2="<<c2<<n1; cout<<"c3="<<c3<<n2<<"c4="<<c4<<n1; } 输出: c1=a c2=a c3=a c4=a 使用转义字符

60 字符串常量: 用" "表示,在内存中顺序存放,以'\0'结束。 如:"CHINA" C H I N A \0
用" "表示,在内存中顺序存放,以'\0'结束。 如:"CHINA" C H I N A \0 实际上内存是对应字符的ASCII码形式 0x43 0x48 0x49 0x55 0x41 \0 'a'在内存中占一个字节 "a"占两个字节 a a \0

61 标识符常量 在C++中有二种方法定义标识符常量,一种是使用编译预处理指令;另一种是使用C++的常量说明符const。 例如: #define PRICE 30 //在程序中凡是出现PRICE均用30替代 #define PI #define S “China” const float pi= ; //将变量pi定义为常量 (举例说明)

62 #include<iostream.h>
#define PI #define S "China" void main(void) { const float pi= ; //变量作为常量使用 cout<<"PI="<<PI<<endl; cout<<"10*PI="<<10*PI<<endl; cout<<S<<endl; // PI=PI+3; // pi=pi+4; cout<<"pi="<<pi<<endl; } 输出: PI= 10*PI= China pi=

63 下列常量的表示在C++中是否合法?若不合法,指出原因;若合法,则指出常量的数据类型。
u e3.4 3L e-32 ‘\87’ “Computer System” “a” ‘a’ ‘\96\45’

64 变量 1) 在程序的执行过程中,其值可以改变的量称为变量。 2) 变量名必须用标识符来标识。 3) 变量根据其取值的不同值域,分为不同类型的变量:整型变量、实型变量、字符型变量、指针型变量等等。

65 4) 对于任一变量,编译程序要为其分配若干个字节(连续的)的内存单元,以便保存变量的取值。
5) 当要改变一个变量的值时,就是把变量的新的取值存放到为该变量所分配的内存单元中;用到一个变量的值时,就是从该内存单元中取出数据。 6) 不管什么类型的变量,通常均是变量的说明在前,使用变量在后。

66 开辟空间后, 空间中为随机值 int i, j, k; //定义了三个整型变量i,j,k
四个字节的连续空间 j i 开辟空间后, 空间中为随机值 float x,y,z; //定义了三个实型变量x,y,z z 四个字节的连续空间 y x char c1,c2; //说明了二个字符型变量c1,c2 double dv1;//说明了一个双精度型变量dv1 dv1 八个字节的连续空间 c2 1个字节的空间 c1

67 在定义变量的同时给变量赋值,即在内存中开辟出一个空间后马上给此空间赋值。 但这个空间的值并不是固定不变的,在程序的运行中一样可以改变。
变量赋初值 在定义变量的同时给变量赋值,即在内存中开辟出一个空间后马上给此空间赋值。 但这个空间的值并不是固定不变的,在程序的运行中一样可以改变。 int a=4; //定义语句,在开辟空间后马上为空间赋值 a=6; //重新为该空间赋值 a 4 6 char a='\x64', b='d'; int a1=6, a2=98; a=‘A’; b=‘\n’; a1=011; a2=121;

68 算术运算符和算术表达式 一、算术运算符和算术表达式 + - * / % 用算术运算符连接起来的式子是算术表达式
+ - * / % 用算术运算符连接起来的式子是算术表达式 两个整数相除结果为整数 /2= /2=2 整数才可求余,余数的符号与左边数的符号相同。 3%2= %2= %-2= %-2= %4=0 二、优先级与结合性 () * / % —

69 三、强制转换类型 (类型名)(表达式) (double) a (int) (x+y) (int) 6.2%4=2 在强制类型运算后原变量不变,但得到一个所需类型的中间变量。 如:int x; float y=5.8; x=(int)y; x=5 y的值没有改变,仍是单精度浮点型 y=5.8

70 i=4 j=4 ++在前, 先运算,后赋值 i=4 j=3 ++在后, 先赋值,后运算 四、自增、自减运算符 (难点) ++ --
四、自增、自减运算符 (难点) -- i=6; i++; i=i i= i; i=i+1 i=7 i i 7 6 7 6 i=6; i--; i=i-1 i= --i ; i=i-1 i=5 int i, j; i=3; j = ++i; int i, j; i=3; j = i++; i j 3 4 3 i j 4 3 4 i=4 j=4 ++在前, 先运算,后赋值 i=4 j=3 ++在后, 先赋值,后运算

71 1)自增、自减运算符只能用于变量,不可用于常量和表达式
因为表达式在内存内没有具体空间,常量所占的空间不能重新赋值 (x+y) (-i)++ 2)结合方式自右至左,优先级最高,向右取最大 -i -(i++) i+++j (i++) +j 若i=3, j=2 (i++) +j 等于 5 i=4, j=2

72 赋值运算符和赋值表达式 bmw=2002 "="左边必须是变量名。 若“ = ” 两边变量类型不同,在赋值时要进行类型转换。
转换原则:根据左边变量的类型转换。

73 1)若多字节变量为unsigned ,则转换后多余字节补零。
少字节多字节 1)若多字节变量为unsigned ,则转换后多余字节补零。 short int a=-1; unsigned long b; b=a; a 1 unsigned b 1

74 2)若多字节变量为有符号型,则转换后扩展少字节的最高位。
short int a=-1; long b; b=a; a 1 有符号型,符号扩展 b 1 转换后,数据的符号不变。

75 多字节少字节 低位照搬 int a=-1; int a=65535; short int b; short int b; b=a;

76 复合的赋值运算符 a+= a=a+3 x*=y x=x*(y+3) x/=x x=x/(x-4) x+=y x=x+y i+=j i=i+(j--) 赋值表达式 a=b=5 ; b= a=5 "="的结合性为自右至左

77 a=12; a+=a-=a*a; a=a-(a * a) =12-(12*12)=-132 a=a+(-132)=-132-132=-264

78 关系运算符和关系表达式 关系运算符(比较运算) < > <= >= = = != = = 与 = a=5; 赋值运算 a= =5;判断是否相等 < > <= >= 的优先级大于= = != 3. 算术运算符的优先级大于关系运算符的优先级

79 关系表达式:用关系运算符将表达式连接起来称为关系表达式。其值非真即假。在C++语言中,用非0代表真,用0表示假。关系表达式的结果只有两个,真为1,假为0。
a= ='a' a>'a' b=a= =2 a=2 b=3 c=4 a>2 a>b+c a= =2 1 'a'>'A' b= ='a'+1 c-a= =a 1 1 1

80 && | | ! 逻辑运算符 运算符 与&& 或 || 非! A B 结果 0 0 0 0 1 0 1 0 0 1 1 1
逻辑运算符   运算符 与&& 或 || 非! && | | A B 结果 0 0 0 0 1 0 1 0 0 1 1 1 有0出0,全1出1 A,B同时成立 A B 结果 0 0 0 0 1 1 1 0 1 1 1 1 有1出1,全0出0 A或B有一个成立 A 结果 0 1 有0出1, 有1出0

81 例如:两个条件:江苏籍 男生 江苏籍的男生 江苏籍的学生和所有男生 非江苏籍的学生 江苏籍&&男生 江苏籍||男生 !江苏籍 注意: 1.优先级:!&&| | !算术关系逻辑赋值逗号

82 2.作为条件,所有非0值均为真;作为结果,只有0或1两种。
5>3 && 2 || 8<4-!0 3.不可写为 1<x< 应为:1<x && x<10 4.当前面的表达式可以得出整个表达式的结果时,不必再求后面的表达式。 a&&b&&c 当a为0时,表达式为0,不必求b与c。 a||b||c 当a为1时,表达式为1,不必求b与c。

83 x=4 y=5 i= ++x= =5 || ++y= =6 x=5 y=5 i=1 i= x++= =5&& y++= =6 x=5 y=5 i=0 判断某年是否为闰年 1)能被400整除 2)能被4整除,不能被100整除 (2200年不是) year%400= =0 year%4= =0&& year%100!=0 (year%400= =0) || (year%4= =0&&year%100!=0)

84 当c=4时,以下的值各多少? (c=1)&&(c=3)&&(c=5) (c= =1)||(c= =2) || (c= =5) (c!=2) && (c!=4) &&(c>=1)&&(c<=5) 1

85 sizeof()运算符 sizeof()运算符是一个单目运算符,用于计算某一个操作数类型的字节数。其格式为:
sizeof(int) //其值为4 sizeof(float) //其值为4 sizeof(double) //其值为8 sizeof(char) //其值为1

86 逗号运算符和逗号表达式 表达式1,表达式2,表达式3,…,表达式n 顺序求解,结果为最后一个表达式的值,并且优先级最低。
a=(3+4, 5*6, 2+1); a=3 a=3*3, a+6, a+7; 16 a=9 (a=3*5, a*4), a+5 20 a=15

87 下列语句中表达式中i, j的值各为多少 1、int i=0, j=0; 、 int i=0, j=1; i=3, (j++)+i ; i+=j*=3; 3、int i=1, j=0; 、int i=1, j=1; j=i=((i=3)*2); i+=j+=2; i=3,j=1 i=3,j=3 i=6,j=6 i=4,j=3

88 在进行运算时,不同类型的数据要先转换成同一类型的数据再进行运算。 转换规则如下:
各类数值型数据间的混合运算 整型、实型、字符型数据间可以混合运算。 在进行运算时,不同类型的数据要先转换成同一类型的数据再进行运算。 转换规则如下: float double long unsigned int char 10+'a' *'b'

89 第三章 简单的输入输出

90 输入语句:cin 程序在执行期间,接收外部信息的操作称为程序的输入;而把程序向外部发送信息的操作称为程序的输出。在C++中没有专门的输入输出语句,所有输入输出是通过输入输出流来实现的。

91 要使用C++提供的输入输出时,必须在程序的开头增加一行:
#include <iostream.h> 即包含输入输出流的头文件“iostream.h”。有关包含文件的作用,在编译预处理部分(第五章)作详细介绍。

92 输入语句自动过滤空白字符。 输入十进制整数和实数
cin >> <变量名1>《 >> <变量名2> 》(举例说明) int a,b; cin>>a>>b; //程序运行至此停下,等待从键盘输入变量值 a 键盘 3 键盘输入:3 5<CR> 或:3<CR> 5<CR> 均可。 b 键盘 5 输入语句自动过滤空白字符。

93 浮点型数据同整型数据一样。 float c,d; cin>>c>>d; char ch1,ch2; cin>>ch1>>ch2; 若输入:ab<CR> 则ch1为a, ch2为b。 若输入:a b<CR> 则ch1为a, ch2为b。 字符型变量过滤空白字符。cin格式过滤空白字符

94 float a; int i1,i2; char ch1,ch2; cin>>i1>>a>>i2>>ch1>>ch2; 输入: a b<CR> i2:1 i1:34 a:5.578 ch1:a ch2:b 在缺省的情况下,cin自动跳过输入的空格,换言之,cin不能将输入的空格赋给字符型变量,同样地,回车键也是作为输入字符之间的分隔符,也不能将输入的回车键字符赋给字符型变量。

95 若要把从键盘上输入的每一个字符,包括空格和回车键都作为一个输入字符赋给字符型变量时,必须使用函数cin.get()。其格式为:
char c1; cin.get(c1);

96 char ch1,ch2,ch3; cin.get(ch1); 则:ch1:A cin.get(ch2); cin.get(ch3);
ch3:B 输入:A B<CR> 并且在输入缓冲区中保留回车键。 ch2 空格的ASCII码为32 1

97 输入十六进制或八进制数据 在缺省的情况下,系统约定输入的整型数是十进制数据。当要求按八进制或十六进制输入数据时,在cin中必须指明相应的数据类型:hex为十六进制;oct为八进制;dec为十进制。

98 int i,j,k,l; cin>>hex>>i; //指明输入为十六进制数 cin>>oct>>j; //指明输入为八进制数 cin>>k; //输入仍为八进制数 cin>>dec>>l; //指明输入为十进制数 当执行到语句cin时,若输入的数据为: <CR> 结果:i:17 j:9 k:10 l:12

99 使用非十进制数输入时,要注意以下几点: 1、八进制或十六进制数的输入,只能适用于整型变量,不适用于字符型变量,实型变量。 2、当在cin中指明使用的数制输入后,则所指明的数制一直有效,直到在接着的cin中指明输入时所使用的另一数制为止。如上例中,输入k的值时,仍为八进制。

100 cin>>a>>b; cin>>a b;
int a, b; cin>>a,b; cin>>a>>b; cin>>a b; cin>>ab;

101 与输入cin对应的输出是cout输出流。
其中运算符“<<”称为插入运算符,它将紧跟其后的表达式的值,输出到显示器当前光标的位置。

102 cout<<a<<‘\t’<<f1<<‘\t’<<s1<<endl;
int a=6; float f1=12.4; char s1[ ]=“abcd”; cout<<a<<‘\t’<<f1<<‘\t’<<s1<<endl; a 6 f1 12.4 s1 \0 d c b 显示器 显示器 6 12.4 abcd 显示器 ‘\t’为转义字符Tab endl为回车或‘\n’

103 cout将双引号中的字符串常量按其原样输出
char ch1=‘a’,ch2=‘b’; cout<<“c1=“<<ch1<<‘\t’<<“c2=“<<ch2<<endl; c1=a c2=b<CR> int i1=4,i2=5; float a=3.5; cout<<“a*i1=“<<a*i1<<endl<<“a*i2=“<<a*i2<<endl; a*i1=14 a*i2=17.5

104 指定输出项占用的宽度: 在输出的数据项之间进行隔开的另一种办法是指定输出项的宽度。如上面的两个输出语句可改写为: cout <<setw(6)<< i<<setw(10)<<j<<endl; _ _ _ _ _ 4_ _ _ _ _ _ _ _ _12 cout << setw(5)<<m<<setw(10)<<j*k<<endl; _ _ _ _ 7_ _ _ _ _ _ _ _ 24 其中setw(6)指明其后的输出项占用的字符宽度为6,即括号中的值指出紧跟其后的输出项占用的字符位置个数,并向右对齐。setw是“set width”的缩写。

105 使用setw()应注意以下三点: 1、在程序的开始位置必须包含头文件iomanip.h,即在程序的开头增加: #include <iomanip.h> 2、括号中必须给出一个表达式(值为正整数),它指明紧跟其后输出项的宽度。 3、该设置仅对其后的一个输出项有效。一旦按指定的宽度输出其后的输出项后,又回到原来的缺省输出方式。

106 输出八、十六进制数和科学表示法的实数 对于整型数据可指定以十六进制或八进制输出,而对于实型数据可指定以科学表示法形式输出。例如,设有如下一个程序: #include <iostream.h> void main(void) { float x=3.14,y=100; cout.setf(ios::scientific,ios::floatfield); //表明浮点数用科学表示法输出 cout << x<<’\t’; cout <<y<<endl; } 执行该程序后的输出为: e e+002

107 与cin中类同,当在cout中指明以一种进制输出整数时,对其后的输出均有效,直到指明又以另一种进制输出整型数据为止。对实数的输出,也是这样,一旦指明按科学表示法输出实数,则接着的输出均按科学表示法输出,直到指明以定点数输出为止。明确指定按定点数格式输出(缺省的输出方式)的语句为: cout.setf(ios::fixed,ios::floatfield);

108 第四章 C++的流程控制语句

109 程序的三种基本结构 1、顺序 A B 2、选择 条件? A B x>y? z=x z=y

110 3、循环 P A Y N A 当P为真 当型 i++ i<10

111 P A Y N 直到P为真 A 直到型 i>=10 i++

112 if (a>b) cout<<a; else cout<<b; if语句 判断选择语句,有三种形式:
条件 if (a>b) cout<<a; 2) if(表达式) 语句1 else 语句2 语句2 语句1 条件 if (a>b) cout<<a; else cout<<b;

113 if(表达式1) 语句1 else if (表达式2) 语句2 ...... else if (表达式n) 语句n else 语句n+1
表达式2 语句2 表达式3 语句3 表达式4 语句4 语句5

114 表达式1 表达式2 表达式3 表达式4 语句1 语句2 语句3 语句4 语句5

115 注意:1) if 后可跟复合语句。 2) 注意 ;的位置。 3) 注意多重 if else 的搭配。 a=0 b=1 a=1 b=0
2) 注意 ;的位置。 3) 注意多重 if else 的搭配。 if (a>b) { a=1; b=0; } else { a=0; b=1; a=0 b=1 a=1 b=0 a>b

116 if 总是与它上面最近的 else 配对,如要改变,用复合语句{ }。 注意书写格式,相互配对的语句要对齐。
i>j if (i >j) i++; if (i>j); i++; i>j i+ + if 总是与它上面最近的 else 配对,如要改变,用复合语句{ }。 注意书写格式,相互配对的语句要对齐。

117 例:输入两个实数,按代数值由小到大次序输出这两个数。 void main( void ) { float a,b,t; //定义变量
cout<<“ Input 2 Real Number:\n";//在屏幕上的提示信息 cin>>a>>b; //给变量赋值 a:7, b:3 if(a>b) { t=a; a=b; b=t; }//交换数据,用中间变量 cout<<a<<‘\t’<<b<<endl;//输出变量 } 输出结果: b a t 7 3 7 3 7

118 嵌套的条件语句(举例说明) x=100; a=10; b=20; ok1=5; ok2=0; if(a<b) if(b!=15) if(!ok1) x=1; else if (ok2) x=10; x=-1; x=-1

119 x=5 条件运算符 是C++中的唯一的三目运算符。 表达式1?表达式2 :表达式3 表达式3 表达式2 表达式1
max=a>b?a:b ; // 求a, b中的大者 当 a=2 b=1 a>b为真,表达式的值等于a, max值为2 当 a=1 b=2 a>b为假,表达式的值等于b, max值为2 注意: 条件运算符的优先级比赋值运算符高 x=(x=3) ? x+2 : x-3 2. 结合方向自左至右 a>b?a:c>d?c:d 3. 三个表达式的类型可不同 z=a>b?'A':a+b x=5

120 x=((x+y)%z>=x%z+y%z)?1:0; cout<<"x= "<<x<<endl;
cout<<( z+=x>y?x++:y++)<<endl; y=y+z=5 x=x+5=6 9

121 void main(void ) { int x=1,y=2,z=3; x+=y+=z; cout<<x<y?y:x<<endl; cout<<x<y?x++:y++<<endl; cout<<x<<“,”<<y<<endl; cout<<z+=x>y?x++:y++<<endl; cout<<y<<“,”<<z<<endl; x=3; y=z=4; cout<<(z>=y&&y= =x)?1:0<<endl; cout<<z>=y&&y>=x<<endl; } x y z 输出 6 5 3 ,6 ,9 3 4 4

122 执行以下程序段后,变量a,b,c的值分别是:
int x=10, y=9; int a,b,c; a=(--x= =y++)?--x:++y; b=x++; c=y; x=8 y= a=8 b=8 x=9 c=10

123 * * * void main(void ) { int a=5,b=1,c=0;
if(a=b+c) cout<<“* * *\n”; else cout<<“$ $ $\n”; } * * *

124 switch语句 多分支选择语句。if语句只有两个分支,而实际问题中常常需要用到多分支的选择。如,成绩分为A(100~85)、B(84~70)、C(69~60)、D(60以下)等。 ‘A’ 100~85 Y ‘B’ 84~70 ‘C’ 69~60 ‘D’ no pass N 显示出错

125 cin.get(grade); if(grade= =‘A’) cout<<“100~85\n”; else if (grade= =‘B’) cout<<“84~70\n”; else if (grade= =‘C’) cout<<“69~60\n”; else if (grade= =‘D’) cout<<“no pass\n”; else cout<<“error\n”;

126 switch(表达式) { case 常量表达式1:语句1 case 常量表达式2:语句2 … … case 常量表达式n:语句n
default:语句n+1 如果grade为 ‘A’,则结果为 switch(grade) { case ‘A’:cout<<“100~85\n”; case ‘B’:cout<<“84~70\n”; case ‘C’:cout<<“69~60\n”; case ‘D’:cout<<“no pass\n”; default:cout<<“error\n”; 100~85 84~70 69~60 no pass error

127 其流程为:先计算表达式的值,然后顺序地与case子句中所列出的各个常量进行比较,若表达式的值与常量中的值相等,就开始进入相应的case语句执行程序,遇到case和default也不再进行判断,直至switch语句结束。如果要使其在执行完相应的语句后中止执行下一语句,可以在语句后加break。

128 switch(grade) { case ‘A’:cout<<“100~85\n”; break; case ‘B’:cout<<“84~70\n”; break; case ‘C’:cout<<“69~60\n”; break; case ‘D’:cout<<“no pass\n”; break; default:cout<<“error\n”;

129 注意: 1、switch与if不同,它仅能判断一种逻辑关系,即表达式是否等于指定的常量,而 if 可以计算并判断各种表达式。 2、case子句后必须为常量,常常是整型和字符型。 3、default可以省略,这时,不满足条件什么也不执行。

130 4、case和default只起标号的作用,顺序可以颠倒,颠倒时注意后面的break语句。
case ‘A’: case ‘B’: case ‘C’: cout<<“pass!\n”;

131 void main(void ) { int i=10; switch(i) { case 9: i++; case 10: i++; case 11: i++; default: i++; } cout<<“i=”<<i<<endl; } i=11 i=12 i=13 i=13

132 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++; cout<<“a=“<<a<<‘\t’<<“b=”<<b<<endl; a=1 a= b=1 a=2 b=1

133 有3个整数a,b,c,由键盘输入,输出其中最大的数。

134 cout<<“a=“<<a; 当循环语句超过一条时,要用{ }将语句组组合在一起。
while语句 表达式 语句组1 语句组2 while ( 表达式) { 语句组1 } {语句组2} a=3; while(a<100) a=a+5; cout<<“a=“<<a; 当循环语句超过一条时,要用{ }将语句组组合在一起。

135 1 实际上是将i不停地累加到一起 sum 求 1+2+3+……+100 5050 1 3 6 void main(void)
sum 求 ……+100 5050 1 3 6 void main(void) { int i=1,sum=0; //定义变量,初始化 while(i<=100) //构造循环 { sum=sum+i; // 循环体,多次执行 i=i+1; } cout<<“sum=”<<sum<<endl; //输出结果 1 i 101 100 3 2 4 循环结束!! sum=5050 实际上是将i不停地累加到一起 循环条件 初值 循环次数 1 2 3 4 ..... 99 100 101 sum i 1 3 6 10 5050 1 2 3 4 5 100 101

136 注意: 1、循环体如果为一个以上的语句,用{ }括起。 2、循环体内或表达式中必须有使循环结束的条件,即一定有一个循环变量。 3、while表达式可以成为语句,要特别小心。

137 while(k!=0) cout<<k, k--; cout<<endl;
循环条件 输出 2 1 输出:21 2 1 回车

138 cout<<num<<endl; } 1 2 3
void main(void) { int num=0; while(num<=2) { num++; cout<<num<<endl; } 1 2 3 num 循环条件 输出 1 2 3 1<CR> 2<CR> 3<CR>

139 cout<<“y=”<<y<<endl; } 输出是什么? 循环几次?
void main(void) { int y=10; while (y--); cout<<“y=”<<y<<endl; } 输出是什么? 循环几次? y 条件 输出 ...... 10 9 1 -1 输出:y=-1 循环:10次

140 k=10; while( k=0 ) k=k-1; cout<< k; k 10 表达式 输出:0

141 以下语句,循环退出时x为多少? x=10; while (x!=0) x--; x=10; while (x) x--; x=10; while(x--); x=10; while(--x); x=0 x=0 x=-1 x=0

142 输出: 6 6 8 9 7 7 #include<iostream.h> void main()
{ char ch; while(cin.get(ch)&&ch!='\n') switch (ch-'2') { case 0: case 1: cout<<(char)(ch+4); case 2: cout<<(char)(ch+4); break; case 3: cout<<(char)(ch+3) ; default : cout<<(char)(ch+2); break; } cout<<endl; 从键盘输入2473<CR>,则程序的输出结果是: 输出: 6 6 8 9 7 7

143 do—while语句 do { 语句组1} while(表达式); {语句组2} 表达式 语句组1 语句组2 直到P为真 A 直到型

144 求 1+2+3+……+100 void main(void) { int i=1,sum=0; //定义变量,初始化 do //构造循环
{ sum=sum+i; // 循环体,多次执行 i=i+1; }while (i<=100); cout<<“sum=”<<sum<<endl; //输出结果 }

145 注意: do—while首先执行循环体,然后再判断表达式,至少执行一次循环体。当第一次循环表达式的值为真时,while与do—while的结果完全一样,否则结果不相同。

146 若为while循环,则一次也不执行循环体,输出为:
y=0, x=0 x=0,y=0; do { y++; x*=x; } while ((x>0)&&(y>5)); cout<<“y=“<<y<<“,”<<“x=”<<x<<endl; y x 条件 1 输出:y=1,x=0

147 cout<<“s=”<<s<<endl;
do s-=2; while(s= =0); cout<<“s=”<<s<<endl; 第一次 s 7 5 表达式 N 输出:s=5

148 for语句 for(表达式1;表达式2;表达式3) {语句组1(循环体)} {语句组2}
N 表达式2 语句组1 Y 语句组2 表达式1 表达式3 for(表达式1;表达式2;表达式3) {语句组1(循环体)} {语句组2} for(循环变量赋初值;循环结束条件;循环变量增值)

149 求 1+2+3+……+100 void main(void) { int i, sum; void main(void)
while(i<=100) { sum=sum+i; i=i+1; } cout<<“sum=”<<sum<<endl; void main(void) { int i, sum; for (i=1, sum=0; i<=100; i++) sum=sum+i; cout<<“sum=”<<sum<<endl; }

150 注意: 1、当型循环,条件测试是在循环开始时进行,有可能一次也进入不了循环体。 2、for语句中的三个表达式可以部分省略或全部省略, 但;不能省略,若省略表达式2,则表示循环条件为真。 3、for语句中三个表达式可以是任何有效的C语言表达式。

151 输出:azbycx.......lomn void main(void) { char i, j ;
for (i=‘a’,j=‘z’ ; i<j ; i++, j--) cout<<i<<j; cout<<endl; } 输出:azbycx lomn 次数 i j i<j 输出 a b c ...... m n z y x ..... n m ..... az by cx mn CR

152 以下循环结果如何? for ( i=0, k= -1; k=1; i++, k++) cout<<“****\n”; 1 10 以下循环最多执行_____次,最少执行_____次 for (i=0, x=0; i<=9&&x!=876 ; i++) cin>>x;

153 一个循环体内又包含另一个完整的循环体,称为循环的嵌套。
注意: 1、循环体内有多个语句要用{}括起来。 2、书写格式要清晰。 for ( ; ; ) { for ( ; ; ) { }

154 输出: k=0, m=5 i i<2 j j<3 k 1 真 真 1 2 3 1 2 3 真 真 真 假 真 真 真 假 1 2
void main(void) { int i, j, k=0, m=0; for ( i=0; i<2; i++) { for ( j=0; j<3; j++) k++; k- =j; } m=i+j; cout<<“k=“<<k<<“, m=“<< m<<endl; 输出: k=0, m=5 i i<2 j j<3 k 1 1 2 3 1 2 3 1 2 3 1 2 3

155 几种循环的比较 do { 语句组1} while(表达式); while ( 表达式) {语句组2} { 语句组1 } {语句组2} 假
{ 语句组1 } {语句组2} 表达式 语句组1 语句组2 表达式 语句组1 语句组2

156 for(表达式1;表达式2;表达式3) {语句组1} {语句组2} 表达式2 语句组1 语句组2 表达式1 表达式3

157 最大公约数与最小公倍数 求两自然数m , n的最大公约数 欧几里德算法(m>n) 1、m被n除得到余数r(0≤r ≤n) r=m%n 2、若r=0,则算法结束,n为最大公约数,否则做3 3、mn , nr , 回到1 while ( r=m%n ) { m=n; n=r ; } m=6 n=4 r=m%n=6%4=2 m=4 n=2 r=m%n=4%2=0 所以,公约数=2 最小公倍数为两数之积除以最大公约数。4*6/2=12

158 最大公约数:能同时被m和n整除的最大数。
r=m>n?n:m for(i=1; i<r; i++) if(m%i==0&&n%i==0) a=i; cout<<a;

159 { cout<<n%10<<‘\t’; n=n/10; }
将 的每位分别打印出来。 12345%10= /10=1234 1234%10= /10=123 123%10= /10=12 12%10= /10=1 1%10= /10=0 while(n) { cout<<n%10<<‘\t’; n=n/10; }

160 t=x*x/((2*n)*(2*n-1)) 求级数公式: 首先写出通项,然后再用当前项(第n项)除前一项,得出后一项比前一项大多少倍。
通项: t=x*x/((2*n)*(2*n-1)) 表明前一项比后一项大t倍,即后一项乘t等于前一项 后一项=(-1)×前一项×t

161 term=(-1)*term*t; t=x*x/((2*n)*(2*n-1)) 后一项=(-1)×前一项×t
当前项 前一项 S=0;term=1;n=1;//一定要赋初值 while(fabs(term)>=1e-5) { S=S+term; term=(-1)*term*x*x/((2*n)*(2*n-1)); n++; } 新的 旧的

162 t=x*x/((2*n)*(2*n-1)) term=(-1)*term*t; 第n项/第n-1项: 第一项:term=1;
第一次循环:S=S+term; term=(-1)*term*t; 这时左边的term代表第二项,而右边的term为第一项。 第二次循环:S=S+term; term=(-1)*term*t; 这时左边的term代表第三项,而右边的term为第二项。 term=(-1)*term*t; 前一项 当前项 同样是term,在循环中不断用旧的数值去推导赋值出新的数值。

163 S=0;term=1;n=1;//一定要赋初值 while(fabs(term)>=1e-5) { S=S+term;
term=(-1)*term*x*x/((2*n)*(2*n-1)); n++; } 新的 旧的

164 break语句和continue语句 break在switch语句中,可以使流程跳过判断体,执行下面的程序。在循环体中,也可以从循环体内跳出循环体,提前结束循环。 for ( ; ; ) { cin>>x; if (x= =123) break; } 当输入123时,结束循环。 break 只能退出一层循环或switch语句。

165 a=10 ; y=0; do { a+=2; y+=a; cout<<“a=“<<a<<“, y=“<< y<<endl; if (y>50) break; } while (a=14); 第一次:a=12 y=12 输出:a=12 , y=12 第二次:a=16 y=28 输出:a=16 , y=28 第三次:a=16 y=44 输出:a=16 , y=44 第四次:a=16 y=60 输出:a=16 , y=60

166 输出:*#*#*#$ continue:其作用为结束本次循环,即跳过循环体中下面尚未执行的语句,接着进行下一次是否执行循环的判定。
void main(void) { int i; for (i=1 ; i<=5 ; i++ ) { if (i%2) cout<<“*”; else continue; cout<<“#”; } cout<<“ $\n”; 输出:*#*#*#$ i i<=5 i%2 输出 1 2 3 4 5 6 1 1 1 $ *# *# *#

167 i=0 i<2 第一次 i=1 i<2 第二次 i=2 i<2 结束 输出:x=8 void main(void)
{ int i, j, x=0 ; for (i=0 ; i<2; i++) { x++; for (j=0;j<=3; j++) { if ( j%2 ) continue; x++; } cout<<“x=“<< x<<endl; i=0 i<2 第一次 j j%2 x 1 2 3 4 2 2 3 3 4 i=1 i<2 第二次 j j%2 x 1 2 3 4 6 6 7 7 8 i=2 i<2 结束 输出:x=8

168 输出:k=4 c++ c k A B C D E F B C D E F G 2 4 7 1 11 4 真 真 真 真 真 假
void main(void ) { int k=0; char c=‘A’; do { switch (c++) { case ‘A’: k++; break; case ‘B’: k--; case ‘C’: k+=2; break; case ‘D’: k=k%2; continue; case ‘E’: k=k*10; break; default: k=k/3; } k++; }while (c<‘G’); cout<<“k=”<< k<<endl; c++ c k A B C D E F B C D E F G 2 4 7 1 11 4 输出:k=4

169 总结: 在循环体中,break从循环体内跳出循环体,提前结束循环。 for(... ; ... ; ... ) { break; }

170 continue:其作用为结束本次循环,即跳过循环体中下面尚未执行的语句,接着进行下一次是否执行循环的判定。
for(... ; ; ) { continue; } while( ) { continue; }

171 判断一个数 t 是否为素数,用2到t-1循环除。
求素数:只可以被1与自身整除的数。 判断一个数 t 是否为素数,用2到t-1循环除。 for( i=2; i<t ; i++) if(t%i==0) break; if (i==t) cout<<“是素数。\n”; else cout<<“不是素数\n”; t/2 (i>=t/2) 进一步,由于 t 不可能被大于 t/2 的数整除,所以可将循环次数降低。

172 求范围内的素数(50~100): for(t=50, k=0 ; t<=100; t++) { for( i=2; i<t ; i++) if(t%i==0) break; if (i= =t) { cout<<t<<“ “; k++; if(k%5==0) cout<<endl; } 判断t是否为素数 保证每行输出5个数据

173 鸡兔共有30只,脚共有90只,问鸡兔各有多少? void main(void) { int i; //i代表鸡,则兔为30-i只 for(i=0; i<=15; i++) if(2*i + 4*(30-i)= =90) { cout<<“鸡”<<i<<endl; cout<<“兔”<<30-i<<endl; }

174 一百万富翁 遇到一陌生人,陌生人找他谈一个换钱的计划,该计划如下:我每天给你十万元,而你第一天只需给我一分钱,第二天我仍给你十万元,你给我两分钱,第三天我仍给你十万元,你给我四分钱,....,你每天给我的钱是前一天的两倍,直到满一个月(30天),百万富翁很高兴,欣然接受了这个契约。请编写程序计算陌生人给百万富翁多少钱,百万富翁给陌生人多少钱?

175 利用循环语句编程,打印下列图形: * * * * * * 行号:i * * * * 空格:4-i 星号:i 行号 空格 星号 1 3 2 4
* * * * * * * * * 行号:i 空格:4-i 星号:i 行号 空格 星号 1 3 2 4 for(i=0;i<4;i++) { for(j=4-i-1;j>0;j--) cout<<" "; for(k=1;k<=i+1;k++) cout<<" * "; cout<<endl<<endl; } 找规律: 上面四行

176 void main(void) { int i,j,k; for(i=0;i<4;i++) { for(j=4-i-1;j>0;j--) cout<<" "; for(k=1;k<=i+1;k++) cout<<" * "; cout<<endl<<endl; } for(i=0;i<4-1;i++) { for(j=4-1-i;j>0;j--)

177 行号:i 空格:3-i 星号:2*i+1 如果打印n行 行号:0~n-1 空格:0~n-1-i 打印图形: * * * *
* * * * * * * * * * * * * * * 行号 空格 星号 3 1 2 5 7 行号:i 空格:3-i 星号:2*i+1 如果打印n行 行号:0~n-1 空格:0~n-1-i

178 t=t*10+2; { s = s +t } 计算:2+22+222+.....+2222222=? 累加和 s=0 设通项为t
所以,通项的循环表示为: 22=2*10+2; 前一项 222=22*10+2; t=t*10+2; 2222=222*10+2; 当前项 t的初值为2 循环体为: { s = s +t t=t*10+2;

179 void main(void) { int t,s; s=0; t=2; for(int i=0;i<7;i++) { s=s+t; t=t*10+2; } cout<<s<<endl;

180 满足以下条件三位数n,它除以11所得到的商等于n的各位数字的平方和,且其中至少有两位数字相同。 131 131/11=11 12+32+12=11
分析: 数字应该从100循环到999 将每位数字剥出,判断其是否满足条件

181 满足以下条件三位数n,它除以11所得到的商等于n的各位数字的平方和,且其中至少有两位数字相同。 131 131/11=11 12+32+12=11
分析: 用a,b,c分别代表三位数,a,b,c分别从0循环到9,组成所有可能的三位数,然后找出满足条件的数来。

182 s=s×t 求n=1000时π的近似值 分析: 通项: 迭代算法: 迭代结束条件: 迭代 1000次 注意s与t的初始值
本次计算的结果 上次迭代的结果 注意s与t的初始值 n从1开始迭代 s=1

183 下面程序的功能是用公式求π的近似值,直到最后一项的值小于10-6为止。请填空。
void main(void ) { int i=1; ______ pi=0; while (i*i<=10e+6) { pi=______________ ; i++; } pi=sqrt (6.0 *pi) ; cout<<“ pi=”<<pi<<endl; double pi+1.0/(i*i)

184 有1020个西瓜,第一天卖一半多两个,以后每天卖剩下的一半多两个,问几天以后能卖完?请填空。
#include”stdio.h” void main(void ) { int day, x1, x2; day=0; x1=1020; while (________ ) { x2=__________; x1=x2; day++; } cout<<“day=”<<day<<endl; x1 x1/2-2

185 第五章 函数与编译预处理

186 概述 函数是程序代码的一个自包含单元,用于完成某一特定的任务。 C++是由函数构成的,函数是C++的基本模块。
有的函数完成某一操作;有的函数计算出一个值。通常,一个函数即能完成某一特定操作,又能计算数值。

187 所编写的函数应尽量少与主调函数发生联系,这样便于移植。
为什么要使用函数? 1、避免重复的编程。 2、使程序更加模块化,便于阅读、修改。 所编写的函数应尽量少与主调函数发生联系,这样便于移植。 函数体 参数(多个) 函数值(唯一)

188 说明: 1、一个源程序文件由一个或多个函数组成,编译程序以文件而不是以函数为单位进行编译的。 2、一个程序可以由多个源文件组成,可以分别编译,统一执行。 3、一个程序必须有且只有一个main( )函数,C++从main( )函数开始执行。 4、C++语言中,所有函数都是平行独立的,无主次、相互包含之分。函数可以嵌套调用,不可嵌套定义。 5、从使用角度来说,分标准函数和用户自定义函数;从形式来说,分无参函数和有参函数。

189 库函数是C++编译系统已预定义的函数,用户根据需要可以直接使用这类函数。库函数也称为标准函数。
为了方便用户进行程序设计,C++把一些常用数学计算函数(如sqrt()、exp()等)、字符串处理函数、标准输入输出函数等,都作为库函数提供给用户,用户可以直接使用系统提供的库函数。 库函数有很多个,当用户使用任一库函数时,在程序中必须包含相应的头文件。 如 #include<iostream.h>等。

190 用户在设计程序时,可以将完成某一相对独立功能的程序定义为一个函数。用户在程序中,根据应用的需要,由用户自己定义函数,这类函数称为用户自定义的函数。
根据定义函数或调用时是否要给出参数,又可将函数分为:无参函数和有参函数。

191 函数定义的一般形式 一、无参函数 主调函数并不将数据传给被调函数。 无参函数主要用于完成某一操作。 函数体 类型说明 函数名(void)
参数(多个) 函数值(唯一) 类型说明 函数名(void) { 函数体 } 不传递参数

192 { cout<<“* * * * * * * * * * *\n”; }
void main(void ) { printstar ( ); print_message ( ); printstar( ); } 两个被调函数主要用于完成打印操作。 调用函数 调用函数 调用函数 函数类型 函数名 函数体 void printstar (void ) { cout<<“* * * * * * * * * * *\n”; } void print_message (void) { cout<<“ How do you do! \n”; }

193 输出: * * * * * * * * * * * How do you do! * * * * * * * * * * *

194 二、有参函数 主调函数和被调函数之间有数据传递。主调函数可以将参数传递给被调函数,被调函数中的结果也可以带回主调函数。 类型说明 函数名(形式参数列表说明 ) { 函数体 }

195 cin>>a>>b; c=max (a , b) ;
形参列表说明 函数类型 int max (int x,int y) { int z; z=(x>y)? x : y ; return z; } 函数名 函数体 函数值 主调函数 void main (void ) { int a,b,c; cin>>a>>b; c=max (a , b) ; cout<<“The max is”<< c<<endl; } 将实际值a,b传给被调函数的参数x,y,计算后得到函数值z返回 调用函数 实际参数

196 cin>>a>>b; c=max (a , b) ;
int max (int x,int y) { int z; z=(x>y)? x : y ; return z; } x y z 2 3 3 void main (void ) { int a,b,c; cin>>a>>b; c=max (a , b) ; cout<<“The max is”<< c<<endl; } 2 3 3 c a b

197 函数参数和函数的值 形参是被调函数中的变量;实参是主调函数赋给被调函数的特定值。实参可以是常量、变量或复杂的表达式,不管是哪种情况,在调用时实参必须是一个确定的值。 形参与实参类型相同,一一对应。 形参必须要定义类型,因为在定义被调函数时,不知道具体要操作什么数,而定义的是要操作什么类型的数。

198 若a为3,b为5,则实参为8, 15,分别送给形参x,y。
int max (int x,int y) { int z; z=(x>y)? x : y ; return z; } 若a为3,b为5,则实参为8, 15,分别送给形参x,y。 void main (void ) { int a,b,c; cin>>a>>b; c=max (a+b , a*b) ; cout<<“The max is”<<c<<endl; } 先计算,后赋值

199 说明: 1、在未出现函数调用时,形参并不占内存的存储单元,只有在函数开始调用时,形参才被分配内存单元。调用结束后,形参所占用的内存单元被释放。 2、实参对形参变量的传递是“值传递”,即单向传递。在内存中实参、形参分占不同的单元。 3、形参只作用于被调函数,可以在别的函数中使用相同的变量名。 5 a 8 b 实参 x y 形参 5 8

200 void fun(int a, int b) { a=a*10; b=b+a; cout<<a<<‘\t’<<b<<endl; } void main(void) { int a=2, b=3; fun(a,b); a b 20 23 2 3 2 3 a b

201 形参实参类型相等,一一对应 void fun(int x, int y) { x=x*10; y=y+x;
cout<<x<<‘\t’<<y<<endl; } void main(void) { int a=2, b=3; fun(a+b,a*b); cout<<a<<‘\t’<<b<<endl; x y 50 5 56 6 5 6 2 3 a b 形参实参类型相等,一一对应

202 形参必须要定义类型,因为在定义被调函数时,不知道具体要操作什么数,而定义的是要操作什么类型的数。
形参是被调函数中的变量;实参是主调函数赋给被调函数的特定值。在函数调用语句中,实参不必定义数据类型,因为实参传递的是一个具体的值(常量),程序可依据这个数值的表面形式来判断其类型,并将其赋值到对应的形参变量中。

203 函数的返回值通过return语句获得。函数只能有唯一的返回值。
函数返回值的类型就是函数的类型。 return语句可以是一个表达式,函数先计算表达式后再返回值。 return语句还可以终止函数,并将控制返回到主调函数。 一个函数中可以有一个以上的return语句,执行到哪一个return语句,哪一个语句起作用。

204 若函数体内没有return语句,就一直执行到函数体的末尾,然后返回到主调函数的调用处。
int add ( int a, int b) { return (a+b); } 先计算,后返回 若函数体内没有return语句,就一直执行到函数体的末尾,然后返回到主调函数的调用处。 int max ( int a, int b) { if (x>y) return x ; else return y; } 可以有多个return语句

205 既然函数有返回值,这个值当然应属于某一个确定的类型,应当在定义函数时指定函数值的类型。
int max (float a, float b) // 函数值为整型 函数返回值的类型,也是函数的类型 不带返回值的函数可说明为void型。 函数的类型与函数参数的类型没有关系。 double blink ( int a, int b) 如果函数的类型和return表达式中的类型不一致,则以函数的类型为准。函数的类型决定返回值的类型。对数值型数据,可以自动进行类型转换。

206 函数体的类型、形式参数的类型必须在函数的定义中体现出来。
如果有函数返回值, 函数的类型就是返回值的类型 int max ( int a, int b) { int z; z=x>y?x:y; return z; } 如果有函数返回值,返回值就是函数值,必须惟一。 函数体的类型、形式参数的类型必须在函数的定义中体现出来。 函数体 参数(多个) 函数值(唯一)

207 函数的调用 i=2; f (i, ++i); 函数调用的一般形式 实际调用: f (3, 3); 函数名(实参列表);
形参与实参类型相同,一一对应。 函数调用的方式 作为语句 printstar( ); 作为表达式 c=max (a,b); 作为另一个函数的参数 cout<<max (a,b);

208 在一个函数中调用另一函数(即被调用函数)需要具备哪些条件呢?
1) 被调用的函数必须是已存在的函数 2) 如果使用库函数,必须用 #include < math.h> 3) 函数调用遵循先定义、后调用的原则,即被调函数应出现在主调函数之前。

209 实参传递的是一个具体的值,不必说明参数类型
float max(float x, float y) { float z; z=(x>y)? x : y ; return z; } 形参必须说明参数类型 被调函数先定义 void main (void) { float a,b, c; cin>>a>>b; c=max (a+b , a*b) ; cout<<“The max is”<<c<<endl; } 定义之后再调用 实参传递的是一个具体的值,不必说明参数类型

210 4) 如果使用用户自己定义的函数,而该函数与调用它的函数(即主调函数)在同一个程序单位中且位置在主调函数之后,则必须在调用此函数之前对被调用的函数作声明。

211 定义是一个完整的函数单位,而原型说明仅仅是说明函数的返回值及形参的类型。
void main (void) { float a,b, c; float max (float,float); cin>>a>>b; c=max (a,b) ; cout<<“The max is”<<c<<endl; } 函数原型说明 float max (float x, float y) { float z; z=(x>y)? x : y ; return z; } 函数定义 定义是一个完整的函数单位,而原型说明仅仅是说明函数的返回值及形参的类型。

212 void main(void) { int i=2, x=5, j=7; void fun(int,int); fun ( j, 6); cout<<i<<‘\t’<< j<<‘\t’<< x<<endl; } void fun ( int i, int j) { int x=7; cout<<i<<‘\t’<< j<<‘\t’<<x<<endl; 2 i 5 x 7 j 6 j x i 7 7 6 输出:

213 void main(void ) { int x=2,y=3, z=0;void add(int,int,int); cout<<“(1) x=“<<x<<“ y=“<<y<<“ z=“<<z<<endl; add (x, y, z); cout<< (“(3) x=“<<x<<“ y=“<<y<<“ z=“<<z<<endl; } void add ( int x, int y, int z) { z=x+y; x=x*x; y=y*y; cout<<(“(2) x=“<<x<<“ y=“<<y<<“ z=“<<z<<endl; 2 x 3 y z 2 3 x y z (1) x=2 y=3 z=0 (2) x=4 y=9 z=5 4 9 5 (3) x=2 y=3 z=0

214 编写程序,分别计算下列函数的值(x从键盘输入)

215 float f1(float x) { float y; y=3*x*x*x+2*x*x-1; return y; } void main(void) { float x, y; cin>>x; y=f1(x); cout<<“x=“<<x<<“ , y=“<<y<<endl;

216 编写程序,分别计算下列函数的值(x从键盘输入)
当最后一项小于 时,累加结束。

217 float fun(float x) { float s=1, t=1; do { t=t/x; s+=t; }while (t> ); return s; } void main(void) { float x; cin>>x; cout<<“s=“<<fun(x)<<endl; }

218 计算100~200之间的素数,用函数prime( )判断一个数是否是素数,若是该函数返回1,否则返回0。
int prime(int x) { for(int i=2;i<x/2;i++) if(x%i==0) return 0; return 1; } void main(void) { for(int i=100;i<=200; i++) if(prime(i)==1) cout<<i<<‘\t’; }

219 计算输入两个数的最大公约数 int gys(int a, int b) { int r; if(a<b){r=a; a=b; b=r;} while(r=a%b) { a=b; b=r;} return b; } void main(void) { int x, y; cin>>x>>y; cout<<gys(x,y)<<endl; }

220 计算输入三个数的最大公约数 void main(void) { int x, y, z; cin>>x>>y>>z; cout<<gys(x,y,z)<<endl; } int gys(int a, int b,int c) { int r; if(a<b){r=a; a=b; b=r;} r=r>c?r:c; for(int i=r-1;i>=1;i--) { if(a%i==0&&b%i==0&&c%i==0) break; } return i;

221 写一个函数验证哥德巴赫猜想;一个不小于6的偶数可以表示为两个素数之和,如6=3+3, 8=3+5, 10=3+7……。在主函数中输入一个不小于6的偶数n,函数中输出以下形式的结果∶
34=3+31

222 C语言中,所有函数都是平行独立的,无主次、相互包含之分。函数可以嵌套调用,不可嵌套定义。
函数的嵌套调用 C语言中,所有函数都是平行独立的,无主次、相互包含之分。函数可以嵌套调用,不可嵌套定义。 int max ( int a, int b) { int c; int min ( int a, int b) { return ( a<b? a: b); } c=min(a,b); return ( a>b? a : b); int min ( int a, int b) { return ( a<b? a: b); } 嵌套定义 平行定义 int max ( int a, int b) { int c; c=min(a,b); return ( a>b? a : b); } 嵌套调用

223 在main函数中调用a函数,在a函数中又调用b函数。
结束 (4) (2) (3) (5) 调用 b 函数 (6) (8) (9) (7)

224 平行定义 平行定义 嵌套调用 嵌套调用 int power(int m,int n) //m^n { int i,product=m;
for(i=1;i<n;i++) product=product*m; return product; } int sum_of_power(int k,int n) //n^k的累加和 { int i,sum=0; for(i=1;i<=n;i++) sum+=power(i,k); return sum; 平行定义 平行定义 嵌套调用 void main(void) { int k,m; cin>>k>>m; cout<<"f("<<k<<","<<m<<")="<<sum_of_power(k,m)<<endl; //m^k的累加和 } 嵌套调用

225 函数的递归调用 在调用一个函数的过程中直接或间接地调用函数本身,称为函数的递归调用。 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); int f(int x) { int y,z ; ..... z=f(y); .... return (2*z); }

226 有5个人坐在一起,问第5个人多少岁,他说比第4个人大2岁。问第4个人多少岁,他说比第3个人大2岁。问第3个人多少岁,他说比第2个人大2岁。问第2个人多少岁,他说比第1个人大2岁。问第1个人多少岁,他说是10岁。请问第5个人多大? age(n)= n=1 age(n-1)+2 n>1 age(5)=age(4)+2 必须有递归结束条件 age(4)=age(3)+2 age(3)=age(2)+2 age(2)=age(1)+2 int age ( int n ) { int c; if (n= =1) c=10; else c=age(n-1)+2; return c; } age(1)=10 int age ( int n ) { int c; c=age(n-1)+2; return c; } void main(void) { int age(int); cout<<age(5)<<endl; }

227 虽然算法一致,但n不同,c不同,在内存中每一层函数变量所在的内存单元均不相同。必须有递归终止条件。
int age ( int n ) { int c; if (n= =1) c=10; else c=age(n-1)+2; return c; } void main(void) { int age(int); cout<<age(5)<<endl; } age (5) age (4) age (3) age (2) age (1) n=5 n=4 n=3 n=2 n=1 c=age (4)+2 c=age (3)+2 c=age (2)+2 c=age (1)+2 c=10 return c return c return c return c return c c=18 c=14 c=12 c=16 虽然算法一致,但n不同,c不同,在内存中每一层函数变量所在的内存单元均不相同。必须有递归终止条件。

228 用递归方法求n! n!= 1 n=0,1 n*(n-1)! n>1 float fac (int n) { float y;
if ((n= =0)|| (n= =1) y=1; else y=n*fac(n-1); return y; } void main (void) { float y; int n; cout<<“Input n:\n”; cin>>n ; cout<<n<<“!=”<<fac(n)<<endl; } fac (5) fac (4) fac (3) fac (2) fac (1) n=5 n=4 n=3 n=2 n=1 y=5*fac (4) y=4*fac (3) y=3*fac (2) y=2*fac (1) y=1 return y return y return y return y return y y=120 y=6 y=2 y=24

229 cout<<sub(i)<<endl; }
int sub (int n ) { int a; if (n= =1) return 1; a=n+sub(n-1); return a; } int sub(int); void main (void) { int i=5; cout<<sub(i)<<endl; } sub (5) sub (4) sub (3) sub (2) sub (1) n=5 n=4 n=3 n=2 n=1 a=5+sub (4) a=4+sub (3) a=3+sub (2) a=2+sub (1) a=1 return a return a return a return a return a a=15 a=10 a=6 a=3 算法相同,层层调用,每层函数的变量所占内存单元不同。

230 43211234 输入:1234 void f(int n ) {if(n= =0) return; void main (void)
else {cout<<n%10; f(n/10); cout<<n%10; return; }} void main (void) { int i=5; cin>>i; f(i); } 输入:1234 1 4 3 2 f(1234) f (123) f(12) f(1) f(0) cout<<n%10 cout<<n%10 cout<<n%10 cout<<n%10 n=0 f(n/10) f(n/10) f(n/10) f (n/10) return cout<<n%10 cout<<n%10 cout<<n%10 cout<<n%10 return return return return 4 3 2 1

231 void recur(char c) { cout<<c; if(c<‘5’) recur(c+1); cout<<c; } void main(void) { recur(‘0’); } 输出:

232 void f(int n) { if(n>=10) f(n/10); cout<<n<<endl; } void main(void) { f(12345); 1 12 123 1234 12345

233 作用域和存储类 作用域是指程序中所说明的标识符在哪一个区间内有效,即在哪一个区间内可以使用或引用该标识符。在C++中,作用域共分为五类:块作用域、文件作用域、函数原型作用域、函数作用域和类的作用域。

234 块作用域 我们把用花括号括起来的一部分程序称为一个块。在块内说明的标识符,只能在该块内引用,即其作用域在该块内,开始于标识符的说明处,结束于块的结尾处。 在一个函数内部定义的变量或在一个块中定义的变量称为局部变量。

235 在函数内或复合语句内部定义的变量,其作用域是从定义的位置起到函数体或复合语句的结束。形参也是局部变量。
float f1( int a) { int b,c; ..... } void main(void ) { int m, n; ..... } a,b,c有效 m,n有效 float f2( int x, int y) { int i, j; ..... } x,y,i,j 有效

236 定义变量既是在内存中开辟区间 主函数main中定义的变量,也只在主函数中有效,同样属于局部变量。
不同的函数可以使用相同名字的局部变量,它们在内存中分属不同的存储区间,互不干扰。 void main(void) { int x=10; { int x=20; cout<<x<<endl; } x 10 定义变量既是在内存中开辟区间 x 20 20 10

237 注意: 具有块作用域的标识符在其作用域内,将屏蔽其作用块包含本块的同名标识符,即 变量名相同,局部更优先。

238 cout<<a<<‘\t’<<b<<‘\t’<<c<<endl;
void main(void) { int a=2, b=3, c=5; cout<<a<<‘\t’<<b<<‘\t’<<c<<endl; { int a, b=2; a=b+c; } c=a-b; a 2 b 3 c 5 -1 a b 2 7 3 5

239 void main(void) { int a=1,b=2,c=3; ++a; c+=++b; { int b=4, c; c=b*3; a+=c; cout<<“first:”<<a<<‘\t’<<b<<‘\t’<<c<<endl; cout<<“second:”<<a<<‘\t’<<b<<‘\t’<<c<<endl; } cout<<“third:”<<a<<‘\t’<<b<<‘\t’<<c<<endl; a=2 b=3, c=6 b=4 c=12 a=14 a=14,b=4,c=12 a=26 a=26,b=4,c=12 a=26,b=3,c=6

240 文件作用域 在函数外定义的变量称为全局变量。 全局变量的作用域称为文件作用域,即在整个文件中都是可以访问的。 其缺省的作用范围是:从定义全局变量的位置开始到该源程序文件结束。 当在块作用域内的变量与全局变量同名时,局部变量优先。

241 全局变量增加了函数间数据联系的渠道,在函数调用时可以得到多于一个的返回值。
p,q有效 int p=1, q=5; float f1( int a) { int b,c; ..... } char c1,c2; main( ) { int m, n; a,b,c有效 m,n有效 c1,c2有效 全局变量 局部变量 全局变量增加了函数间数据联系的渠道,在函数调用时可以得到多于一个的返回值。

242 min 在main( )和max( )中均有效,在内存中有唯一的存储空间。 4 x y z 函数值为4
全局变量 int min; int max (int x, int y) { int z; min=(x<y)?x : y; z=(x>y)? x : y ; return z; } 1 min min 在main( )和max( )中均有效,在内存中有唯一的存储空间。 1 4 4 x y z 函数值为4 void main (void) { int a,b,c; cin>>a>>b; c=max (a , b) ; cout<<“The max is”<<c<<endl; cout<<“ The min is”<<min<<endl; } a b c 1 4 4 The max is 4 The min is 1

243 输出:8 在同一个源文件中,外部变量与局部变量同名,则在局部变量的作用范围内,外部变量不起作用。 int a=3, b=5;
int max(int a, int b) { int c; c=a>b? a:b; return c; } void main(void) { int a=8; cout<<max(a,b)<<endl; 3 a 5 b a 8 max (8,5) 8 a 5 b 输出:8

244 int x; void cude(void) { x=x*x*x ; } void main (void) { x=5; cude ( ); cout<<x<<endl; 输出: 125 x为0 输出: 5 int x=5;

245 ::i=104 i=18 j=108 在块作用域内可通过作用域运算符“::”来引用与局部变量同名的全局变量。
#include <iostream.h> int i= 100; void main(void) { int i , j=50; i=18; //访问局部变量i ::i= ::i+4; //访问全部变量i j= ::i+i; //访问全部变量i和局部变量j cout<<”::i=”<<::i<<’\n’; cout<<”i=”<<i<<’\n’; cout<<”j=”<<j<<’\n’; } ::i=104 i=18 j=108

246 函数原型作用域 在函数原型的参数表中说明的标识符所具有的作用域称为函数原型作用域,它从其说明处开始,到函数原型说明的结束处结束。 float tt(int x , float y); //函数tt的原型说明 由于所说明的标识符与该函数的定义及调用无关,所以,可以在函数原型说明中只作参数的类型说明,而省略参量名。 float tt (int , float);

247 void main(void) { int i=5; rest(i/2); cout<<“i=“<<i<<endl; rest(i=i/2); i= rest(i/2); workover(i) } int i=0; int workover(int i) { i=(i%i)*((i*i)/(2*i)+4); cout<<“i=“<<i<<endl; return i; } int rest (int i) { i=i<2?5:0; i=5 i=2 i=5 i=0 i=5

248 存储类 内存 外存 程序区 存放程序代码 程序 静态存储区 存放变量 动态存储区 需要区分变量的存储类型

249 静态存储:在文件运行期间有固定的存储空间,直到文件运行结束。
作用域 全局变量 局部变量 生存期 动态存储变量 静态存储变量 静态存储:在文件运行期间有固定的存储空间,直到文件运行结束。 动态存储:在程序运行期间根据需要分配存储空间,函数结束后立即释放空间。若一个函数在程序中被调用两次,则每次分配的单元有可能不同。 程序区 静态存储区 动态存储区 静态局部变量 全局变量 动态局部变量

250 局部变量的分类 动态变量(auto):默认,存储在动态区 寄存器变量(register):在cpu内部存储
静态局部变量(static):存储在静态区 动态局部变量未被赋值时,其值为随机值。其作用域的函数或复合语句结束时,空间被程序收回。 程序执行到静态局部变量时,为其在静态区开辟存储空间,该空间一直被保留,直到程序运行结束。 由于存储在静态区,静态局部变量或全局变量未赋初值时,系统自动使之为0。

251 5 9 int fun(int a) { int c; static int b=3; c=a+ b++; return c; }
void main(void) { int x=2, y; y=fun(x); cout<<y<<endl; y=fun(x+3); 只赋一次初值 5 2 4 5 3 9 5 a a b c c 输出: 5 2 9 5 9 x y 变量b是静态局部变量,在内存一旦开辟空间,就不会释放,空间值一直保留

252 i=0 a=2 只赋一次初值 int f (int a) { int b=0; static int c=3; b=b+1; c=c+1; return a+b+c; } b=0, b=1 输出:7 c=3, c=4 a=2 i=1 b=0, b=1 输出:8 c=4, c=5 a=2 i=2 b=0, b=1 输出:9 void main(void) { int a=2,i; for (i=0;i<3;i++) cout<<f(a)<<endl; } c=5, c=6 7 8 9

253 int func (int a, int b) { static int m=0, i=2; i+=m+1; m=i+a+b; return m; } void main(void) { int k=4, m=1, p; p=func(k, m); cout<<p<<endl; func( 4, 1) func( 4, 1) a=4, b=1 a=4, b=1 m=0, i=2 m=8, i=3 i=3 i=3+8+1=12 m=3+4+1=8 m=12+4+1=17 输出:8,17

254 int q(int x) { int y=1; static int z=1; z+=z+y++; return x+z; } void main(void) { cout<<q(1)<<‘\t’; cout<<q(2)<<‘\t’; cout<<q(3)<<‘\t’;

255 全局变量的存储方式(extern static)
全局变量是在函数的外部定义的,编译时分配在静态存储区,如果未赋初值,其值为0。 1、extern 存储类别 全局变量的默认方式,当在一个文件中要引用另一个文件中的全局变量或在全局变量定义之前要引用它时,可用extern作说明,相当于扩大全局变量的作用域。 2、静态(static)存储类别 它仅能在本文件中引用,即使在其它文件中用extern说明也不能使用。相当于限制了全局变量的作用域范围。

256 程序的作用是:给定b的值,输入a和m,求a×b和am的值。
文件file1.c中的内容为: int a; void main(void) { extern int power (int); int b=3, c, d, m; cin>>a>>m; c=a*b; cout<<a<<“*”<<b<<“=“<<c<<endl; d= power(m); cout<<a<<“**”<<m<<“=“<<d<<endl; } 外部全局变量定义 文件file2.c中的内容为: extern int a; int power (int n ) { int i, y=1; for (i=1; i<=n; i++) y*=a; return y; } 外部全局变量说明 引用文件外定义的全局变量

257 静态局部变量:static 在函数内部定义,存储在静态存储区,与auto对应,在别的函数中不能引用。
全局静态变量:static 在函数外部定义,只限在本文件中使用,与extern对应。 当变量名相同致使作用域相重时,起作用的是最近说明的那个变量。 自动 auto 局部变量 静态 static 寄存器 register 全局变量 静态 static 外部 extern

258 内联函数 主调函数 被调函数 调用处 内联函数 主调函数 调用处 被调函数 将被调函数体的代码直接插到调用处

259 内联函数的实质是用存储空间(使用更多的存储空间)来换取时间(减少执行时间).
内联函数的定义方法是,在函数定义时,在函数的类型前增加修饰词inline。

260 inline int max (int x, int y)
{ int z; z=(x>y)? x : y ; return z; } void main (void ) { int a,b,c; cin>>a>>b; c=max (a+b , a*b) ; cout<<“The max is”<<c<<endl; }

261 使用内联函数时应注意以下几点: 1、C++中,除在函数体内含有循环,switch分支和复杂嵌套的if语句外,所有的函数均可定义为内联函数。 2、内联函数也要定义在前,调用在后。形参与实参之间的关系与一般的函数相同。 3、对于用户指定的内联函数,编译器是否作为内联函数来处理由编译器自行决定。说明内联函数时,只是请求编译器当出现这种函数调用时,作为内联函数的扩展来实现,而不是命令编译器要这样去做。 4、正如前面所述,内联函数的实质是采用空间换取时间,即可加速程序的执行,当出现多次调用同一内联函数时,程序本身占用的空间将有所增加。如上例中,内联函数仅调用一次时,并不增加程序占用的存储间。

262 具有缺省参数值和参数个数可变的函数 在C++中定义函数时,允许给参数指定一个缺省的值。在调用函数时,若明确给出了这种实参的值,则使用相应实参的值;若没有给出相应的实参,则使用缺省的值。(举例说明)

263 int fac(int n=2) { int t=1; for(int i=1;i<=n;i++) t=t*i; return t; } void main(void) { cout<< fac(6) <<endl; 输出:720 输出:2 fac( )

264 48 16 8 int area(int long=4 , int width=2) { return long* width; }
void main(void ) { int a=8, b=6; cout<< area(a,b) <<endl; cout<< area(a) <<endl; cout<< area( ) <<endl; } 16 8

265 错误! 使用具有缺省参数的函数时,应注意以下几点: 1.不可以靠左边缺省 int area(int long , int width=2)
2.函数原型说明时可以不加变量名 float v(float,float=10,float=20); 3.只能在前面定义一次缺省值,即原型说明时定义了缺省值,后面函数的定义不可有缺省值。

266 参数个数可变的函数 到目前为止,在定义函数时,都明确规定了函数的参数个数及类型。在调用函数时,实参的个数必须与形参相同。在调用具有缺省参数值的函数时,本质上,实参的个数与形参的个数仍是相同的,由于参数具有缺省值,因此,在调用时可省略。在某些应用中,在定义函数时,并不能确定函数的参数个数,参数的个数在调时才能确定。在C++中允许定义参数个数可变的函数。

267 首先,必须包含头文件“stdarg.h”,因为要用到里面的三个库函数 va_start( )、va_arg( )和va_end( )。
其次,要说明一个va_list类型的变量。va_list与int,float类同,它是C++系统预定义的一个数据类型(非float),只有通过这种类型的变量才能从实际参数表中取出可变有参数。如:va_list ap; (可变参数) a b ... va_start(ap,b):初始化 va_arg(ap,int):依次取参数 va_end(ap):正确结束 ap (va_list)变量

268 va_start():有两个参数,va_start(ap,b); b即为可变参数前的最后一个确定的参数。
va_arg():有两个参数,va_arg(ap,int) int即为可变参数的数据类型名。 int temp; temp=va_arg(ap,int); va_end():完成收尾工作。va_end(ap); 在调用参数个数可变的函数时,必定有一个参数指明可变参数的个数或总的实参个数。如第一个参数值为总的实际参数的个数。

269 使用参数数目可变的函数时要注意以下几点:
1、在定义函数时,固定参数部分必须放在参数表的前面,可变参数在后面,并用省略号“...”表示可变参数。在函数调用时,可以没有可变的参数。 2、必须使用函数va_start()来初始化可变参数,为取第一个可变的参数作好准备工作;使用函数va_arg()依次取各个可变的参数值;最后用函数va_end()做好结束工作,以便能正确地返回。 3、在调用参数个数可变的函数时,必定有一个参数指明可变参数的个数或总的实参个数。

270 所谓函数的重载是指完成不同功能的函数可以具有相同的函数名。
C++的编译器是根据函数的实参来确定应该调用哪一个函数的。 int fun(int a, int b) { return a+b; } void main(void) { cout<<fun(3,5)<<endl; cout<<fun(5)<<endl; } int fun (int a) { return a*a; } 8 25

271 1、定义的重载函数必须具有不同的参数个数,或不同的参数类型。只有这样编译系统才有可能根据不同的参数去调用不同的重载函数。
2、仅返回值不同时,不能定义为重载函数。 即仅函数的类型不同,不能定义为重载函数 int fun(int a, int b) { return a+b; } void main(void) { cout<<fun(3,5)<<endl; cout<<fun(3,5)<<endl; } float fun (int a,int b) { return (float) a*a; }

272 不同的参数类型 double sin(double x1,double x2) { return x1*x2;}
double sin(double x,int a) { return a+x;} void main(void) { double x; cin>>x; cout<<sin(x)<<endl;; cout<<sin(x,x)<<endl; cout<<sin(x,10)<<endl; } sin(x,x) sin(x,10) 不同的参数类型

273 不同的参数个数 int add(int a,int b,int c) { return a+b+c; }
void main(void) { cout<<"3+5="<<add(3,5)<<endl; cout<<"3+5+8="<<add(3,5,8)<<endl; } 不同的参数个数

274 编译预处理 编译预处理 高级语言编译过程 C语言提供的编译预处理的功能有以下三种: 宏定义 文件包含 条件编译 库文件 (各种函数)
可执行文件 (二进制文件) *.EXE 源程序 (文本文件) *.CPP 目标文件 (二进制文件) *.OBJ 编译 连接 C语言提供的编译预处理的功能有以下三种: 宏定义 文件包含 条件编译

275 宏定义 不带参数的宏定义 用一个指定的标识符(即名字)来代表一个字符串,以后凡在程序中碰到这个标识符的地方都用字符串来代替。
这个标识符称为宏名,编译前的替代过程称为“宏展开”。 # define 标识符 字符串

276 { int num, total; /*定义变量*/ num=10; /*变量赋值*/ total=num*PRICE;
#define PRICE 30 void main(void) { int num, total; /*定义变量*/ num=10; /*变量赋值*/ total=num*PRICE; cout<<"total=“<<total<<endl; } 编译前用30替代 编译程序将宏定义的内容认为是字符串,没有任何实际的物理意义。

277 1、宏展开只是一个简单的“物理”替换,不做语法检查,不是一个语句,其后不加分号“;”
注意: 1、宏展开只是一个简单的“物理”替换,不做语法检查,不是一个语句,其后不加分号“;” 2、#define命令出现在函数的外面,其有效范围为定义处至本源文件结束。可以用# undef命令终止宏定义的作用域。 #define G 9.8 void main(void ) {.....} # undef G int max(int a,int b) { }

278 3、对程序中用双引号括起来的字符串内容,即使与宏名相同,也不进行置换。
4、在进行宏定义中,可以用已定义的宏名,进行层层置换。

279 # define R 3.0 # define PI # define L 2*PI*R # define S PI*R*R void main(void) { cout<<“L=“<<L<<“ S=”<<S<<endl; } 层层置换 层层置换 不置换 不置换

280 带参数的宏定义 #define 宏名(参数表) 字符串 #define S(a, b) a*b .... float x, y,area;
cin>>x>>y; area=S(x, y); /* area=x*y; */ 宏定义 形式参数 定义的宏 实参代入后还原 实际参数 宏调用

281 按#define命令行中指定的字符串从左至右进行置换宏名,字符串中的形参以相应的实参代替,字符串中的非形参字符保持不变。
#define S(a, b) a*b 机械地将实参代入宏定义的形参形式 area=S(3,2) 3*2 S(3,2)等同于 3*2 S(a,b)等同于 a*b

282 #define PI #define S(r) PI*r*r void main(void) { float a, area, b; a=3.6; b=4.0; area=S(a); cout<<“r=“<<a<<“\narea=”<<area<<endl; } S(r) PI*r*r S(a) PI*a*a 编译前机械替换,实参形参一一对应 PI*a*a

283 #define PI #define S(r) PI*r*r void main(void) { float a, area, b; a=1; b=2; area=S(a+b); cout<<“r=“<<a<<“\narea=”<<area<<endl; } S(r) PI*r*r S(a+b) PI*a+b*a+b S(a+b) PI*(a+b)*(a+b) 错误 编译前机械替换,实参形参一一对应 宏展开时实参不运算,不作语法检查 #define S(r) PI*(r)*(r)

284 定义宏时在宏名与带参数的括弧间不能有空格。
#define S_ (r) P*r*r 带参数的宏与函数调用的区别 相同:有实参、形参,代入调用。 不同之处: 1、函数调用先求表达式的值,然后代入形参,而宏只是机械替换。 2、函数调用时形参、实参进行类型定义,而宏不需要,只是作为字符串替代。 3、函数调用是在运行程序时进行的,其目标代码短,但程序执行时间长。而宏调用是在编译之前完成的,运行时已将代码替换进程序中,目标代码长,执行时间稍快。 一般用宏表示实时的、短小的表达式。

285 93 编译前机械替换,实参形参一一对应 y=0 ((-1)+1) #define A 3 #define B(a) ((A+1)*a)
执行 x=3*(A+B(7)); 后, x的值为: 93 #define neg(x) ((-x)+1) int neg( int x) {return x+1; } void main(void) { int y; y=neg(1); cout<<“y=“<<y<<endl; } 编译前机械替换,实参形参一一对应 y=0 ((-1)+1)

286 # include “文件名” 文件包含 一个源文件可以将另外一个源文件的全部内容包含进来,即将另外的文件包含到本文件之中。
file1.cpp file1.cpp B A file2.cpp #include “file2.cpp” B A

287 注意: 1、文件名是C的源文件名,是文本文件,后缀名可以任选。*.cpp *.h 2、一个#include语句只能指定一个被包含文件。 3、文件名用双引号或尖括号括起来。 4、包含后所有源文件编译为一个可执行文件。

288 C语言允许有选择地对程序的某一部分进行编译。也就是对一部分源程序指定编译条件。
条件编译 C语言允许有选择地对程序的某一部分进行编译。也就是对一部分源程序指定编译条件。 源程序 可以将部分源程序不转换为机器码

289 当标识符已被定义过(用#define定义),则对程序段1进行编译,否则编译程序段2.
条件编译有以下几种形式: 标识符 1、 # ifdef 标识符 程序段1 # else 程序段2 # end if # define DEBUG ...... # ifdef DEBUG cout<<x<<‘\t’<<y<<endl; # endif 当标识符已被定义过(用#define定义),则对程序段1进行编译,否则编译程序段2.

290 与形式1相反,当标识符没有被定义过(用#define定义),则对程序段1进行编译,否则编译程序段2。
# define DEBUG ...... # ifndef DEBUG cout<<x<<‘\t’<<y<<endl; # endif 2、 # ifndef 标识符 程序段1 # else 程序段2 # endif 与形式1相反,当标识符没有被定义过(用#define定义),则对程序段1进行编译,否则编译程序段2。 调试完后加#define DEBUG,则不输出调试信息。

291 3、 # if 表达式 程序段1 # else 程序段2 # endif # define DEBUG 1 ...... # if DEBUG cout<<x<<‘\t’<<y<<endl; # endif 当表达式为真(非零),编译程序段1,表达式为零,编译程序段2。 调试完后改为 #define DEBUG 0,则不输出调试信息。 采用条件编译后,可以使机器代码程序缩短。

292 以下程序的运行结果是: #define DEBUG void main(void) { int a=14, b=15, c; c=a/b; # ifdef DEBUG cout<<“a=“<<oct<<a<<“ b=“<<b<<endl; # endif cout<<“c=“<<dec<<c<<endl; } 输出:a=16, b=17c=0

293 程序的多文件组织 而在设计一个功能复杂的大程序时,为了便于程序的设计和调试,通常将程序分成若干个模块,把实现一个模块的程序或数据放在一个文件中。当一个完整的程序被存放在多于一个文件中时,称为程序的多文件组织。

294 内部函数:函数只限于在本文件中调用,其它文件不能调用,用static 定义该函数。
内部函数和外部函数 内部函数:函数只限于在本文件中调用,其它文件不能调用,用static 定义该函数。 static float fac( int n) { } 外部函数:函数的默认形式,可以被其它文件调用,用extern 定义该函数。调用时,在文件中用extern 说明。 void main(void) { extern enter_string( ); char str[80]; enter_string(str); } 说明外部函数

295 补充算法 方程求解 1、牛顿切线法 只有为数不多的方程有精确解,一般都是用迭代方法近似求方程的解。方程f(x)=0的实数解实际上是曲线f (x)在x轴上交点的值。 y f(x) x x0

296 1、任选一x值x1,在y1=f(x1)处做切线与x轴相交于x2处。
2、若|x2-x1|或|f(x2)|小于指定的精度,则令x1=x2,继续做1。当其满足所需的精度时,x2就是方程的近似解。 根据已知点求其切线的公式为: 这就是牛顿切线法。 f(x1) y f(x) x2 x1 x2 x 牛顿切线法收敛快,适用性强,缺陷是必须求出方程的导数。 x0 x1

297 已知方程为f(x)=x*x-a时,用牛顿切线法求方程的解。给定初值x0,精度10-6,算法编程如下。
cin>>x1; //从键盘输入x0 do { x0=x1; x1=x0-(x0*x0-a)/(2*x0) ; // } while (fabs(x1-x0)>=1e-6) ; cout>>”x=”>>x1>>endl; 上一循环的新值成为本次循环的旧值 旧值算本次循环的新值

298 y f(x1) 2、弦截法 f(x) x0 x2 x0 x2 x x1 x f(x2) 1、在x轴上取两点x1和x2, 要确保x1与x2之间有且只有方程唯一的解。 2、x1与x2分别与f(x)相交于y1=f(x1)、y2=f(x2)。 3、做直线通过y1、y2与x轴交于x0点。 4、若|f(x0)|满足给定的精度,则x0即是方程的解,否则,若f(x0)*f(x1)<0,则方程的解应在x1与x0之间,令x2=x0,继续做2。同理,若f(x0)*f(x1)>0,则方程的解应在x2与x0之间,令x1=x0,继续做2 ,直至满足精度为止。

299 用两分法求方程的根。 x3-5x2+16x-80=0 void main(void ) { float x1,x2, x0, f0, f1, f2; do { cout<<“Input x1, x2\n”; cin>>x1>>x2; f1=f(x1); f2=f(x2); } while (f1*f2>0); { x0=xpoint(x1,x2); f0=f(x0); if ((f0*f1) >0) { x1=x0;f1=f0;} else { x2=x0; f2=f0;} }while (fabs(f0)>=0.0001); cout<<”x=”<< x0<<endl; } #include <math.h> float f (float x) {return x*x*x-5*x*x+16*x-80; } 输入x,输出f(x) 判断输入是否合法 输入x1,x2,输出x0 float xpoint(float x1,float x2) { float x0; x0=(x1*f(x2)-x2*f(x1))/(f(x2)-f(x1)); return x0; }

300 3、两分法 x0=(x1+x2)/2 1、在x轴上取两点x1和x2, 要确保x1与x2之间有且只有方程唯一的解。
y 3、两分法 f(x) x0 x2 x0 x2 x0=(x1+x2)/2 x x1 x 1、在x轴上取两点x1和x2, 要确保x1与x2之间有且只有方程唯一的解。 2、求出x1,x2的中点x0。 3、若|f(x0)|满足给定的精度,则x0即是方程的解,否则,若f(x0)*f(x1)<0,则方程的解应在x1与x0之间,令x2=x0,继续做2。同理,若f(x0)*f(x1)>0,则方程的解应在x2与x0之间,令x1=x0,继续做2 ,直至满足精度为止。

301 x0=(x1+x2)/2 判断输入是否合法 求x1与x2的中点 用两分法求方程的根。 x3-5x2+16x-80=0
void main(void ) { float x1,x2, x0, f0, f1, f2; do { cout<<“Input x1, x2\n”; cin>>x1>>x2; f1=f(x1); f2=f(x2); } while (f1*f2>0); { x0=(x1+x2)/2; f0=f(x0); if ((f0*f1) >0){ x1=x0;f1=f0;} else { x2=x0;f2=f0;} }while (fabs(f0)>=0.0001); cout<<”x=”<< x0<<endl; } x0=(x1+x2)/2 #include <math.h> float f (float x) {return x*x*x-5*x*x+16*x-80; } 输入x,输出f(x) 判断输入是否合法 求x1与x2的中点

302 int q(int x) { int y=1; static int z=1; z+=z+y++; return x+z; } void main(void) { cout<<q(1)<<‘\t’; cout<<q(2)<<‘\t’; cout<<q(3)<<‘\t’;

303 将后一项除以前一项,找规律 输入精度输出π 下面函数pi的功能是:根据以下公式,返回满足精度(0.0005)要求的π的值,请填空。
#include “math.h” double pi(double eps) { double s, t; int n; for ( ___________; t>eps; n++) { s+=t; t=n*t/(2*n+1); } return ___________ ; main( ) { double x; cout<<“\nInput a precision:”; cin>>x; cout<< “π=“<<pi(x); } t=1,s=0,n=1 2*s

304 void f(int n) { if(n>=10) f(n/10); cout<<n<<endl; } void main(void) { f(12345); 1 12 123 1234 12345

305 545455555657 void main(void) { char s; cin.get(s); while(s!=‘\n’)
{ switch(s-’2’) { case 0: case 1: cout<<s+4; case 2: cout<<s+4;break; case 3: cout<<s+3; default: cout<<s+2; break; } cin.get(s); }cout<<endl; 输入:2347<CR>


Download ppt "C++语言."

Similar presentations


Ads by Google