Presentation is loading. Please wait.

Presentation is loading. Please wait.

VC++系统开发 第二章 C++语言基础 河北经贸大学信息技术学院.

Similar presentations


Presentation on theme: "VC++系统开发 第二章 C++语言基础 河北经贸大学信息技术学院."— Presentation transcript:

1 VC++系统开发 第二章 C++语言基础 河北经贸大学信息技术学院

2 本章主要内容 C++语言主要特点概述 基本数据类型和表达式 数据的输入与输出 算法的基本控制结构 构造数据类型 函数 指针与字符串
预处理指令与文件

3 本章教学目标 熟悉C++语言的主要特点及对C语言的扩展增强; 掌握C++语言的基本语法及面向过程程序设计的基本方法;
进一步熟悉VC++环境下程序的开发编辑、调试过程。 本章重点讨论构造数据类型及函数与指针应用,其他由学生自学。 本章讲授学时数2学时

4 2.1 C++的主要特点概述 C++特点概述 总的说来C++有如下这些特点:
C++是一种多范型混合语言,它既支持POP,又支持OOP。 C++保持了C的紧凑、灵活、高效、功能强和可移植性好等众多优点。 C++对数据抽象的支持主要基于类的概念和机制,对动态联编的支持主要通过虚拟函数来实现。

5 在非面向对象方面的拓展增强主要包括如下方面:
C++特点概述 单行注释--// 块(分程序)内任何位置可定义和声明 显式类型转换新的形式 函数重载 更强的类型检查机制 函数参数的默认值 内联(inline)函数 引用 单目作用域运算符--:: new和delete运算符等 输入/输出流—cin/cout

6 在面向对象方面的拓展增强主要包括如下方面:
C++特点概述 类(包括结构型) 数据封装(类成员的访问控制) 构造函数和析构函数 对象和消息 友元 类中的运算符和函数重载 类的继承(或派生) 多态--虚拟函数等

7 2.2 基本数据类型和表达式 C++各种数据类型占用固定内存长度 short、int、long float、double bool char
跨平台特性 C++各种数据类型占用固定内存长度 C++中字符型数据在操作时将按整型数处理。

8 常量 布尔常量:true和false 整形常量:十(非0开头)、八(以0开头)、十六(以ox开头)进制表示。长整形(加l或L,64位内存)
基本数据类型和表达式 布尔常量:true和false 整形常量:十(非0开头)、八(以0开头)、十六(以ox开头)进制表示。长整形(加l或L,64位内存) unsigned(无符号) 浮点常量:一般浮点(32位F或f),双精度(64位,D或d)、E记数法(如1.2E-9)。长双精度(LD) 字符常量:一对单引号括起,可用转义字符表示(见表2-2)。 字符串常量:双引号括起。如“hello”,”My\nJava”

9 变量 变量是用来存放指定类型的数据,其值在程序运行过程中是可变的 变量分为两种:类成员变量和局部变量
基本数据类型和表达式 变量是用来存放指定类型的数据,其值在程序运行过程中是可变的 变量分为两种:类成员变量和局部变量 变量必须先声明,后使用,声明变量即开辟内存空间,登记变量名、初始值等。如 int a; char b,c; a=10;b=‘n’; bool m_bFlag=true;

10 运算符与表达式 赋值运算 算术运算 关系运算 逻辑运算 位运算 其它运算 表 达 式 基本数据类型和表达式 变量或对象=表达式;
复杂赋值:*= 赋值运算 双目运算符:+、-、*、/、% 单目运算符:++、--、- 算术运算 关系运算符:==、!=、>、< >=、<=。其值true 或false 关系运算 逻辑运算符:!、&&、|| 其值true 或false 逻辑运算 位运算 位运算符:~、&、|、^、<<、>> 三目运算符:? X?y:z//x为逻辑值 其它运算

11 运算符与表达式 运算符的优先级与结合性 优先级决定了表达式中不同运算执行的先后顺序。括号→ ++ 、 --→ sizeof→ *, /, % → +, - → ==, != → 位运算→ && → ||→ ?:→赋值运算→逗号运算 结合性决定了并列的相同运算的先后执行顺序。 一般单目、三目、赋值为右结合。 x+y+z等价与(x+y)+z !!x等效与!(!x),

12 运算符与表达式 类型转换 C++类型转换规定: 自动转换:变量从占用内存较少的短数据类型转换为占用内存较多的长数据类型 可以采用强制类型转换: 例如: float c; int a,b; c=float(a)/float(b); 或 c= (float)a/(float)b;

13 思考:int a=2,b=3;float x=3.5,y=2.5; 计算: (float)(a+b)/2+(int)x%(int)y
运算符与表达式 重要知识点: 1.只有整数类型(int,long,short)的数据才能够进行取余运算。两个整形的数据做除法,结果是截取商数的整数部分,如1/2=0,float(1)/2=0.5 思考:int a=2,b=3;float x=3.5,y=2.5; 计算: (float)(a+b)/2+(int)x%(int)y 结果:3.5 如7/5和9/5 ; 1 40%5的结果是: 0 40%-11的结果是:7 -40%11的结果是:-7 -40%-11的结果是:-7 结果符号同被除数

14 重要知识点: 2.字符数据在内存中的存储形式 以ASCII码存储,占1字节,用7个二进制位 转义序列表示法 ( \ddd”和“\xhh )
运算符与表达式 2.字符数据在内存中的存储形式 以ASCII码存储,占1字节,用7个二进制位 转义序列表示法 ( \ddd”和“\xhh )  -例如“\101”和“\x41” ,”\n”, “\\” , “\”” “Please press \"F1\" to help!” 字符数据的使用方法 字符数据和整型数据之间可以运算。 字符数据与整型数据可以互相赋值。 如:int b='a'+3; // 结果b为100,‘a’的ASCII码值97 字符串常量 例:“CHINA” “a“ 字符串常量 ‘a’ 字符常量 结果: Please press "F1" to help!” 所以:char c; c="a";

