C++语言程序设计 第六章 数组 指针与字符串.

Slides:



Advertisements
Similar presentations
C++语言程序设计教程 第5章 构造数据类型 第6章 C++程序的结构.
Advertisements

移动应用软件开发技术 第二讲:C++编程基础
电子成绩单项目实现.
第一章 C语言概述 计算机公共教学部.
第5章 指 针 教学目标: 掌握指针定义、初始化方法和基本运算; 掌握利用指针访问一维数组、二维数组的方法;
高级语言程序设计 C++程序设计教程(下) 2006年春季学期 与一些教材的区别 偏重理论,不去讨论某个系统的具体使用方法,但会涉及实现技术
VC++系统开发 第二章 C++语言基础 河北经贸大学信息技术学院.
第4章 数组 数组是由一定数目的同类元素顺序排列而成的结构类型数据 一个数组在内存占有一片连续的存储区域 数组名是存储空间的首地址
第六讲 指针与字符串 —— 为什么指针 —— 持久动态内存分配 —— 字符串(字符数组).
第六章 数 组 主讲教师 贾月乐 联系电话:
資料大樓 --談指標與陣列 綠園.
内容提要 对象的生命周期 构造函数 析构函数 拷贝构造函数. 常宝宝 北京大学计算机科学与技术系
C++语言程序设计 第四章 类与对象 成都信息工程学院计算机系.
C++程序设计 第二讲 清华大学软件学院.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
新世纪计算机专业系列教材 数据结构 C++实现 第一章 缪淮扣 顾训穰 沈 俊 编著 科 学 出 版 社.
Introduction to the C Programming Language
第3章 继承和派生.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Object-Oriented Programming in C++ 第一章 C++的初步知识
第三章 C++中的C 面向对象程序设计(C++).
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
Chap 8 指针 8.1 寻找保险箱密码 8.2 角色互换 8.3 冒泡排序 8.4 电码加密 8.5 任意个整数求和*
第五章 指针 5.1 指针的概念和定义 5.2 指针运算 5.3 指针和数组 5.4 字符串指针 5.5 指针数组 5.6 指向指针的指针
第二章 C++对C 在非面向对象方面的改进 更简洁,更安全.
第3讲 C++程序控制结构 3.1 顺序结构 3.2 分支结构 3.3 循环结构 3.4 转向控制 3.5 综合案例分析.
C++语言程序设计 第六章 数组 指针与字符串 清华大学 郑 莉.
C++语言程序设计 第二章 C++简单程序设计.
程序的三种基本结构 if条件分支语句 switch多路开关语句 循环语句 循环嵌套 break,continue和goto语句
第八章 使用指针.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
切換Dev c++顯示語言 工具->環境選項(V)->介面->language (Chinese TW)
Introduction to the C Programming Language
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
C++大学基础教程 第5章 数组 北京科技大学 信息基础科学系.
C++大学基础教程 第3章 C++控制语句 北京科技大学 信息基础科学系.
C语言概述 第一章.
C语言复习3----指针.
第 二 章 数据类型、运算符与表达式.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第三章 控制语句 第十一组 C++语言程序设计.
第10讲 构造函数和析构函数 构造函数 析构函数 This 指针.
C语言大学实用教程 第6章 数组 西南财经大学经济信息工程学院 刘家芬
Introduction to the C Programming Language
Oop8 function函式.
第六章 指针 C++程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
第十四章 若干深入问题和C独有的特性 作业: 函数指针 函数作参数 函数副作用 运算 语句 位段 存储类别 编译预处理
第三章 数据抽象.
C++语言程序设计教程 第2章 数据类型与表达式 第2章 数据类型与表达式 制作人:杨进才 沈显君.
C程序设计.
C++程式設計入門 變數與運算子 作者:黃建庭.
第二章 基本数据类型 ——数据的表示.
第二讲 基本数据类 型及数组等 此为封面页,需列出课程编码、课程名称和课程开发室名称。
C/C++基礎程式設計班 C++: 物件的使用、參考、重載函式 講師:林業峻 CSIE, NTU 3/28, 2015.
第 9 章 建構函式與解構函式.
C程序设计.
第 3 章 类的基础部分 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
挑戰C++程式語言 ──第9章 函數.
#include <iostream.h>
本章主題 C++的程式結構 資料型態與宣告 算術運算 簡易的輸入輸出指令 程式編譯(Compile)的過程與原理.
《数据结构与算法设计》第一部分 面向对象的C++程序设计基础.
Introduction to the C Programming Language
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
第9章 C++程序设计初步 9.1 C++的特点 9.2 最简单的C++程序 9.3 C++的输入输出 9.4 函数的重载
變數與資料型態  綠園.
第六章 复合数据类型 指针的声明与使用 数组的声明与使用 指针与数组的相互引用 字符串及相关库函数 new与delete
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
Presentation transcript:

