第21章 指针 三 实例演练与提高.docx
《第21章 指针 三 实例演练与提高.docx》由会员分享,可在线阅读,更多相关《第21章 指针 三 实例演练与提高.docx(16页珍藏版)》请在冰豆网上搜索。
第21章指针三实例演练与提高
第二十一章指针三实例演练与提高
21.1简单变量、数组、指针
21.2小王成绩管理系统V2.0的问题
21.2.1软件升级历史
21.3指针的最常用用法
21.3.1分配内存
21.3.2访问指针指向的内存
21.4小王成绩管理系统V3.0
21.5字符串指针
21.5.1为字符串分配指定大小的空间
21.5.2字符串常用函数
21.5.2.1字符串比较
21.5.2.2字符串复制
21.6指针数组
21.6.1什么叫“指针数组”?
21.6.2指针数组实例一
21.6.3指针数组实例二
21.6.4字符串指针数组
21.1简单变量、数组、指针
学习的知识点越来越多了……
刚开始会觉得很兴奋啊,学得越多越好嘛。
可慢慢的就会感到压力了,各种知识点在头脑里混在一起,每个都变得模糊了。
其实,每个知识点都有它存在,或出现的理由,只要我们多做对比,就会发现学习的知识点越多,反倒越容易理解每个知识点本质。
比如说,简单变量、数组、指针,三者都是C++中用于表达数据的工具,但在表达能力上,又各有不同。
如果用建筑上的房间来比喻:
简单变量是一间房屋。
优点是占用空间少,建筑时间短,缺点是一间房子只适于住一个人;
数组是房间数固定的一排房子,每个房子里头同样只住一人,但由于它有多间,所以适于多人居住,优点是可以统一管理多人,缺点一来是占用空间大,二来房间数一旦确定,就不能改变了。
先头盖了10间,如果如果来了11个人,就有一人住不下,如果来了9个人,就有一间浪费。
指针呢……它不是实际房子,而是设计纸上的房子。
因此,它首先有一个特点:
如果你想让指针存储数据,那一定得先为它分配内存。
这就像光有一张设计蓝图是解决不了四代同堂的问题的,重要的是你还得根据这张蓝图,去找块地皮盖好房子。
指针的优点是可以临时决定要盖多少间房子。
下面我们回顾一个例子,以理解三者的不同用处。
21.2小王成绩管理系统V2.0的问题
先回顾一下该程序的升级过程,今天我们将对它做出两种不同方向的改进。
21.2.1软件升级历史
V1.0:
本版成绩管理系统实现让计算机自动统计6个班级的成绩总分和平均分。
V2.0:
经过改进,本版可以实现多达5000个学生的成绩进行求总分和平均分,并且可以支持用户输入序号,查询任意一个学生的成绩!
在第一版,小王正在学习“循环流程”。
通过在每次循环中,让用户输入一个成绩,然后保存在一个简单变量里,并累加到另一个简单变量,最终计算出总分和平均分。
第二版,由于段长要求不仅可以统计5000个学员的成绩,而且应实现成绩查询功能,这就要求程序必须同时记下5000个学生成绩。
小王先是想用5000个简单变量来记下成绩——这显然太不实际了,后来学到数组,用数组轻松解决了这个问题,因为数组正是为“同时存储多个相同类型的变量”这一问题来设计的。
然而,第二版存在的不足也是显然易见的。
那就是,它固定只能处理最多5000个学员的成绩。
假想,这个软件要推广到全市300个学校,每个学校的学生总数都是不一样的,更惨的是每一年,一个学校的学生个数总是会有变化。
难道就让我们的王老师时不时地改它的程序?
在没有指针时,惟一办法就是,浪费一点,比如定义数组元素个数为1万。
目的是宁可浪费一点,也尽量不要出现不够的情况。
显然,本办法只能算是一个无奈之举。
难道就没有一个办法,即可以适应某个山区小学只有30名学员也情况,又可以轻松对付某大学高达2万名学员的情况?
锣声响起,锵锵锵……指针出场了。
指针是如何完成这一历史使命?
带着问题,我们来学习下面的内容。
我们会在学习新内容之中,同时有选择地做一些旧知识点的复习工作。
但如果你仍看不懂下面的一些代码,那得全面复习前两章的指针内容;或者,如果你连for都有些陌生,那你得重温一下小王成绩管理系统的前两个版本。
21.3指针的最常用用法
21.3.1分配内存
如何为指针分配和释放内存,上一章的内容中讲到了C++独用的new/delete、new[]/delete[]和C使用的malloc,realloc/free方法。
如果你忘了,请先复习。
我们这里使用C++的方法演练。
new只能为我们分配一个简单变量的内存,就是说new只盖了一间房子。
new[]才能为我们盖出一排的房子。
例子:
int*p;//定义一个整型指针
p=new[10]; //new[]为我们分配出10个int大小的内存。
(盖了10间房,每间住一个整数)
21.3.2访问指针指向的内存
前面:
p=new[10];为我们分配了10个int,那么,我们该如何设置和访问这10个整数的值呢?
这一点完全和数组一致,我们来看数组是如何操作:
inta[10];//以数组方式来定义10个int
//让第1个整数的值为100:
a[0]=100;
//让第2个整数的值为80:
a[1]=80;
指针的操作方式如下:
int*p=newint[10];//定义1个整型指针,并为它分配出10个int的空间
//让第1个整数的值为100:
p[0]=100;
//让第2个整数的值为80:
p[1]=80;
对比以上两段代码,你可以发现,对指针分配出的元素操作,完全和对数组的元素操作一致。
不过,指针还有另一种对其元素的操作方法:
int*p=newint[10];//定义1个整型指针,并为它分配出10个int的空间
//让第1个整数的值为100:
*(p+0)=100;
//让第2个整数的值为80:
*(p+1)=80;
请大家自己对比,并理解。
如果觉得困难,请复习第19章关于*的用法,和指针偏移部分的内容。
21.4小王成绩管理系统V3.0
3.0版的最重要的改进就是:
用户可以事先指定本校的学生总数。
请仔细看好。
//定义一个指针,用于存入未知个数学生的成绩:
int*pCj;
//总成绩,平均成绩:
intzcj=0,pjcj;
//首先,要求用户输入本校学生总数:
intxszs;//学生总数
cout<<"请输入本校学生总数:
";
cin>>xszs;
//万一有调皮用户输入不合法的总数,我们就不处理
if(xszs<=0)
{
cout<<"喂,你想耍我啊?
竟然输入一个是0或负数的学生总数.我不干了!
"< return-1;//退出
}
pCj=newint[xszs];
//仍然可以用我们熟悉的循环来实现输入:
for(inti=0;i{
cout<<"请输入第"<
";
cin>>pCj[i]; //输入数组中第i个元素
//不断累加总成绩:
zcj+=pCj[i];
}
//平均成绩:
pjcj=zcj/xszs;
//输出:
cout<<"总成绩:
"<cout<<"平均成绩:
"<
//下面实现查询:
inti;
do
{
cout<<"请输入您要查询的学生次序号(1~"<";
cin>>i;
if(i>=1&&i<=xszs)
{
cout<为什么索引是i-1,而不是i?
}
elseif(i!
=0)
{
cout<<"您的输入有误!
"< }
}
while(i!
=0); //用户输入数字0,表示结束。
//最后,要释放刚才分配出的内存:
delete[]pCj;
......
请大家现在就动手,实现小王成绩管理3.0版。
这是本章的第一个重点。
通过该程序,你应该可以记住什么叫“动态分配内存”。
21.5字符串指针
21.5.1为字符串分配指定大小的空间
有必要的话,你应复习一下第16章之第6节:
字符数组。
假设有个老外叫"Mike",以前我们用字符数组来保存,需要指定是5个字符大小的数组:
charname[5]="Mike";
"Mike"长4个字符,为什么要5个字符的空间来保存?
这是因为计算机还需要为字符串最后多保存一个零字符:
'\0'。
用来表示字符串结束了。
在学了指针以后,我们可以用字符串指针来表达一个人的姓名:
char*pname="Mike";
此时,由系统自动为pname分配5个字符的位置,并初始化为"Mike"。
最后一个位置仍然是零字符:
‘\0’。
采用字符串的好处,同样前面所说的,可以在程序中临时决定它的大小(长度)。
比如:
char*pname;
pname=newchar[9];//临时分配9个字符的大小。
除了要记得额外为字符串的结束符'\0'分配一个位置以外,字符串指针并没有和其它指定有太多的不同。
既然讲到字符串,我们就顺带讲几个常用的字符串操作函数
21.5.2字符串常用函数
字符串操作函数的声明都包含在该头文件:
21.5.2.1字符串比较
intstrcmp(constchar*s1,constchar*s2);
比较s1和s2两个字符串,返回看哪个字符串比较大。
对于字母,该比较区分大小写
返回值:
<0 :
s1 0 :
s1==s2;
>0 :
s1>s2;
intstrcmpi(constchar*s1,constchar*s2);
该函数类似于上一函数,只是对于字母,它不区分大小写,比如它认为'A'和'a'是相等的。
要说两个字符串相等不相等,还好理解,比如:
"Borland"和"Borlanb"显然不相等。
不过,字符串之间还有大小之分吗?
对于字母,采用ASCII值来一个个比较。
谁先出现一个ASCII值比较大的字母,谁就是大者。
比如:
"ABCD"比"AACD"大。
如果一直相等,但有长短不一,那就长的大。
比如:
“ABCD”比“ABC”。
记住了,由于在ASCII表里,小写字母比大写字母靠后,所以小写的反倒比大写的大。
比如:
"aBCD"比"ABCD"大啊。
我这里写个例子,看如何比较字符串:
#include
#include
...
intreu=strcmp("ABCD","AACD");
if