15 符号常量是具有固定值的标识符,可以用两种格式来定义一个符号常量,其格式如下: #define PI 3.141593
重要知识点: 运算符与表达式 3. ——符号常量 符号常量是具有固定值的标识符,可以用两种格式来定义一个符号常量,其格式如下: #define PI const double PI= ; //带有数据类型,编译时查错 4.++、--运算符 int x=2,y; int y=++x*3;//结果 int y=x++*3;//结果 x=3,y=9 x=3,y=6

16 Bool b=x>y&&x++==y--;//结果 6.位运算
运算符与表达式 重要知识点: 5.逻辑运算的短路求值 int x=3,y=5; Bool b=x>y&&x++==y--;//结果 6.位运算 x=3,y=5,b=false 如:~1011=0100。1011&1010=1010。    1011 | 1010=1011。1011^1010=0001。 x(十进制表示) 二进制补码 x<< x>>2 右移:a)无符号数:最低位舍弃,最高位补0;b)有符号数:最低位舍弃,最高位与原来的最高位相同。如1011>>2结果为0010。

17 k=i<j?++i;++j;//k=5,j=?,i=?
重要知识点: 运算符与表达式 7.三目运算符 int i=8,j=4,k; k=i<j?++i;++j;//k=5,j=?,i=? k=i<j?i+j:(i+j)>0?i:j++;//k=8,j=?,i=? 7.复杂运算符 x+=a;//x=x+a; x*=a+b;//x=x*(a+b); j=8,i=5, j=4,i=8 8. 逗号运算和逗号表达式 如:a=3*5,a*4 ; 最终结果为15 如:a=(a=3*5,a*4 ) ; 最终结果为60

18 赋值表达式举例 重要知识点: a=5 表达式值为5 a=b=c=5 表达式值为5,a,b,c均为5
运算符与表达式 赋值表达式举例 a=5 表达式值为5 a=b=c=5 表达式值为5,a,b,c均为5 a=5+(c=6) 表达式值为11,a为11,c为6 a=(b=4)+(c=6) 表达式值为10,a为10,b为4,c为6 a=(b=10)/(c=2) 表达式值为5,a为5,b为10,c为2 a+=a-=a*a 相当于: a=a+(a=a-a*a) 赋值语句与赋值表达式的区别: 赋值表达式可以包含在其它表达式中,而赋值语句不可。 例:if ((a=b)>0) t=a; 不可写为:if ((a=b;)>0) t=a; Page 18

19 2.3 标准输入输出(I/O) 标准I/O操作指通过标准输入输出设备进行数据的输入和输出操作(输入:键盘,输出:显示器)
C++中的cin和cout 是预先定义的流对象,分别代表标准输入设备(键盘)和标准输出设备(显示器)。cin和cout定义在iostream.h头文件中,因此程序中需要使用cin和cout对象时,应将该头文件包含进去。 向标准输出设备(显示器)输出 例: cout<<"ABCD\t"<<1234<<"\t"<<endl;; 从标准输入设备(键盘)输入 例:int nNum1, nNum2, nNum3; cin>>nNum1>>nNum2>>Nnum3; 提取符 插入符

20 2.4 结构化程序设计 结构化程序设计的基本原则:任何程序都可以且只能由三种基本流程结构组成 即顺序结构、分支结构和循环结构。 分支语句 循环语句 跳转语句

21 2.4.1 分支语句 流程控制语句 if (表达式) 语句 例:if (x>y) cout<<x; if ( )
if (表达式) 语句1 else 语句2 else cout<<y; if (表达式1) 语句1 else if (表达式2) 语句2 else if (表达式3) 语句 … else 语句 n if ( ) if ( ) 语句 1 else 语句 2 else if ( ) 语句 3 else 语句 4 例2-1 输入两个整数,比较两个数的大小。(P31页)

22 请使用if-else if完成该题 流程控制语句 #include<iostream.h> void main( ) {
int x,y; cout<<"Enter x and y:"; cin>>x>>y; if (x!=y) if (x>y) cout<<"x>y"<<endl; else cout<<"x<y"<<endl; cout<<"x=y"<<endl; } 运行结果1: Enter x and y:5 8 x<y 运行结果2: Enter x and y:8 8 x=y 运行结果3: Enter x and y:12 8 x>y 请使用if-else if完成该题

23 2.4.2 switch 语句 一般形式 执行顺序 流程控制语句
{ case 常量表达式 1:语句1 case 常量表达式 2:语句2 case 常量表达式 n:语句n default : 语句n+1 } 可以是整型、字符型、枚举型 每个常量表达式的值不能相同,次序不影响执行结果。 例:P58 程序举例:P 自己看书 可以是多个语句,但不必用{ }。 执行顺序 以case中的常量表达式值为入口标号,由此开始顺序执行。因此,每个case分支最后应该加break语句。

24 例2-2:输入成绩(P33页) 若:90—100:A , 70—89:60—69:C 59-0 :D 流程控制语句
#include <iostream.h> void main() { float score=80,int MyGrade; String MyScore; MyGrade=(int)(score/10); switch (MyGrade) { case 10: case 9:MyScore=‘A’;break; case 8: case 7:MyScore=‘B’;break case 6:MyScore=‘C ; default:MyScore=‘D’ ; } 若干分支执行内容相同可共用一组语句。 break定义分支出口 这里的复合语句不需{ }