C++语言程序设计 第六章 数组 指针与字符串

本章主要内容 数组 指针 动态存储分配 指针与数组 指针与函数 字符串

数组的概念 数 组 数组是具有一定顺序关系的若干相同类型变量的集合体,组成数组的变量称为该数组的元素。 数组属于构造类型。

例6. 1 一维数组的声明与引用 数 组 #include <iostream.h> void main( ) { 数 组 #include <iostream.h> void main( ) { int A[10],B[10]; int i; for(i=0;i<10;i++) A[i]=i*2-1; B[10-i-1]=A[i]; } for(i=0;i<10;i++) { cout<<"A["<<i <<"]="<<A[i]; cout<<" B["<<i <<"]=" <<B[i]<<endl; }

一维数组的存储顺序 数 组 例如:具有10个元素的数组 a,在内存中的存放次序如下: a 数组元素在内存中顺次存放,它们的地址是连续的。 数 组 数组元素在内存中顺次存放,它们的地址是连续的。 例如:具有10个元素的数组 a,在内存中的存放次序如下: a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] a 数组名字是数组首元素的内存地址。 数组名是一个常量,不能被赋值。

一维数组的初始化 数 组 可以在编译阶段使数组得到初值: 数 组 可以在编译阶段使数组得到初值: 在声明数组时对数组元素赋以初值。 例如: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}

例6-2 :用数组来处理求Fibonacci数列问题 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) printf("\n"); printf("%12d",f[i]); } } 运行结果: 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765

例6-3 一维数组应用举例 数 组 本例循环从键盘读入若干组选择题答案,计算并输出每组答案的正确率,直到输入ctrl+z为止。 数 组 本例循环从键盘读入若干组选择题答案,计算并输出每组答案的正确率,直到输入ctrl+z为止。 每组连续输入5个答案,每个答案可以是'a'..'d'。

#include <iostream.h> void main(void) { char key[ ] = {'a','c','b','a','d'}; char c; int ques = 0, numques = 5, numcorrect = 0; cout << "Enter the " << numques << " question tests:" << endl;;

while (cin.get(c)) { if (c != '\n') if (c == key[ques]) { numcorrect++; cout << " "; } else cout << "*"; else { cout<< " Score " <<float(numcorrect)/numques*100<< "%"; ques = 0; // reset variables numcorrect = 0; cout << endl; continue; ques++;

运行结果: acbba ** Score 60% acbad Score 100% abbda * ** Score 40% bdcba ***** Score 0%

二维数组的声明及引用 数 组 例: int a[5][3]; 数 组 数据类型 标识符[常量表达式1][常量表达式2] …; 例: int a[5][3]; 表示a为整型二维数组,其中第一维有5个下标(0~4),第二维有3个下标(0~2),数组的元素个数为15,可以用于存放5行3列的整型数据表格。

二维数组的声明及引用 数 组 二维数组的声明 存储顺序 引用 类型说明符 数组名[常量表达式][常量表达式] 数 组 二维数组的声明 类型说明符 数组名[常量表达式][常量表达式] 例如: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 下标不要越界

二维数组的初始化 数 组 分行给二维数组赋初值 将所有数据写在一个{}内,按顺序赋值 可以对部分元素赋初值 二维数组程序举例: 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}};

数组作为函数参数 数 组 数组元素作实参,与单个变量一样。 数 组 数组元素作实参,与单个变量一样。 数组名作参数,形、实参数都应是数组名,类型要一样,传送的是数组首地址。对形参数组的改变会直接影响到实参数组。

例6-4 使用数组名作为函数参数 数 组 主函数中初始化一个矩阵并将每个元素都输出,然后调用子函数,分别计算每一行的元素之和,将和直接存放在每行的第一个元素中,返回主函数之后输出各行元素的和。

#include <iostream.h> void RowSum(int A[ ][4], int nrow) { int sum; for (int i = 0; i < nrow; i++) { sum = 0; for(int j = 0; j < 4; j++) sum += A[i][j]; cout << "Sum of row " << i << " is " << sum << endl; }

void main(void) { int Table[3][4] = {{1,2,3,4},{2,3,4,5},{3,4,5,6}}; for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) cout << Table[i][j] << " "; cout << endl; } RowSum(Table,3);

运行结果: 1 2 3 4 2 3 4 5 3 4 5 6 Sum of row 0 is 10 Sum of row 1 is 14 Sum of row 2 is 18

对象数组 数 组 声明: 类名 数组名[元素个数]; 访问方法: 通过下标访问 数组名[下标].成员名

对象数组初始化 数 组 数组中每一个元素对象被创建时,系统都会调用类构造函数初始化该对象。 通过初始化列表赋值。 数 组 数组中每一个元素对象被创建时,系统都会调用类构造函数初始化该对象。 通过初始化列表赋值。 例: Point A[2]={Point(1,2),Point(3,4)}; 如果没有为数组元素指定显式初始值,数组元素便使用缺省值初始化(调用缺省构造函数)。

数组元素所属类的构造函数 数 组 不声明构造函数,则采用缺省构造函数。 各元素对象的初值要求为相同的值时,可以声明具有缺省形参值的构造函数。 数 组 不声明构造函数,则采用缺省构造函数。 各元素对象的初值要求为相同的值时,可以声明具有缺省形参值的构造函数。 各元素对象的初值要求为不同的值时,需要声明带形参(无缺省值)的构造函数。 当数组中每一个对象被删除时,系统都要调用一次析构函数。

例6-5 对象数组应用举例 数 组 //Location.h #if !defined(_LOCATION_H) 数 组 //Location.h #if !defined(_LOCATION_H) #define _LOCATION_H class Location { public: Location( ); Location(int xx,int yy); ~Location( ); void Move(int x,int y); int GetX( ) {return X;} int GetY( ) {return Y;} private: int X,Y; }; #endif

#include<iostream.h> #include "Location.h" Location::Location( ) //6-5.cpp #include<iostream.h> #include "Location.h" Location::Location( ) { X=Y=0; cout<<"Default Constructor called."<<endl; } Location::Location(int xx,int yy) { X=xx; Y=yy; cout<< "Constructor called."<<endl; 构造函数的实现

Locatuon::~Location( ) { cout<<"Destructor called."<<endl; } void Location::Move(int x,int y) X=x; Y=y; 析构函数的实现

cout<<"Entering main..."<<endl; Location A[2]; int main( ) { cout<<"Entering main..."<<endl; Location A[2]; for(int i=0;i<2;i++) A[i].Move(i+10,i+20); cout<<"Exiting main..."<<endl; return 0; } 声明数组时调用缺省构造函数 程序结束时自动删除数组元素,调用析构函数 注意成员函数的调用形式

Default Constructor called. Exiting main... Destructor called. 运行结果: Entering main... Default Constructor called. Exiting main... Destructor called.

关于内存地址 内存空间的访问方式 地址运算符:& 通过变量名访问 通过地址访问 例: int var; 则&var 表示变量var在内存中的起始地址

指针变量的概念 指 针 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

指针变量的初始化 指 针 语法形式 存储类型 数据类型 *指针名=初始地址; 例: int *pa=&a; 注意事项 指 针 语法形式 存储类型 数据类型 *指针名=初始地址; 例: int *pa=&a; 注意事项 用变量地址作为初值时,该变量必须在指针初始化之前已说明过,且变量类型应与指针类型一致。 可以用一个已赋初值的指针去初始化另一 个指针变量。 不要用一个内部 auto 型变量去初始化 static 型指针。