25 2.4.3 循环语句 流程控制语句 a)while语句 b)do-while语句 c)for语句 真 假 真 假 表达式 语句 真 表达式
表达式1 表达式3 表达式2 表达式 语句 表达式 语句 例2-3a 例2-3b 例2-3c

26 例2-3a 求自然数1~10之和 分析:本题需要用累加算法,累加过程是一个循环过程,可以用while语句实现。
#include<iostream.h> void main( ) { int i(1), sum(0); while(i<=10) { sum+=i; i++; } cout<<"sum="<<sum <<endl; 请用d0-while、for 语句实现? (详见P34,例2-11)

27 分离各位i=n/100;j=(n-i*100)/10;k=n%10;
例2-4 求水仙花数 流程控制语句 水仙花数:是一个三位数,它的各位数字的立方和 等于这个三位数本身,如371= 用while循环,编写程序 分离各位i=n/100;j=(n-i*100)/10;k=n%10; 判断是否水仙花数 若是则输出

28 2.4.4 跳转、break、return语句 Continue语句 continue语句必须用于循环体内.
流程控制语句 Continue语句 continue语句必须用于循环体内. continue;//作用是跳过本轮循环。 break语句 break语句使程序的流程从一个语句块内跳转过来. break;//从当前switch分支或最内层循环体内跳转出来 return语句 return 表达式; //返回表达式的值

29 2.5 构造数据类型(了解) 自定义数据类型 为一个已有的数据类型另外命名 语法形式 例如 typedef 已有类型名 新类型名表;
2.5 构造数据类型(了解) 自定义数据类型 为一个已有的数据类型另外命名 语法形式 typedef 已有类型名 新类型名表; 例如 typedef double area,volume; typedef int natural; natural i1,i2; area a; volume v;

30 2.5.1 数组 数组是具有一定顺序关系的若干相同类型变量的集合体,组成数组的变量称为该数组的元素。 数组属于构造类型。 数组
本单元教学目标:  了解构造数据类型,掌握数组的定义、初始化和使用方法;  理解字符与字符串、字符串与字符数组的区别,掌握它们的使用方法。

31 一维数组 一维数组的声明 例如: int a[10]; 引用 必须先声明,后使用。 存储顺序。 a 数组
类型说明符 数组名[ 常量表达式 ]; 引用 必须先声明,后使用。 只能逐个引用数组元素,而不能一次引用整个数组 例如:a[0]=a[5]+a[7]-a[2*3] 存储顺序。 数组元素在内存中顺次存放,它们的地址是连续的。 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] a 数组名字是数组首元素的内存地址。 数组名是一个常量,不能被赋值。

32 在声明数组时对数组元素赋以初值。 例如:static int a[10]={0,1,2,3,4,5,6,7,8,9};
一维数组初始化。 可以在编译阶段使数组得到初值 在声明数组时对数组元素赋以初值。 例如:static int a[10]={0,1,2,3,4,5,6,7,8,9}; 可以只给一部分元素赋初值。 例如:static int a[10]={0,1,2,3,4}; 在对全部数组元素赋初值时,可以不指定数组长度。 例如:static int a[ ]={1,2,3,4,5}

33 例2-7 :用数组来处理求Fibonacci数列问题
#include <iostream.h> void main( ) { int i; static int f[20]={1,1};/*初始化第0、1个数*/ for(i=2;i<20;i++) f[i]=f[i-2]+f[i-1]; /*求第2~19个数*/ for(i=0;i<20;i++) /*输出,每行5个数*/ { if(i%5==0) cout<<‘\n’; cout<<f[i]; } } 运行结果: 例2-8 :冒泡法排序 P39

34 二维数组 二维数组的声明 存储顺序 a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23 引用
类型说明符 数组名[常量表达式][常量表达式] 例如:float a[3][4]; a[0]——a00 a01 a02 a03 a[1]——a10 a11 a12 a13 a[2]——a20 a21 a22 a23 a 可以理解为: 存储顺序 按行存放,上例中数组a的存储顺序为: a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23 引用 例如:b[1][2]=a[2][3]/2 下标不要越界

35 二维数组的初始化 分行给二维数组赋初值 将所有数据写在一个{}内,按顺序赋值 可以对部分元素赋初值 数组
二维数组程序举例: P87 例6.4 二维数组的初始化 分行给二维数组赋初值 例如:static int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}; 将所有数据写在一个{}内,按顺序赋值 例如:static int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; 可以对部分元素赋初值 例如:static int a[3][4]={{1},{0,6},{0,0,11}};

36 字符数组与字符串 字符数组的声明和引用 字符数组的初始化
char string[10]; //一维字符数组 char book[5][10]; //二维字符数组 字符数组中的一个元素存放一个字符。 用字符数组来存放字符串,字符串以'\0'为结束标志 字符数组的初始化 例:static char str[8]={112,114,111,103,114,97,109,0}; static char str[8]={'p','r','o','g','r','a','m','\0'}; static char str[8]="program"; static char str[ ]="program";

37 方法 注意 字符串的输入/输出 逐个字符输入输出
数组 字符串的输入/输出 方法 逐个字符输入输出 将整个字符串一次输入或输出 例:char c[ ]="China"; cout<<c; 注意 输出字符不包括 '\0' 输出字符串时,输出项是字符数组名,输出时遇到'\0'结束。 输入多个字符串时,以空格分隔;输入单个字符串时其中 不能有空格。