指针变量的赋值运算 指 针 指针名=地址 “地址”中存放的数据类型与指针类型必须相符。 指 针 指针名=地址 “地址”中存放的数据类型与指针类型必须相符。 向指针变量赋的值必须是地址常量或变量,不能是普通整数。但可以赋值为整数0,表示空指针。 指针的类型是它所指向变量的类型,而不是指针本身数据值的类型,任何一个指针本身的数据值都是unsigned long int型。 允许声明指向 void 类型的指针。该指针可以被赋予任何类型对象的地址。 例: void *general;

例6-6 指针的声明、赋值与使用 指 针 #include<iostream.h> void main( ) 指 针 #include<iostream.h> void main( ) { int *i_pointer; //声明int型指针i_pointer int i; //声明int型数i i_pointer=&i; //取i的地址赋给i_pointer i=10; //int型数赋初值 cout<<"Output int i="<<i<<endl; //输出int型数的值 cout<<"Output int pointer i="<<*i_pointer<<endl; //输出int型指针所指地址的内容 }

程序运行的结果是: Output int i=10 Output int pointer i=10

例6-7 void类型指针的使用 指 针 void vobject; //错,不能声明void类型的变量 指 针 void vobject; //错,不能声明void类型的变量 void *pv; //对,可以声明void类型的指针 int *pint; int i; void main( ) //void类型的函数没有返回值 { pv = &i; //void类型指针指向整型变量 // void指针赋值给int指针需要类型强制转换: pint = (int *)pv; }

指针变量的算术运算 指 针 指针与整数的加减运算 指针加一,减一运算 指 针 指针与整数的加减运算 指针 p 加上或减去 n ,其意义是指针当前指向位置的前方或后方第 n 个数据的地址。 这种运算的结果值取决于指针指向的数据类型。 指针加一,减一运算 指向下一个或前一个数据。 例如:y=*px++ 相当于 y=*(px++) (*和++优先级相同,自右向左运算)

pa-2 pa-1 pa+1 pa+2 pa+3 *(pa-2) *pa *(pa+1) *(pa+2) *(pa+3) *(pa-1) short *pa pa

pb-1 long *pb *(pb-1) pb *pb pb+1 *(pb+1) pb+2 *(pb+2)

指针变量的关系运算 指 针 关系运算 赋值运算 指向相同类型数据的指针之间可以进行各种关系运算。 指 针 关系运算 指向相同类型数据的指针之间可以进行各种关系运算。 指向不同数据类型的指针,以及指针与一般整数变量之间的关系运算是无意义的。 指针可以和零之间进行等于或不等于的关系运算。例如:p==0或p!=0 赋值运算 向指针变量赋的值必须是地址常量或变量,不能是普通整数。但可以赋值为整数0,表示空指针。

指向数组元素的指针 指 针 声明与赋值 通过指针引用数组元素 例: 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是数组首地址是常量。

例6-8 指 针 设有一个int型数组a,有10个元素。用三种方法输出各元素: 使用数组名和下标 使用数组名和指针运算 使用指针变量

使用数组名和下标 main( ) { int a[10]; int i; for(i=0; i<10; i++) cin>>a[i]; cout<<endl; cout<<a[i]; }

使用数组名指针运算 main( ) { int a[10]; int i; for(i=0; i<10; i++) cin>>a[i]; cout<<endl; cout<<*(a+i); }

使用指针变量 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; }

指针数组 指 针 数组的元素是指针型 例:Point *pa[2]; 由pa[0],pa[1]两个指针组成

例6-9 利用指针数组输出单位矩阵 指 针 #include <iostream.h> void main( ) 指 针 #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;

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

例6-10 二维数组举例 指 针 #include <iostream.h> void main( ) 指 针 #include <iostream.h> void main( ) { int array2[2][3]={{11,12,13},{21,22,23}}; for(int i=0;i<2;i++) { cout<<*(array2+i)<<endl; for(int j=0;j<3;j++) { cout<<*(*(array2+i)+j)<<" "; } cout<<endl; }

在某次运行之后,程序的输出结果为: 0X0065FDE0 11,12,13 0X0065FDEC 21,22,23

指针与常量 —指向常量的指针 指 针 不能通过指针来改变所指对象的值,但指针本身可以改变,可以指向另外的对象。例: int n1=3; 指针与常量 —指向常量的指针 指 针 不能通过指针来改变所指对象的值,但指针本身可以改变,可以指向另外的对象。例: int n1=3; int const n2=5; const int *pn= &n1; pn=&n2; //正确 *pn=6; //错误

指针与常量 —指针常量 若声明指针常量,则指针本身的值不能被改变。例: int n1=3; int const n2=5; 指针与常量 —指针常量 若声明指针常量,则指针本身的值不能被改变。例: int n1=3; int const n2=5; int *const pn= &n1; pn=&n2; //错误 *pn=6; //正确

例6-11 指针应用举例 指 针 #include <iostream.h> int main( ) { 指 针 #include <iostream.h> int main( ) { int *pt_int; float *pt_float; int pig = 7, dog = 27; float x = 1.2345, y = 32.14; void *general;

pt_int = &pig; *pt_int += dog; cout << "Pig now has the value of " << *pt_int << "\n"; general = pt_int; //指向int型的指针赋值给void型指针 pt_float = &x; y += 5 * (*pt_float); cout << "y now has the value of " << y << "\n"; general = pt_float; //指向float型的指针赋值给void型指针

const char *name1 = "John"; //指向常量的指针,所指对象之值不能改变 char *const name2 = "John"; //常量指针,指针本身不能被改变 return 0; } 运行结果: Pig now has the value of 34 y now has the value of 38.3125

例6-12 指向常量的指针做形参 指 针 #include<iostream.h> const int N=6; 指 针 #include<iostream.h> const int N=6; void print(const int *p,int n); void main( ) { int array[N]; for(int i=0;i<N;i++) cin>>array[i]; print(array,N); }

void print(const int *p, int n) { cout<<"{"<<*p; for(int i=1;i<n;i++) cout<<"."<<*(p+i); cout<<"}"<<endl; }

指向类类型对象的指针 指 针 声明形式 例 通过指针访问对象成员 类名 *对象指针名; Point A(5,10); Piont *ptr; 指 针 声明形式 类名 *对象指针名; 例 Point A(5,10); Piont *ptr; ptr=&A; 通过指针访问对象成员 对象指针名->成员名

例6-13 对象指针应用举例 指 针 int main( ) { Point A(5,10); Point *ptr; ptr=&A; 指 针 int main( ) { Point A(5,10); Point *ptr; ptr=&A; int x; x=ptr->GetX( ); cout<<x<<endl; return 0; }

动态申请内存操作符 new 动态存储分配 new 类型名T(初值列表) 结果值:成功:T类型的指针,指向新分配的内存。失败:0(NULL) malloc与free是C中的函数,在C++中仍可使用,new和free是C++中新增的操作符。 将动态存储分配功能设计为操作符,原因是: 1)非常重要,使用频繁 2)可以进行运算符重载,任何类都可以声明自己的new和delete 版本,增加了程序的灵活性。 (运算符重载下一讲再讲)

释放内存操作符delete 动态存储分配 delete 指针P 功能:释放指针P所指向的内存。P必须是new操作的返回值。

例6-14 动态存储分配举例 动态存储分配 #include <iostream.h> struct date { int month; int day; int year; };