38 例如: 数组 程序中有下列语句: static char str1[5],str2[5],str3[5];
cin>>str1>>str2>>str3; 运行时输入数据: How are you? 内存中变量状态如下: str1: H o w \0 str2: a r e \0 str3: y o u ? \0 数组 若改为: static char str[13]; cin>>str; 运行时输入数据: How are you? 内存中变量 str 内容如下: str: H o w \0

39 字符串处理函数 数组 字符串 strcat(连接),strcpy(复制), strcmp(比较),strlen(求长度), strlwr(转换为小写), strupr(转换为大写) 头文件<string.h>

40 例2-9 string类应用举例 数组 例4.4 输入一行文本,统计其中单词的个数。单词是长度不超过20个字符的字母和数字组成的字符串,以空格作为不同单词的分隔符。例如,如输入“The 50 books in the disk”,则单词个数为6。 分析:若文本行已送入buf,对buf中内容从头到尾一个一个地取出并进行判断,当遇到空格时,表示已读完一个单词,将它拼接起来且存入一个表格。能放单词的表格应是二维字符数组,数组的每一行放一个单词,即每行20列。 字符串

41 数组 程序: #include <string.h> #include <stdio.h> #include <ctype.h>//使用字符函数时要包含头文件 const int SIZE=80; const int N= 20;  void main( ) { char buf[SIZE], s[SIZE][N]={0}; int num, pos, i; cin>>buf; num=-1; // 单词计数初始值 pos=0; // 下标

42 数组 do{ if(buf[pos]!=' ' && buf[pos]!='\0') { //读到单词的首字符 num++; // 统计单词个数 i=0; //拼一个单词送入s while(isalnum(buf[pos])) s[num][i++]=buf[pos++]; } else pos++; }while(pos<SIZE && buf[pos]); cout<<"They are ”<< num+1 <<“words: \n"; for(i=0; i<=num; i++) cout<< i+1<< s[i];

43 数组 程序的运行情况如下: The 50 books in the disk The are 6 words: 1. The 2. 50 3. books 4. in 5. the 6. disk 程序中使用字符函数isalnum(ch)判断一个字符ch是否为字母或数字字符,是,则返回1,否则返回0。

44 例2-10 综合举例(源代码,演示) 某班有3个学生,期终考试3门课程。求每个学生总成绩、平均成绩,并按总成绩高分到低分输出。使用数组()
源代码  E:\Myvc\CH2\Exp2_10\Exp2_10.cpp #include<iomanip.h> #include<string.h> const int M=3; const int N=5; //void input( ); //输入函数 void count( ); /*计算函数*/ void sort( );/*排序函数*/ void output( );/*输出函数*/ char st[M][8]={"王","张","李"};/*定义学号数组实现数据传递*/ float cj[M][N]={{56,67,89},{78,89,90},{90,89,98}};//定义成绩及总成绩、平均成绩数组。

45 void main() { int i,flag=1; while(flag)//当flag为真时循环 { cout<<"1-输入 排序"<<endl; cout<<"2-修改 输出"<<endl; cout<<"3-计算 退出"<<endl; cout<<"输入你的选择(0-5):"; cin>>i; while(i<0||i>5) { cout<<"请重新输入你的选择(0-5):"; cin>>i;} cout<<endl;

46 switch(i) { case 1://输入 cout<<"正在输入学生数据..."<<endl; //input();//调用输入数据函数 break; case 2://修改 cout<<"修改学生数据..."<<endl; cout<<"本模块正在加工中..."<<endl; case 3://计算 …… case 0://结束 cout<<"本次处理结束。bye-bye"<<endl; flag=0; }

47 2.5.2 枚举类型—enum 枚举类型应用说明: 对枚举元素按常量处理,不能对它们赋值。例如,不能写:sun=0;
枚举元素具有缺省值,它们依次为: 0,1,2,......。 也可以在声明时另行指定枚举元素的值,如: enum weekday {sun=7,mon=1,tue,wed,thu,fri,sat}; 枚举值可以进行关系运算。 整数值不能直接赋给枚举变量,如需 要将整数赋值给枚举变量,应进行强 制类型转换。

48 2.5.3 结构体——结构的声明 结构的概念 结构是由不同数据类型的数据组成的集合体。 声明结构类型 举例:
结构体——结构的声明 结构的概念 结构是由不同数据类型的数据组成的集合体。 声明结构类型 举例: struct Student //学生成绩结构体 { int num; //学号 char name[8]; //姓名 float score[3],ave,sum;//成绩 }stu[M} ; 结构体成员的引用形式: 结构变量名.成员名

49 例2-11学生成绩管理结构体实现 源代码 E:\Myvc\CH2\Exp2_11\Exp2_11.cpp
void input() /*输入函数*/ { int i, j; for(i=0; i<M; i++) { cout<<"请输入第"<<i+1<<"学生成绩"<<endl; cout<<"学号 姓名 数学 语文 英语 \n"; cin>>stu[i].num; cin>>stu[i].name; for(j=0;j<N-2;j++) cin>>stu[i].score[j]; } cout<<"共输入"<<i<<"个学生记录"<<endl;

50 续: 例2-12 P41 void sort()/*排序函数*/ {int i,j; Student ts;
for(i=0; i<M-1; i++) {for (j=i+1;j<M;j++) if(stu[i].sum<stu[j].sum) {ts=stu[i];stu[i]=stu[j];stu[j]=ts;} } 例 P41

51 2.5.4 联合体 声明形式: 联合体类型变量说明的语法形式 引用形式: union 联合名 { 数据类型 成员名 1;
联合体 声明形式: union 联合名 { 数据类型 成员名 1; 数据类型 成员名 2;  : 数据类型 成员名 n; }; 联合体类型变量说明的语法形式 联合名 联合变量名; 引用形式: 联合名.成员名

52 自定义数据类型 联合体 例: union uarea { char c_data; short s_data; long l_data; }

53 2.6 函数 本单元教学目标: 理解和掌握结构化程序设计的有关知识,掌握函数的定义和使用方法; 理解和掌握预处理;
能综合运用上述方法和技术进行一般的程序设计。

54 本节主要内容 函数的声明和调用 函数间的参数传递 内联函数 带缺省形参值的函数 函数重载 函数模板

55 2.6.1 函数的声明与调用 函数是面向对象程序设计中的基本抽象单元,是对功能的抽象 函数声明的语法形式 类型标识符 函数名(形式参数表)
类型标识符 函数名(形式参数表) { 语句序列 } 若无参数,写void 是被初始化的内部变量,寿命和可见性仅限于函数内部 若无返回值,写void

56 函数的调用 调用前先说明函数原型: 类型标识符 被调用函数名 (含类型说明的形参表); 调用形式 函数名(实参列表) 嵌套调用
类型标识符 被调用函数名 (含类型说明的形参表); 调用形式 函数名(实参列表) 嵌套调用 函数不允许嵌套声明,但可以嵌套调用。 递归调用 函数直接或间接调用自身。

57 例2-12 编写程序求π的值 函数的声明与使用 其中arctan用如下形式的级数计算:
直到级数某项绝对值不大于10-15为止;π和x均为double型。

58 #include<iostream.h>
void main( ) { double a,b; double arctan(double x) ; a=16.0*arctan(1/5.0) ; b=4.0*arctan(1/239.0) ; //注意:因为整数相除结果取整, //如果参数写1/5,1/239,结果就都是0 cout<<"PI="<<a-b<<endl; }

59 运行结果: PI=3.14159 double arctan(double x) { int i; double r,e,f,sqr;
sqr=x*x; r=0; e=x; i=1; while(e/i>1e-15) { f=e/i; r=(i%4==1)? r+f : r-f ; e=e*sqr; i+=2; } return r ; 运行结果: PI=

60 递归调用 函数的声明与使用 函数直接或间接地调用自身,称为递归调用。 递归过程的两个阶段: 递推: 未知 已知 回归:
4!=4×3! → 3!=3×2! → 2!=2×1! → 1!=1×0! → 0!=1 未知 已知 回归: 4!=4×3!=24←3!=3×2!=6←2!=2×1!=2←1!=1×0!=1←0!=1 未知 已知

61 例2-13 求n! 函数的声明与使用 分析:计算n!的公式如下: 这是一个递归形式的公式,应该用递归函数实现。

62 源程序: #include <iostream.h> long fac(int n) { long f; if (n<0) cout<<"n<0,data error!"<<endl; else if (n==0) f=1; else f=fac(n-1)*n; return(f); }

63 void main( ) { long fac(int n); int n; long y; cout<<"Enter a positive integer:"; cin>>n; y=fac(n); cout<<n<<"!="<<y<<endl; } 运行结果: Enter a positive integer:8 8!=40320

64 2.6.2 函数的参数传递机制 ——传递参数值 函数的声明与使用 在函数被调用时才分配形参的存储单元。 实参可以是常量、变量或表达式。
2.6.2 函数的参数传递机制 ——传递参数值 函数的声明与使用 在函数被调用时才分配形参的存储单元。 实参可以是常量、变量或表达式。 实参类型必须与形参相符。 传递时是传递参数值,即单向传递。

65 例2-13a 输入两 整数交换后输出 #include<iostream.h> void Swap(int a, int b);
int main( ) { int x(5), y(10); cout<<"x="<<x<<" y="<<y<<endl; Swap(x,y); return 0; } 交换函数 Swap 采用值传递,未达到交换效果。 void Swap(int a, int b) { int t; t=a;a=b;b=t; } 运行结果: x= y=10

66 函数的参数传递 ——用引用做形参 例2-13b 输入两个整数交换后输出 void Swap(int& a, int& b)
函数的参数传递 ——用引用做形参 例2-13b 输入两个整数交换后输出 void Swap(int& a, int& b) { int t; t=a; a=b; b=t; } 运行结果: x= y=10 x= y=5 #include<iostream.h> void Swap(int& a, int& b); int main( ) { int x(5), y(10); cout<<"x="<<x<<" y="<<y<<endl; Swap(x,y); return 0; }

67 2.6.3 内联函数声明与使用 内联函数 声明时使用关键字 inline。 编译时在调用处用函数体进行替换,节省了参数传递、控制转移等开销。
注意: 内联函数体内不能有循环语句和switch语句。 内联函数的声明必须出现在内联函数第一次被调用之前。 对内联函数不能进行异常接口声明。 内联函数

68 缺省形参 带缺省形参值的函数 函数在声明时可以预先给出默认的形参值,调用时如给出实参,则采用实参值,否则采用预先给出的默认形参值。 例如:
int add(int x=5,int y=6) { return x+y; } void main(void) { add(10,20); //10+20 add(10); //10+6 add( ); //5+6 } 注:缺省形参值必须从右向左顺序声明,并且在缺省形参值的右面不能有非缺省形参值的参数。

69 2.6.3 重载函数的声明 函 数 重 载 C++允许功能相近的函数在相同的作用域内以相同函数名声明,从而形成重载。方便使用,便于记忆。
函 数 重 载 C++允许功能相近的函数在相同的作用域内以相同函数名声明,从而形成重载。方便使用,便于记忆。 例: 形参类型不同 int add(int x, int y); float add(float x, float y); 形参个数不同 int add(int x, int y); int add(int x, int y, int z);

70 注意事项 函 数 重 载 重载函数的形参必须不同: 个数不同或类型不同。
函 数 重 载 重载函数的形参必须不同: 个数不同或类型不同。 编译程序将根据实参和形参的类型及个数的最佳匹配来选择调用哪一个函数。 int add(int x,int y); int add(int a,int b); 编译器不以形参名来区分 int add(int x,int y); void add(int x,int y); 编译器不以返回值来区分 不要将不同功能的函数声明为重载函数,以免出现调用结果的误解、混淆。这样不好: int add(int x,int y) { return x+y; } float add(float x,float y) { return x-y; }

71 函数模板 例2-14 求绝对值函数的模板 #include<iostream.h>
template<typename T> T abs(T x) { return x<0?-x:x; } void main( ) { int n=-5; double d=-5.5; cout<<abs(n)<<endl; cout<<abs(d)<<endl; } 运行结果: 5 5.5

72 例2-15函数综合举例学生成绩管理函数实现 #include<iomanip.h>
#include<string.h> const int M=50; struct Student { int num; char name[8]; float score[3],ave,sum; }; void input(Student s[],int n); /*调用函数声明*/ void count(Student s[],int n); /*计算函数*/ void sort(Student s[],int n);/*排序函数*/ void output(const Student s[], int n);/*输出函数*/

73 例2-15函数综合举例学生成绩管理函数实现 void main() {Student stu[M];
int n;cout<<"请输入班级人数(人数不超过50):"; cin>>n; …… switch(i) { case 1://输入 cout<<"正在输入学生数据..."<<endl; input(stu,n);//调用输入数据函数 break; }

74 例2-15函数综合举例学生成绩管理函数实现 void input(Student s[],int n ) /*输入函数*/
{ int i, j; for(i=0; i<n; i++) {cout<<"请输入第"<<i+1<<"学生成绩"<<endl; cout<<"学号 姓名 数学 语文 英语 \n"; cin>>s[i].num; cin>>s[i].name; for(j=0;j<3;j++) cin>>s[i].score[j]; } cout<<"共输入"<<i<<"个学生记录"<<endl;

75 2.7 指针 教学目标: 理解指针的含义,掌握指针定义、初始化和使用方法; 理解指针与数组之间的关系,掌握使用指针访问数组的方法;
2.7 指针 教学目标: 理解指针的含义,掌握指针定义、初始化和使用方法; 理解指针与数组之间的关系,掌握使用指针访问数组的方法; 理解动态数组与动态存储分配的概念,会使用动态数组与动态存储分配; 理解指针与字符串之间的关系,能用指针操作字符串; 理解指针与函数之间的关系,掌握指针参数和返回指针的函数的用法; 理解指向函数的指针的含义,会用指向函数的指针调用函数。

76 本单元主要内容 指针和指针变量 指针变量的定义和使用 指针与数组 指针与字符串 指针与函数 有关指针的数据类型小结

77 2.7.1 指针与指针变量 指 针 static int *i_pointer=&i; 概念 指针:另一个变量的地址, 用于间接访问变量
内存用户数据区 变量 i 变量 j 变量 i_pointer 3 6 2000 2004 3010 指 针 概念 指针:另一个变量的地址, 用于间接访问变量 指针变量: 用于存放地址的变量 声明 例:static int i; static int *i_pointer=&i; 指向整型变量的指针 引用 例1: i=3; 例2: *i_pointer=3; 2000 3 i_pointer *i_pointer i

78 2.7.2 指针变量的定义与使用 例2-16 a 调用swap函数交换实参变量的值。 #include <iostream.h>
void swap(int x, int y); //函数原型声明 main( ) //main函数定义 { int a=6, b=9; swap(a, b); //调用swap函数,交换a,b的值 cout>>”a=“>>a>>”b=“>>b>>endl; //显示交换的结果 } void swap(int x, int y) //swap函数定义 { int t; cout>>”x=“>>x>>”y=“>>y>>endl; //显示交换前的值 t = x; x = y; y = t; cout>>”x=“>>x>>”y=“>>y>>endl; //显示交换后的值 }

79 指 针 运行该程序,输出结果为: Start of the swap:x=6 y=9 End of the swap:x=9 y=6
In main after swap:a=6 b=9 结论:虽然在swap函数中变量x、y的值交换了,但主函数中变量a、b的值并没有交换。为什么? 例2-16a程序的执行情况如下图所示: 指 针

80 例2-16b 用swap函数交换实参变量的值(传地址方式)。
#include <iostream.h> void swap(int *x, int *y); //函数原型声明,形参为指针变量 main( ) { int a=6, b=9; swap(&a, &b); //以变量的地址作swap函数的实参 cout>>”a=“>>a>>”b=“>>b>>endl; } void swap(int *x, int *y) //swap函数定义,形参为指针变量 { int t; t = *x; *x = *y; *y = t; //交换指针所指向的存储单元中的值 } 程序运行的结果为: In main:a=9 b=6

81 指针的基本操作:P

82 2.7.4 指针与数组 指针与一维数组 声明与赋值 例: int a[10], *pa; pa=&a[0]; 或 pa=a;
指针与数组 指针与一维数组 声明与赋值 例: int a[10], *pa; pa=&a[0]; 或 pa=a; 通过指针引用数组元素 经过上述声明及赋值后: *pa就是a[0],*(pa+1)就是a[1],... ,*(pa+i)就是a[i]. a[i], *(pa+i), *(a+i), pa[i]都是等效的。 不能写 a++,因为a是数组首地址,是常量。

83 数组元素的引用 指 针 例2-17 设有一个int型数组a,有10个元素。用三种方法输出各元素: (1) 下标法
数组名下标法: array[i] 指针变量下标法:pointer[i] (2) 指针法: 数组名指针法: array+i 表示array[i]的地址 *(array+i) 表示数组元素array[i] 指针变量指针法: pointer+i 表示array[i]的地址 *(pointer +i) 表示数组元素array[i] 指 针 例2-17 设有一个int型数组a,有10个元素。用三种方法输出各元素:

84 #include<iostream.h> void main( )
{ int a[10]; int i; for(i=0; i<10; i++) cin>>a[i]; cout<<endl; cout<<*(a+i); } 使用指针变量 #include<iostream.h> void main( ) { int a[10]; int *p,i; for(i=0; i<10; i++) cin>>a[i]; cout<<endl; for(p=a; p<(a+10); p++) cout<<*p; } 使用数组名和下标 使用数组名和指针

85 指针与数组 指 针 指针与二维数组 二维数组的指针(即行指针)是二级指针,数组元素的指针(即列指针)是一级指针。
指 针 二维数组的指针(即行指针)是二级指针,数组元素的指针(即列指针)是一级指针。 在C++中,二维数组的行指针和列指针的表示方法见下表: 行指针 列指针 数组元素 &a[i] ⑴ &a[i][j] ① a[i][j]  a[i]+j ② *(a[i]+j)  a+i ⑵ *(a+i)+j ③ *(*(a+i)+j) 

86 指向数组的指针作函数参数 指向数组的指针可用作函数的形参和实参,其目的是向函数传送数组的地址

87 例2-18 用选择排序法对n个整数排序(降序)。
#include<iostream.h> #const int N=8; void sort(int x[], int n); void main() { int a[N], i; for(i=0; i<N; i++) //从键盘上输入数据 cin>>a[i]; sort(a,N); //用选择排序法排序 for(i=0; i<N; i++) //输出排序结果 cout<<a[i]; }

88 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<n; j++) //内循环:选出本次的最大元素 if(x[j]>x[k]) k=j; //存在更大元素,保存其下标 if(k!=i) //存在更大元素,交换 { t=x[i]; x[i]=x[k]; x[k]=t; } } 运行情况为:

89 指 针 指针数组 数组的元素是指针型 例:Point *pa[2]; //利用指针数组输出单位矩阵
指 针 //利用指针数组输出单位矩阵 #include <iostream.h> void main( ) { int line1[ ]={1,0,0}; //声明数组,矩阵的第一行 int line2[ ]={0,1,0}; //声明数组,矩阵的第二行 int line3[ ]={0,0,1}; //声明数组,矩阵的第三行 int *p_line[3]; //声明整型指针数组 p_line[0]=line1; //初始化指针数组元素 p_line[1]=line2; p_line[2]=line3;

90 cout<<"Matrix test:"<<endl;
//输出单位矩阵 cout<<"Matrix test:"<<endl; for(int i=0;i<3;i++) //对指针数组元素循环 { for(int j=0;j<3;j++) //对矩阵每一行循环 { cout<<p_line[i][j]<<" "; } cout<<endl; } 输出结果为: Matrix test: 1,0,0 0,1,0 0,0,1

91 2.7.5 动态内存分配和释放 P48 2.动态对象数组的创建与撤消 1.单个动态对象的创建与撤消
new T(初始值列表) //返回值为创建对象的指针值(地址) delete 堆对象指针; 结果值:成功:T类型的指针,指向新分配的内存。失败:0(NULL) 2.动态对象数组的创建与撤消 new T[E] //T-数据类型,E-运算表达式 delete[] 堆对象指针 malloc与free是C中的函数,在C++中仍可使用,new和free是C++中新增的操作符。 将动态存储分配功能设计为操作符,原因是: 1)非常重要,使用频繁 2)可以进行运算符重载,任何类都可以声明自己的new和delete 版本,增加了程序的灵活性。 (运算符重载下一讲再讲)

92 例 动态存储分配举例 int *ptr; //定义一个指针变量
ptr=new int(6); //创建一个初值为6的整形对象,返回该对象的指针值付给指针ptr delete ptr;//删除ptr所指向的堆对象。 int *ptr=new int[20]; //创建一个整形数组, 其中有20个元素,返回数组的指针值赋给指针变量ptr。 delete [] ptr; //撤消上面用new开辟的存放整形数组的空间。 char (*fp)[3]; fp = new char[2][3]; 用new定义二维动态数组,必须先定义一个指向一维数组的指针变量,利用这个指针获得二维动态数组的首地址。

93 2.7.6 指针与函数 指针作为函数参数 #include<iostream.h>
2.7.6 指针与函数 指针作为函数参数 #include<iostream.h> #include"Point.h" //Point 类声明略 void f(Point **a, int n); int main( ) { Point *pa[2]; //动态生成对象,其地址赋给指针数组元素 pa[0]=new Point(1,3); pa[1]=new Point(2,4); f(pa,2); delete pa[0]; delete pa[1]; return 0; }

94 for(int i=0;i<n;i++) cout<<a[i]->GetX( )<<endl; }
void f(Point **a, int n) //实参是指针数组,形参应使用二级指针 //也可以写成 void f(Point *a[ ], int n) { for(int i=0;i<n;i++) cout<<a[i]->GetX( )<<endl; } 运行结果: Constructor called. 1 2 Destructor called.

95 2.7.6 指针与字符串 字符串在内存中的起始地址称为字符串的指针。 1.字符串的表示与引用
指针与字符串 字符串在内存中的起始地址称为字符串的指针。 1.字符串的表示与引用 在C++中,字符串既可以用字符数组表示,也可用字符指针变量来表示; 引用时,既可以逐个字符引用,也可以整体引用,下面我们来看一个例子。 例2-20 信息加密与解密。这个例子主要目的是展示如何用字符指针逐字符访问字符串和整体访问字符串,因此加密与解密算法较为简单,都是使用 “按位异或”的方法。

96 #include<stdio.h>
#include<conio.h> void main() { char buf[80], *p=buf, *msg="Input the string: "; int k; cout<<msg; //通过指针整体输出字符串:显示提示信息 gets(p); //通过指针整体引用字符串:接收输入信息 cout<<"Input the keyword(1--127): "; //提示输入密钥 cin>>k; //接收密钥 for(; *p!='\0'; p++) *p ^= k; //通过指针引用单个字符:信息加密

97 p=buf; cout<<"The encrypted string: \n“<<p<<‘\n’;//通过指针整体输出字符串——密文 cout<<"Press any key to continue...\n"; getch(); for(p=buf; *p!='\0'; p++) *p ^= k; //通过指针引用单个字符:信息解密 cout<<"The Original is: %s\n“<< buf; //通过数组整体输出字符串——明文 } 程序运行情况: Input the string: I am a programer.  Input the keyword(1--127): 31 The encrypted string: V?~r?~?ompxm~rzm1 Press any key to continue... The Original is: I am a programer.

98 2.字符指针变量与字符数组的区别 字符指针和字符数组都能用来存储和处理字符串,但二者有较大区别,见表6.3:

99

100 3.字符型指针和字符型数组作为函数参数有以下几种情况:

101 2.7.6 有关指针的数据类型小结 常用有关指针的数据类型的定义

102 2.8 预处理指令与文件 P57 2.8.1 预处理 C++程序的源代码中可包含各种编译指令,这些指令称为预处理命令
宏定义命令;#define PI 文件包含命令;#include <文件名> #include "文件名" 条件编译命令;三种形式 #if <表达式1> <程序段1> [#elif <表达式2> <程序段2> …] [#else <程序段n>] #endif #ifdef <标识符> <程序段1> [#else <程序段2> ] #endif #ifndef <标识符> <程序段1> [#else <程序段2> ] #endif

103 2.8 预处理指令与文件 2.8.2 文件 ASCII文件又称文本文件,文本文件中每一个字节用以存放一个字符的ASCII码值 。
文件 ASCII文件又称文本文件,文本文件中每一个字节用以存放一个字符的ASCII码值 。 二进制文件是将数据用二进制形式存放在文件中,它保持了数据在内存中存放的原有格式。 文件指针:总是和一个文件所关联的,当文件每次打开时,文件指针指向文件的开始。

104 2.8 预处理指令与文件 一、顺序文件操作 打开和关闭文件 (使用fstream类的成员函数open和close来实现 #include〈 fstream.h 〉 原型如下:) void open(const char *name,int access, int prot=fliebuf::openprot); //文件名,访问方式,文件的共享方式 void close(); //P61 打开前: fstream file1; // 定义一个fstream类的对象 file1.open(“Ex_File.cpp”,ios::out); // 打开一个文件用于写

105 2.8 预处理指令与文件 一、顺序文件操作 2. 文件的读写 例2-26:将文件内容保存在另一文件中,并将内容显示在屏幕上 (参见P62页)
函数原型 说 明 get(char &ch) 从文件中读取一个字符 getline( char * pch, int count, char delim='\n'); 从文件中读取多个字符,字符个数由count指定,delim是读取字符时指定的结束符 read(char *pch, int count); 从文件中读取多个字符,字符个数由count指定,它非常适用于二进制文件 put(char ch); 向一个文件写入一个字符 write(const char * pch, int count); 向一个文件写入多个字符,字符个数由count指定,它非常适用于二进制文件 例2-26:将文件内容保存在另一文件中,并将内容显示在屏幕上 (参见P62页)

106 2.8 预处理指令与文件 二、随机文件操作 在以随机的方式访问文件时,文件中的信息在逻辑上组织成定长的记录格式。这样就可以通过逻辑的方法,将文件指针直接移动到所读写的数据的起始位置,来读取数据或者将数据直接写到文件的这个位置上。 C++根据具体的读/写操作为用户提供seekg 和seekp函数将文件指针移动到指定的位置,

107 2.8 预处理指令与文件 二、随机文件操作 1. 指针定位 绝对位置 文件读操作 istream &seekg(long pos);
istream&seekg(long off, ios::seek_dir dir); 相对位置 文件写操作 ostream&seekp(long pos); ostream&seekp(long off, ios::seek_dir dir); dir的值及其含义 方 式 含 义 ios::beg 文件开头 ios::cur 文件指针的当前位置 ios::end 文件尾

108 2.8 预处理指令与文件 例2-21:使用seekp指定文件指针的位置P62页 例2-22:学生成绩管理文件操作

109 小结与习题 C++的基本语法(数据类型、常量、变量、表达式) C++流程控制语句(分支、循环、跳转)
构造数据类型(数组、枚举、结构体与联合体) 函数(定义与调用、参数传递、内联、递归、重载) 指针(定义、初始化与使用,指针与数组、指针与字符串、指针与函数 应能编写较复杂的C++程序,熟悉基本输入输出和简单算法设计(如学生成绩管理,常用算法设计)

110 小结与习题 思考题:P65 3、4、6、8、9、12 编程题:7、14、15 上机题:验证例题和习题;项目单1

111


Download ppt "VC++系统开发 第二章 C++语言基础 河北经贸大学信息技术学院."

Similar presentations


Ads by Google