int main( ) { int index, *point1, *point2; point1 = &index; *point1 = 77; point2 = new int; *point2 = 173; cout << "The values are " << index << " " << *point1 << " " << *point2 << "\n"; delete point2; point1 = new int; point2 = point1; *point1 = 999; cout << "The values are " << index << " " <<*point1 << " " << *point2 << "\n"; delete point1;

float *float_point1, *float_point2 = new float; delete float_point2; delete float_point1;

date *date_point; date_point = new date; //动态分配结构体 date_point->month = 10; date_point->day = 18; date_point->year = 1938; cout << date_point->month << "/" << date_point->day << "/" <<date_point->year << "\n"; delete date_point; //释放结构体

char *c_point; c_point = new char[37]; //动态分配数组 delete [ ] c_point; //释放数组 c_point = new char[sizeof(date) + 133]; //动态分配数组 delete [ ] c_point; //释放数组 return 0; } 运行结果: The values are 77 77 173 The values are 77 999 999 10/18/1938

动态分配数组时应注意: 用new创建多维数组: new 类型名T[下标表达式1][下标表达式2]…; 如果内存申请成功,new运算返回一个指向新分配内存首地址的指针,是一个T类型的数组,数组元素的个数为除最左边一维外各位下标表达式的乘积。例如: char (*fp)[3]; fp = new char[2][3];

例6-15 动态创建对象举例 动态存储分配 #include<iostream.h> class Point { public: { X=Y=0; cout<<"Default Constructor called.\n";} Point(int xx,int yy); { X=xx; Y=yy; cout<< "Constructor called.\n"; } ~Point( ) { cout<<"Destructor called.\n"; } int GetX( ) {return X;} int GetY( ) {return Y;} void Move(int x,int y) { X=x; Y=y; } private: int X,Y; };

{ cout<<"Step One:"<<endl; Point *Ptr1=new Point; int main( ) { cout<<"Step One:"<<endl; Point *Ptr1=new Point; delete Ptr1; cout<<"Step Two:"<<endl; Ptr1=new Point(1,2); delete Ptr1; return 0; } 运行结果: Step One: Default Constructor called. Destructor called. Step Two: Constructor called.

例6-16 动态创建对象数组举例 动态存储分配 #include<iostream.h> class Point { //类的声明同例6-16,略 }; int main( ) { Point *Ptr=new Point[2]; //创建对象数组 Ptr[0].Move(5,10); //通过指针访问数组元素的成员 Ptr[1].Move(15,20); //通过指针访问数组元素的成员 cout<<"Deleting..."<<endl; delete[ ] Ptr; //删除整个对象数组 return 0; }

运行结果: Default Constructor called. Deleting... Destructor called.

例6-17 动态创建多维数组 动态存储分配 #include<iostream.h> void main( ) { float (*cp)[9][8]; int i,j,k; cp = new float[8][9][8]; for (i=0; i<8; i++) for (j=0; j<9; j++) for (k=0; k<9; k++) *(*(*(cp+i)+j)+k)=i*100+j*10+k; //通过指针访问数组元素

for (i=0; i<8; i++) { for (j=0; j<9; j++) { for (k=0; k<8; k++) //将指针cp作为数组名使用, //通过数组名和下标访问数组元素 cout<<cp[i][j][k]<<" "; cout<<endl; }

动态存储分配函数 动态存储分配 void *malloc( size ); 参数size:欲分配的字节数 头文件: <stdlib.h> 和 <malloc.h> malloc: 参数size:欲分配的字节数 返回值: 成功,则返回void型指针,指向新分配内存 的首地址。 失败(没有足够内存),则返回空指针。 注意:若申请内存成功,分配的字节数至少为 size,也可能会大一些。 头文件:<stdlib.h> 和 <malloc.h> free: 注意:用free释放的内存必须是先前用malloc分配的。 同一内存只能释放一次,重复释放会出错。

动态内存释放函数 动态存储分配 void free( void *memblock ); 参数memblock: 指针,指向需释放的 内存。 返回值:无 头文件:<stdlib.h> 和 <malloc.h>

以指针作为函数参数 指针与函数 以地址方式传递数据,可以用来返回函数处理结果。 实参是数组名时形参可以是指针。

例6-18 指针做函数参数举例 指针与函数 #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; }

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.

例6.19 指针与函数 题目:读入三个浮点数,将整数部分和小数部分分别输出 #include <iostream.h> void splitfloat(float x, int *intpart, float *fracpart) { //形参intpart、 fracpart是指针 *intpart = int(x); // 取x的整数部分 *fracpart = x - *intpart; //取x的小数部分 }

void main(void) { int i, n; float x, f; cout << "Enter three (3) floating point numbers" << endl; for (i = 0; i < 3; i++) cin >> x; splitfloat(x,&n,&f); //变量地址做实参 cout << "Integer Part is " << n << " Fraction Part is " << f << endl; }

运行结果: Enter three (3) floating point numbers 4.7 Integer Part is 4 Fraction Part is 0.7 8.913 Integer Part is 8 Fraction Part is 0.913 -4.7518 Integer Part is -4 Fraction Part is -0.7518

例6-20 输出数组元素的内容和地址 指针与函数 #include <iostream.h> 例6-20 输出数组元素的内容和地址 指针与函数 #include <iostream.h> #include <iomanip.h> void Array_Ptr(long *P, int n) { int i; cout << "In func, address of array is " << unsigned long(P) << endl; cout << "Accessing array in the function using pointers" << endl; for (i = 0; i < n; i++) { cout << " Address for index " << i << " is " << unsigned long(P+i); cout << " Value is " << *(P+i) << endl; }

void main(void) { long list[5] = {50, 60, 70, 80, 90}; cout << "In main, address of array is " << unsigned long(list) << endl; cout << endl; Array_Ptr(list,5); }

运行结果: In main, address of array is 6684132 In func, address of array is 6684132 Accessing array in the function using pointers Address for index 0 is 6684132 Value is 50 Address for index 1 is 6684136 Value is 60 Address for index 2 is 6684140 Value is 70 Address for index 3 is 6684144 Value is 80 Address for index 4 is 6684148 Value is 90

指针型函数 指针与函数 当函数的返回值是地址时,该函数就是指针形函数。 声明形式 存储类型 数据类型 *函数名( )

指向函数的指针 指针与函数 声明形式 存储类型 数据类型 (*函数指针名)( ); 含义: 存储类型 数据类型 (*函数指针名)( ); 含义: 数据指针指向数据存储区,而函数指针指向的是程序代码存储区。

例6-21 函数指针 指针与函数 #include <stdio.h> void print_stuff(float data_to_ignore); void print_message(float list_this_data); void print_float(float data_to_print); void (*function_pointer)(float); int main( ) { float pi = 3.14159; float two_pi = 2.0 * pi;

print_stuff(pi); function_pointer = print_stuff; function_pointer(pi); function_pointer = print_message; function_pointer(two_pi); function_pointer(13.0); function_pointer = print_float; print_float(pi); return 0; }

void print_stuff(float data_to_ignore) { printf("This is the print stuff function.\n"); } void print_message(float list_this_data) printf("The data to be listed is %f\n", list_this_data); void print_float(float data_to_print) printf("The data to be printed is %f\n", data_to_print);

运行结果: This is the print stuff function. The data to be listed is 6.283180 The data to be listed is 13.000000 The data to be printed is 3.141590

用字符数组存储和处理字符串 字符串 字符数组的声明和引用 例6-19 例6-20 字符串 字符串常量,例如:"china" 没有字符串变量,用字符数组来存放字符串 字符串以'\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";

用字符数组存储和处理字符串 字符串 注意!若有如下声明: char a[4], *p1, *p2; 错误的: a="abc"; cin>>p1; 正确的: p1="abc"; p2=a; cin>>p2;

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

例如: 程序中有下列语句: 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

整行输入字符串 字符串 cin.getline(字符数组名St, 字符个数N, 结束符); 功能:一次连续读入多个字符(可以包括空格),直到读满N个,或遇到指定的结束符(缺省为'\n')。读入的字符串存放于字符数组St中。读取但不存储结束符。 cin.get(字符数组名St, 字符个数N, 结束符); 功能:一次连续读入多个字符(可以包括空格),直到读满N个,或遇到指定的结束符(缺省为'\n')。读入的字符串存放于字符数组St中。 既不读取也不存储结束符。

例6-22 整行输入字符串举例 字符串 #include <iostream.h> void main (void) { char city[80]; char state[80]; int i; for (i = 0; i < 2; i++) { cin.getline(city,80,','); cin.getline(state,80,'\n'); cout << "City: " << city << " State: " << state << endl; }

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

例6.23 string类应用举例 字符串 #include <string> #include <iostream> using namespace std ; void trueFalse(int x) { cout << (x? "True": "False") << endl; }

void main( ) { string S1="DEF", S2="123"; char CP1[ ]="ABC"; char CP2[ ]="DEF"; cout << "S1 is " << S1 << endl; cout << "S2 is " << S2 << endl; cout<<"length of S2:"<<S2.length( )<<endl; cout << "CP1 is " << CP1 << endl; cout << "CP2 is " << CP2 << endl; cout << "S1<=CP1 returned "; trueFalse(S1<=CP1); cout << "CP2<=S1 returned "; trueFalse(CP2<=S1); S2+=S1; cout<<"S2=S2+S1:"<<S2<<endl; }

作业 复习第六章,预习第七章 6-22~6-25 实验六