为什么用指针输入和输出一维数组指针时总要申明p=a

以下程序用指针实现一维数组的数据输入与输出,请填空并运行。-土地公问答
以下程序用指针实现一维数组的数据输入与输出,请填空并运行。
以下程序用指针实现一维数组的数据输入与输出,请填空并运行。
#include &stdio.h&void main(){ int a[6],i;_____________;for (i=0;i&6;i++)scanf (&%d&,_________);p=a;for (i=0;i&6;i++)printf (&%3d&,___________);printf (&\n&);} 思考:语句p=a;删程序运行结
依填int *p;&a[i]*p++p=a掉p由于未赋值预知值其进行*p操作导致预知结甚至程序崩溃
其它类似问题
其它人正在问的问题用指针??输入一个数组,逆序输出该数组
时间: 17:19:03
&&&& 阅读:153
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&&&&/*
*Copyright(c) 2014 烟台大学计算机学院
*All rights reserved.
* Copyright (c) 2014, 烟台大学计算机学院
* All rights reserved.
* 文件名称:test.cpp
者:杨汉宁
* 完成日期:2014年 12 月 11 日
* 版 本 号:v1.0
* 问题描述:输入一个数组,逆序输出该数组
* 输入描述:输入一个数组
* 程序输出:逆序输出该数组
#include &iostream&
const int N=100;
int main()
int a[N],*p,*q;
for(p=a; p&n+a; p++)
while(p&q)
for(p=a; p&a+n; p++)
cout&&*p&&' ';
标签:&&&&&&&&&&&&&&&原文:http://blog.csdn.net/i__am__legend/article/details/
教程昨日排行
&&国之画&&&& &&&&&&
&& &&&&&&&&&&&&&&
鲁ICP备号-4
打开技术之扣,分享程序人生!利用指针输出一维数组的所有元素_百度知道
利用指针输出一维数组的所有元素
我有更好的答案
#include&stdio.h&#define N 10void main(){ int a[N],i,*p;
for ( i=0;i&N;i++ ) a[i]=i;
for ( i=0,p=a;i&N;i++,p++ ) printf(&%d &,*p); printf(&\n&);}
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。C++语言程序设计 第六章 数组 指针与字符串 本章主要内容数组 ? 指针 ? 动态存储分配 ? 指针与数组 ? 指针与函数 ? 字符串? 数组一维数组 ? 二维数组 ? 高维数组 ? 数组作为函数参数 ? 对象数组? 6.1 数组一个班学生的学习成绩 一行文字 一个矩阵 ? 这些数据的特点是:?1.具有相同的数据类型 ?2.使用过程中需要保留原始数据 6.1 数组数组是具有一定顺序关系的若干相同类型 变量的集合体,组成数组的变量称为该数组的 元素。 数组属于构造类型。可以由除void型以外的任何一种类型构成。 6.1.1 一维数组 ――一维数组的声明和使用一维数组的声明 包括:?? 确定数组的名称 ? 确定数组元素的类型? 确定数组的结构(包括数组维数,每一维的大小)类型说明符 数组名[ 常量表达式 ]; 数组名的构成方法与一般变量名相同。 例如:int a[10];表示 a 为整型数组,有10个元素:a[0]...a[9] 说明:1.数组名定名规则和变量名相同,遵循标识符定名规 则。 2.在定义数组时,需要指定数组中元素的个数,方括 弧中的常量表达式用来表示元素的个数,即数组长度 。3.常量表达式中可以包括常量和符号常量,但不能包 含变量。也就是说,C语言不允许对数组的大小作动 态定义,即数组的大小不依赖于程序运行过程中变量 的值。 例如:scanf(“%d″,&n); int a[n]; 数组说明中其他常见的错误: ① float a[0]; /* 数组大小为0没有意义 */ ② int b(2)(3); /* 不能使用圆括号 */ ③ int k, a[k]; /* 不能用变量说明数组大小*/ /*在程序中临时输入数组的大小 */ 一维数组的引用?使用?必须先声明,后使用。?只能逐个引用数组元素,而不能一次引用整个数组 例如:a[0]=a[5]+a[7]-a[2*3]注意:定义数组时用到的“数组名[常量表达式]” 和引 用数组元素时用到的“数组名[下标]” 是有区别的 。 例如∶ int a[10]; 例6. 1一维数组的声明与引用数 组#include &iostream& int main() {int A[10],B[10]; 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]&& } } 一维数组元素引用的程序实例#include &stdio.h& void main() { int i,a[10]; for (i=0; i&=9;i++) a[i]=i; for(i=9;i&=0; i--) printf(&%d ″,a[i]); printf(&\n″); }运行结果如下: 9 8 7 6 5 4 3 2 1 0程序使a[0]到 a[9]的值为0~9, 然后按逆序输出。 一维数组的存储顺序数 组数组元素在内存中顺次存放,它们的地址是连 续的。例如:具有10个元素的数组 a,在内存 中的存放次序如下: a a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8]a[9]数组名字是数组首元素的内存地址。 数组名是一个常量,不能被赋值。 一维数组在内存中的存放一维数组: float mark[100]; 低地址 每个数据元素占用 的字节数,就是基 类型的字节数 一个元素占4个字节高地址86.5 92.0 77.5 52.0. . .94.0mark[0] mark[1] mark[2] mark[3]. . .mark[99] 一维数组的初始化对数组元素初始化的实现方法: 1.在定义数组时对数组元素赋以初值。 例如:int a[10]={0,1,2,3,4,5,6,7,8,9};将数组元素的初值依次放在一对花括弧内。经过上面的 定义和初始化之后,a[0]=0,a[1]=1,a[2]=2, a[3]=3,a[4]=4,a[5]=5,a[6]=6,a[7]=7, a[8]=8,a[9]=9。 2. 可以只给一部分元素赋值。 例如: int a[10]={0,1,2,3,4}; 定义a数组有10个元素,但花括弧内只提供5个初值, 这表示只给前面5个元素赋初值,后5个元素值为0。 3. 如果想使一个数组中全部元素值为0,可以写成:inta[10]={0,0,0,0,0,0,0,0,0,0};或int a[10]={0}; 不能写成:int a[10]={0*10}; 4. 在对全部数组元素赋初值时,由于数据的个数已经确定,因此可以不指定数组长度。例如:int a[5]={1,2,3,4,5};也可以写成int a[]={1,2,3,4,5};只初始化前5个int a[10]={1,2,3,4,5};元素,后5个元素为0。 一维数组程序举例用数组来处理,求解Fibonacci数列。Fibonacci数列公式:已知: a1=a2=1an=an-1+an-2 即:1,1,2,3,5,8,13程序实例: #include &stdio.h& void main() { int f[20]={1,1}; for(i=2;i&20;i++) f[i]=f[i-2]+f[i-1]; for(i=0;i&20;i++) { if(i%5==0) printf(″\ n″); printf(″%12d″,f[i]) } /*For循环结束*/ } /*程序结束*/ 运行结果如下: 1 1 2 8 13 21 89 144 233 987 if语句用来控 制换行,每行 输出5个数据。3 34 377 41815 55 610 6765 一维数组应用举例循环从键盘读入若干组选择题答案,计算 并输出每组答案的正确率,直到输入ctrl+z为止 。 每组连续输入5个答案,每个答案可以是 'a'..'d'。 #include &iostream& int main() { char key[ ]={'a','c','b','a','d'}; int ques=0,numques=5,numcorrect=0; cout&&&Enter the &&&numques&&& question tests:&&&20 while(cin.get(c)) { if(c != ‘\n’)//内层循环,判断一个学生的一组成绩 if(c == key[ques]) { numcorrect++; cout && & &; } else cout&&&*&; else { cout&&& Score &&&float(numcorrect)/numques*100&&&%&; ques = 0; numcorrect = 0; cout && //结束本次循环,进行下一次循环 } ques++; } }get()是iostream中的成员函数,功能 是从键盘上得到一个字符 运行结果: acbba ** Score 60% acbad Score 100% abbda * ** Score 40% bdcba ***** Score 0%22 6.1.2 二维数组―― 二维数组的声明及使用数 组数据类型 标识符[常量表达式1][常量表达式2] …;例: int a[5][3]; 表示a为整型二维数组,其中第一维有5 个下标(0~4),第二维有3个下标(0~2 ),数组的元素个数为15,可以用于存放 5行3列的整型数据表格。 二维数组的声明及使用数 ? 二维数组的声明 组?类型说明符 数组名[常量表达式][常量表达式]例如:float a[3][4];二维数组的使用例如:b[1][2]=a[2][3]/2下标不要越界 二维数组的存放?存储顺序按行存放,上例中数组a的存储顺序为:例如:float a[3][4];可以理解为: aa[0]――a00 a01 a02 a03 a[1]――a10 a11 a12 a13 a[2]――a20 a21 a22 a23a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23 例如:整型数组 b[3][3]={ {1,2,3}, {4,5,6}, {7,8,9} }; 地址 值 数组元素 3000H b[0][0] 1 3002H b[0][1] 2 b[0][2] 3004H 3H 300AH4 5 6 7 8 9b[1][0] b[1][1]b[1][2]b[2][0] b[2][1] b[2][2]300CH300EH 3010H 二维数组的初始化1.分行给二维数组赋初值。 例如: int a[3][4]={{1,2,3,4},{5,6,7, 8},{9,10,11,12}}; 2.可以将所有数据写在一个花括号内,按数组排列 的顺序对各元素赋初值。 例如:int a[3][4]={1,2,3,4,5,6,7,8, 9,10,11,12}; 3.可以对部分元素赋初值。 例如: int a[3][4]={{1},{5},{9}};也可以对各行中的某一元素赋初值,如int a[3][4]={{1},{0,6},{0,0,11}}; 1 0 0 0 5 6 0 0 0 0 0 0 1 0 0 0 6 0 0 0 0 0 11 0 1 0 0 0 5 0 0 0 9 0 0 0也可以只对某几行元素赋初值。如: int a[3][4]={{1},{5,6}}; 4.如果对全部元素都赋初值,则定义数组时对第 一维的长度可以不指定,但第二维的长度不能省。 例如:int a[3][4]={1,2,3,4,5,6,7, 8,9,10,11,12};它等价于:int a[][4] ={1,2,3,4,5,6,7,8,9,10,11,12}; 0 0 3 0 在定义时也可以只对部分元素赋初值而省略第一维 0 0 0 0 的长度,但应分行赋初值。 0 10 0 0 例如:int a[][4]={{0,0,3},{},{0, 10}}; 例: 有一个3×4的矩阵,要求编程序求出其中值最大的那 个元素的值,以及其所在的行号和列号。 N-S流程图表示算法 如下: 程序: #include &stdio.h& void main() { int i,j,row=0,colum=0, int a[3][4]={{1,2,3,4},{9,8,7,6}, {-10,10,-5,2}}; max=a[0][0]; for (i=0;i&=2;i++) for (j=0;j&=3;j++) if (a[i][j]&max) { max=a[i][j]; row=i; colum=j; } printf(″max=%d,row=%d,colum=%d\n″, max,row,colum); } /*程序结束*/ 6.1.3 高维数组?可以将高维数组看成由数组构成的数组 如在二维数组中每一行是一个一维数组 三维数组可看成多个二维数组组成的正方体 ,二维数组的个数是立方体的高度,每一个 二维数组是立方体的一个面,在二维数组的 平面上有行有列。? 三维数组声明语句:维数组必然要转化为一维数组存 储。多维数组按维次序存储,越 M[0][0][0] M[0][0][1] M[0][0][2] M[0][0][3] M[0][1][0] M[0][1][1] 右边的下标变化越快。int M[2][3][4]; //声明一个三维数组 计算机的内存是一维遍址的,多 元素存放顺序为:M[0][1][2] M[0][1][3] M[0][2][0] M[0][2][1] M[0][2][2] M[0][2][3] M[1][0][0] M[1][0][1] M[1][0][2] M[1][0][3] M[1][1][0] M[1][1][1] M[1][1][2] M[1][1][3] M[1][2][0] M[1][2][1] M[1][2][2] M[1][2][3]三维数组存储结构图一般情况下,三维和三维以上的数 组很少使用,最常用的就是一维数组。34 6.1.4 数组作为函数参数数 组??数组元素作实参,与单个变量一样。数组名作参数,形、实参数都应是数 组名,类型要一样,传送的是数组首 地址。对形参数组的改变会直接影响 到实参数组。 例6-2 使用数组名作为函数参数主函数中初始化一个矩阵并将每个元素都输 出,然后调用子函数,分别计算每一行的元 素之和,将和直接存放在每行的第一个元素 中,返回主函数之后输出各行元素的和。? #include &iostream& void RowSum( int A[][4], int nrow ) { 二维数组的 行数 for (int i = 0; i & i++) { sum = 0; for(int j = 0; j & 4; j++) sum += A[i][j]; cout && &Sum of row & && i && & is & && sum && A[i][0]= } }对于二维数组下标 只能省略一个,不 能同时省略37 int main() { 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 && } RowSum(Table,3); for (int i = 0; i & 3; i++) cout && Table[i][0]&;}38 运行结果: 1 2 3 2 3 4 3 4 5 Sum of row Sum of row Sum of row 10 14 184 5 6 0 is 10 1 is 14 2 is 1839 RowSum的另一种实现void RowSum( int A[][4], int nrow ) { for (int i = 0; i & i++) { for(int j = 1; j & 4; j++) A[i][0] += A[i][j]; } } 6.1.5 对象数组数 组?所谓对象数组是有若干个对象所构成的集合 ,它的每一个元素都是一个对象。 声明:类名 数组名[元素个数];??访问方法:通过下标访问数组名[下标].成员名 对象数组初始化数 组数组中每一个元素对象被创建时,系统 都会调用类构造函数初始化该对象。 ? 通过初始化列表赋值。?例: Point A[2]={Point(1,2),Point(3,4)};?如果没有为数组元素指定显式初始值, 数组元素便使用默认值初始化(调用默 认构造函数)。 数组元素所属类的构造函数数 组不声明构造函数,则采用默认构造函数 。 ? 各元素对象的初值要求为相同的值时, 可以声明具有默认形参值的构造函数。 ? 各元素对象的初值要求为不同的值时, 需要声明带形参的构造函数。 ? 当数组中每一个对象被删除时,系统都 要调用一次析构函数。? 例6-3 对象数组应用举例数 组//Point.h #if !defined(_POINT_H) #define _POINT_H class Point { public: Point(); Point(int xx,int yy); ~Point(); void Move(int x,int y); int GetX() {return X;} int GetY() {return Y;} private: int X,Y; }; #endif //6-2.cpp #include&iostream& #include &Point.h& Point::Point() { X=Y=0; cout&&&Default Constructor called.&&& } Point::Point(int xx,int yy) { X= Y= cout&& &Constructor called.&&& } Point ::~Point() { cout&&&Destructor called.&&& } void Point ::Move(int x,int y) { X=x; Y=y; }45 #include&iostream& #include &Point.h& int main() { cout&&&Entering main...&&& Point A[2]; for(int i=0;i&2;i++) A[i].Move(i+10,i+20); cout&&&Exiting main...&&& return 0; }46 运行结果:Entering main... Default Constructor called. Default Constructor called. Exiting main... Destructor called. Destructor called.47 6.2 指针――关于内存地址?内存空间的访问方式?通过变量名访问?通过地址访问?地址运算符:&例: 则&var 表示变量var在内存中的起始地址 指针变量的概念指 针概念 指针:内存地址,用于 间接访问内存单元 2000 指针变量: 2004 用于存放地址的变量 声明 例: 3010 static int *i_pointer=&i;指向整型变量的指针内存用户数据区3 6变量 i 变量 j2000变量 i_pointer引用 例1:i=3; 例2:*i_pointer=3;i_pointer*i_pointer200032000i 指针变量的初始化指 针?语法形式 存储类型 数据类型 *指针名=初始地址;例:int *pa=&a; ?注意事项C用变量地址作为初值时,该变量必须在指针初 始化之前已说明过,且变量类型应与指针类型 一致。 C可以用一个已赋初值的指针去初始化另一 个指 针变量。 C不要用一个内部 auto 变量去初始化 static 指针。 指针变量的赋值运算指 针指针名=地址 ? “地址”中存放的数据类型与指针类型必须相符。 ? 向指针变量赋的值必须是地址常量或变量,不能是 普通整数。但可以赋值为整数0,表示空指针。 ? 指针的类型是它所指向变量的类型,而不是指针本 身数据值的类型,任何一个指针本身的数据值都是 unsigned long int型。 ? 允许声明指向 void 类型的指针。该指针可以被赋 予任何类型对象的地址。 例: void * 例6-5 指针的声明、赋值与使用指 针#include&iostream& int main() {int *i_ //声明int型指针i_ //声明int型数i i_pointer=&i; //取i的地址赋给i_pointer i=10; //int型数赋初值 cout&&&Output int i=&&&i&&//输出int型数的值 cout&&&Output int pointer i=&&&*i_pointer&& //输出int型指针所指地址的内容 } 程序运行的结果是: Output int i=10 Output int pointer i=1053 例6-6 void类型指针的使用指 针//错,不能声明void类型的变量 void *//对,可以声明void类型的指针 int * int main() { pv = &i; //void类型指针指向整型变量 //void指针赋值给int指针需要类型强制转换: pint = (int *) } 指向常量的指针指 针??不能通过指针来改变所指对象的值,但指针本 身可以改变,可以指向另外的对象。 例1char *name1=&John&; //name1是一般指针 *name1='A'; //编译正确,运行出错?例2const char *name1=&John&; //指向常量的指针 char s[]=&abc&; name1=s; //正确,name1本身的值可以改变 *name1='1'; //编译时指出错误 指针类型的常量?若声明指针常量,则指针本身的值不能被改变。例: int n1=3; const int n2=5; int *const pn=&n1;指 针?pn=&n2;*pn=6;?//错误 //正确例:char *const name2=&John&; //错误,指针常量值不能改变 name2=&abc&; 指针变量的算术运算指 针? ?指针与整数的加减运算?指针p加上或减去n,其意义是指针当前指向位置的前方或后方第n个数据的地址。 ?这种运算的结果值取决于指针指向的数据 类型。指针加一,减一运算?指向下一个或前一个数据。 ?例如:y=*px++ 相当于 y=*(px++)(*和++优先级相同,自右向左运算) short *pa pa-2 pa-1 *(pa-2)*(pa-1)*papapa+1*(pa+1) *(pa+2) *(pa+3)pa+2pa+358 long *pbpb-1*(pb-1)pb*pbpb+1 *(pb+1)pb+2*(pb+2)59 指针变量的关系运算指 针?关系运算?指向相同类型数据的指针之间可以进行各种关系运算。 ?指向不同数据类型的指针,以及指针与一般 整数变量之间的关系运算是无意义的。 ?指针可以和零之间进行等于或不等于的关系 运算。例如:p==0或p!=0?赋值运算?向指针变量赋的值必须是地址常量或变量,不能是普通整数。但可以赋值为整数0,表 示空指针。 指向数组元素的指针指 针?声明与赋值例:int a[10], * 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-7指 设有一个int型数组a,有10个元素。用三种方法输出各元素:针?使用数组名和下标 ?使用数组名和指针运算 ?使用指针变量 使用数组名和下标int main() { int a[10]; for(i=0; i&10; i++) cin&&a[i]; cout&& for(i=0; i&10; i++) cout&&a[i]; }63 使用数组名指针运算int main() { int a[10]; for(i=0; i&10; i++) cin&&a[i]; cout&& for(i=0; i&10; i++) cout&&*(a+i); }64 使用指针变量int main() { int a[10]; int *p,i; for(i=0; i&10; i++) cin&&a[i]; cout&& for(p=a; p&(a+10); p++) cout&&*p; }65 指针数组指 针??数组的元素是指针型例:Point *pa[2];由pa[0],pa[1]两个指针组成 例6-8 利用指针数组存放单位矩阵指 针#include &iostream& int 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:&&& for(int i=0;i&3;i++) //对指针数组元素循环 { for(int j=0;j&3;j++)//对矩阵每一行循环 { cout&&p_line[i][j]&&& &; } cout&& } 输出结果为: }Matrix test: 1,0,0 0,1,0 0,0,168 例6-9 二维数组举例指 针#include &iostream& int main() { int array2[2][3]={{11,12,13},{21,22,23}}; for(int i=0;i&2;i++) { cout&&*(array2+i)&& for(int j=0;j&3;j++) { cout&&*(*(array2+i)+j)&&& &; //或者 cout&&array2[i][j]&&& &; } cout&& } } 在某次运行之后,程序的输出结果为: 0X0065FDE0 11,12,13 0X0065FDEC 21,22,2370 指针应用举例#include&iostream.h& void main( ) { int *pt_ float *pt_ int pig=7,dog=27; float x=1.2345,y=32.14; void * pt_int=& *pt_int+= cout&&“Pig now has the value of”&&*pt_int&&“\n”; gereral=pt_ //指向int型的指针赋值给void型指针 pt_float=&x; y+=5*(*pt_float); cout&&“y now has the value of”&&“\n”; gereral=pt_float; //指向float型的指针赋值给void型指针 const char *name1=“John”; //指向常量的指针,所指对象之值不能改变 char *const name2=“John”; //常量指针,指针本身不能被改变 }运行结果: Pig now has the value of 34 y now has the value of 38.3125 指针与函数指针作为函数参数 ? 指针型函数?存储类型?数据类型*函数名()指向函数的指针存储类型 数据类型 (*函数指针名)(); 以指针作为函数参数指 针 与 函 数?以地址方式传递数据,可以用来返回函 数处理结果。??形参是指针,实参可以是变量地址实参是数组名时形参可以是指针。 例6.10题目:读入三个浮点数,将整数部分和小数 部分分别输出#include &iostream& void splitfloat(float x, int *intpart, float *fracpart) { //形参intpart、 fracpart是指针 *intpart=int(x); // 取x的整数部分 *fracpart=x-* //取x的小数部分 } int main() { int i, float x, cout&&&Enter three(3) floating point numbers& && for (i = 0; i & 3; i++) { cin && splitfloat(x,&n,&f); //变量地址做实参 cout&&&Integer Part is &&& n &&& Fraction Part is &&&f&& } }77 运行结果: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.751878 指向常量的指针做形参#include&iostrem.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&&“}”&& }程序执行时,p=array, 当把array作为实参传递给形参 p后,实际是把array的值传递给了p,p所指向的地址 就和array所指向的地址一致,但是p和array各自占用 各自的存储空间。在函数体内对p进行自加1运算,并 不意味着同时对array进行自加1运算。 例: 输出数组元素的内容和地址#include &iostream& #include &iomanip& void Array_Ptr(long *P, int n) { cout&&&In func, address of array is & &&unsigned long(P)&& cout&&&Accessing array using pointers&&& for (i = 0; i & i++) { cout&&& Address for index &&&i&&& is & &&unsigned long(P+i); cout&&& Value is &&&*(P+i)&& } } int main() { long list[5]={50, 60, 70, 80, 90}; cout&&&In main, address of array is & && unsigned long(list)&& cout&& Array_Ptr(list,5); }82 运行结果:In main, address of array is 6684132In func, address of array is 6684132 Accessing array using pointers Address for index 0 is 6684132 Value Address for index 1 is 6684136 Value Address for index 2 is 6684140 Value Address for index 3 is 6684144 Value Address for index 4 is 6684148 Valueis is is is is50 60 70 80 9083 指针型函数指 当函数的返回值是地址时,该 针 函数就是指针形函数。 与 函 声明形式 数存储类型 数据类型 *函数名() main(){ char *day_name(int n); printf(&input Day No:\n&); scanf(&%d&,&i); if(i&0) exit(1); printf(&Day No:%2d--&%s\n&,i,day_name(i) ); } char *day_name(int n)不能把局部变量的地址当成指针 型函数的返回值,因为每个函数 结束时都会释放自己的堆栈,而 局部变量是存储在堆栈中的,函 数结束后存储内容被析构{ static char *name[]={ &Illegal day&,&Monday&,&Tuesday&,&Wednesday&, &Thursday&,&Friday&,&Saturday&,&Sunday&}; return((n&1||n&7) ? name[0] : name[n]); } 指向函数的指针指 针 与 函 数?声明形式存储类型 数据类型 (*函数指针名)();?含义:?数据指针指向数据存储区,而函数指针指向的是程序代码存储区。 例6-11函数指针指 针 与 函 数#include &iostream& 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=(float)3.14159; float two_pi=(float)2.0* print_stuff(pi); function_pointer = print_ function_pointer(pi); function_pointer = print_ function_pointer(two_pi); function_pointer(13.0); function_pointer = print_ function_pointer(pi); print_float(pi);}88 void print_stuff(float data_to_ignore) { cout&&&This is the print stuff function.\n&; } void print_message(float list_this_data) { cout&&&The data to be listed is & &&list_this_data&& } void print_float(float data_to_print) { cout&&&The data to be printed is & &&data_to_print&& }89 运行结果: This is the This is the The data to The data to The data to The data to print stuff function. print stuff function. be listed is 6.283180 be listed is 13.000000 be printed is 3.141590 be printed is 3.14159090 指针型函数和指向函数的指针???int(*p)()和int *p()是两个完全不同的量。 int (*p)()是一个变量说明,说明p是一个指向函数 入口的指针变量,该函数的返回值是整型量,(*p) 的两边的括号不能少。 int *p()则不是变量说明而是函数说明,说明p是一 个指针型函数,其返回值是一个指向整型量的指针 ,*p两边没有括号。作为函数说明,在括号内最好 写入形式参数,这样便于与变量说明区别。 对于指 针型函数定义,int *p()只是函数头部分,一般还应 该有函数体部分。 指向结构体的指针? ?声明形式结构体名 *结构对象指针名;例struct MyStruct { }; struct MyStruct ss={20,30,40}; //声明了结构对象ss,并把 ss的成员初始化为 20,30 和40。 struct MyStruct *ptr=& //声明了一个指向结构对象 ss的指针。它指向的类型是 MyStruct。 int *pstr=(int*)& //声明了一个指向结构对象 ss的指针。但是pstr和 //它被指向的类型ptr 是不同的。 请问怎样通过指针ptr 来访问 ss的三 个成员变量?ptr-&a; //指向运算符,或者可以这们(*ptr).a,建 议使用前者 ptr-&b; ptr-&c; 请问怎样通过指针 pstr来访问ss的三个成员变量?*pstr; //访问了 ss的成员 a。 *(pstr+1); //访问了 ss的成员 b。 *(pstr+2) //访问了 ss的成员 c。 用 pstr 来访问结构成员是不正规的。存放结构对象的各个成 员时,在某种编译环境下,可能会需要字对齐或双字对齐或 者是别的什么对齐,需要在相邻两个成员之间加若干个&填充 字节&,这就导致各个成员之间可能会有若干个字节的空隙。 即使*pstr 访问到了结构对象 ss 的第一个成员变量a,也不能 保证*(pstr+1)就一定能访问到结构成员b。因为成员a 和成员 b 之间可能会有若干填充字节,说不定*(pstr+1)就正好访问到 了这些填充字节。 对象与指针? 对象指针 ? this指针? 指向类的非静态成员的指针? 指向类的静态成员的指针 对象指针的一般概念指 针??声明形式类名 *对象指针名;例Point A(5,10); Piont * ptr=&A;?通过指针访问对象成员(公有)对象指针名-&成员名 ptr-&getx() 相当于 (*ptr).getx(); 对象指针应用举例指 针int main() { Point A(5,10); Point * ptr=&A; x=ptr-&GetX(); cout&&x&& return 0; } 曾经出现过的错误例子指 针class F //前向引用声明 class Barney { F //错误:类Fred的声明尚不完善 }; class Fred { B }; 正确的程序指 针class F //前向引用声明 class Barney { 允许在Barney类中声明一个 Fred *x; 类Fred的指针(而不是对象) }; class Fred { B }; this指针指 针隐含于每一个类的成员函数中的特殊 指针。 ? 明确地指出了成员函数当前所操作的 数据所属的对象。??当通过一个对象调用成员函数时,系统先将该对象的地址赋给this指针,然后 调用成员函数,成员函数对对象的数据 成员进行操作时,就隐含使用了this指 针。 this指针指 例如:Point类的构造函数体中的语句: 针X= Y=相当于:this-&X= this-&Y= 指向类的非静态成员的指针指 针通过指向成员的指针只能访问公有成员 ? 声明指向成员的指针??声明指向公有数据成员的指针 类型说明符 类名::*指针名; ?声明指向公有函数成员的指针 类型说明符 (类名::*指针名)(参数表); 指向类的非静态成员的指针指 针?指向数据成员的指针?说明指针应该指向哪个成员 指针名=&类名::数据成员名; ?通过对象名(或对象指针)与成员指针结合来访问数据成员对象名.* 类成员指针名 或: 对象指针名―&*类成员指针名 指向类的非静态成员的指针指 针?指向函数成员的指针?初始化 指针名=&类名::函数成员名; ?通过对象名(或对象指针)与成员指针结合来访问函数成员(对象名.* 类成员指针名)(参数表) 或: (对象指针名―&*类成员指针名)(参数表) 指向类的非静态成员的指针例6-13 访问对象的公有成员函数的不同方式指 针int main() //主函数 { Point A(4,5); //声明对象A Point *p1=&A; //声明对象指针并初始化//声明成员函数指针并初始化int (Point::*p_GetX)()= &Point::GetX;//(1)使用成员函数指针访问成员函数cout&&(A.*p_GetX)()&&//(2)使用对象指针访问成员函数cout&&(p1-&GetX)()&&//(3)使用对象名访问成员函数cout&&A.GetX()&&} 指向类的静态成员的指针指 针对类的静态成员的访问不依赖于对象 ? 可以用普通的指针来指向和访问静态 成员 ? 例6-14??通过指针访问类的静态数据成员?例6-15?通过指针访问类的静态函数成员 例6-14通过指针访问类的静态数据成员#include &iostream& class Point //Point类声明 {public: //外部接口 Point(int xx=0, int yy=0) {X=Y=countP++;}//构造函数 Point(Point &p); //拷贝构造函数 int GetX() {return X;} int GetY() {return Y;} static int countP; //静态数据成员引用性说明 private: //私有数据成员 int X,Y; }; Point::Point(Point &p) { X=p.X; Y=p.Y; countP++; } int Point::countP=0; //静态数据成员定义性说明指 针 int main() //主函数 { //声明一个int型指针,指向类的静态成员 int *count=&Point::countP; Point A(4,5); //声明对象A cout&&&Point A,&&&A.GetX()&&&,&&&A.GetY(); //直接通过指针访问静态数据成员 cout&&& Object id=&&&*count&& Point B(A); //声明对象B cout&&&Point B,&&&B.GetX() &&&,&&&B.GetY(); //直接通过指针访问静态数据成员 cout&&& Object id=&&&*count&& }108 例6-15通过指针访问类的静态函数成员#include &iostream& class Point //Point类声明 { public: //外部接口 //其他函数略 static void GetC() //静态函数成员 { cout&&& Object id=&&&countP&& } private: //私有数据成员 int X,Y; static int countP; //静态数据成员引用性说明 }; // 函数实现略 int Point::countP=0; //静态数据成员定义性说明指 针 int main() //主函数 { //指向函数的指针,指向类的静态成员函数 void (*gc)()=Point::GetC; Point A(4,5); //声明对象A cout&&&Point A,&&&A.GetX()&&&,&&&A.GetY(); gc(); //输出对象序号,通过指针访问静态函数成员 Point B(A);//声明对象B cout&&&Point B,&&&B.GetX()&&&,&&&B.GetY(); gc(); //输出对象序号,通过指针访问静态函数成员 }110 指向指针的指针char *name[5]={“Follow me”,”Basic”,……}name 数组 name 字符串name[0] name[1] name[2] . .Follow me Basic .. . .name 代表了name数组的首地址,可以送给一个指针p因为name数组之值是地址即指针,所以p的类型应为指向指针的指针即 char * *p (*结合性自右向左) #include&iostream.h& #include”Point.h” //Point类声明略 void f(Point **a, int n) void 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]; } void f(Point **a,int n) //实参是指针数组,形参应使用二级指针 //也可以写成void f(Point *a[ ],int n) { for (int i = 0;i&n;i++) cout&&a[i]-&GetX( )&& 运行结果: }Constructor called。 Constructor called。 1 2Destructor called。Destructor called。 6.3 动态内存分配―― 动态申请内存操作符 new 动 new 类型名T(初值列表) 态 功能:在程序执行期间,申请用于存放T 存 类型对象的内存空间,并依初值列表 储 赋以初值。 分 配 结果值:成功:T类型的指针,指向新分配的内存。失败:0(NULL)或抛出异 常。 释放内存操作符delete动 态 存 储 分 配delete 指针P 功能:释放指针P所指向的内存。P必须 是new操作的返回值。 动态存储分配举例#include&iostream.h& Struct date { } void main() { int index, *point1, *point2; point1 = & *point1 = 77; point2 = *point2 = 173; cout&&“The values are”&&index&&“ ”&&*point1&&“ “&&*point2&&“\n”; delete point2; point1 = point2 = point1; *point1= 999; cout&&“The values are”&&index&&“ ”&&*point1&&“ “&&*point2&&“\n”;delete point1; float *float_point1, *float_point2 =float_point1 = *float_point2 = 3.14159; *float_point1 = 2.3 *(*float_point2); delete float_point2;delete float_point1; date *date_date_point = 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_//释放结构体 char *c_c_point = new char[37]; delete [ ] c_//动态分配数组//释放数组c_point = new char[sizeof(date)+133];//动态分配数组delete [ ] c_return 0; }运行结果://释放数组The values are 77 77 193The values are 77 999 999 10/18/1938 例6-16 动态创建对象举例动 态 存 储 分 配#include&iostream& class Point {public: Point() { X=Y=0; cout&&&Default Constructor called.\n&;} Point(int xx,int yy) { X=Y= 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; }; int main() { cout&&&Step One:&&& Point *Ptr1=new P delete Ptr1; cout&&&Step Two:&&& Ptr1=new Point(1,2); delete Ptr1; return 0; 运行结果: Step One: } Default Constructor called. Destructor called. Step Two: Constructor called. Destructor called. 例6-17动态创建对象数组举例 动 态 存 储 分 配#include&iostream& class Point { //类的声明同例6-16,略 }; int main() { Point *Ptr=new Point[2]; //创建对象数组 Ptr[0].Move(5,10); //通过指针访问数组元素的成员 Ptr[1].Move(15,20); //通过指针访问数组元素的成员 cout&&&Deleting...&&& delete[ ] P //删除整个对象数组 return 0; } 运行结果: Default Constructor called. Default Constructor called. Deleting... Destructor called. Destructor called.124 例6-18动态数组类#include&iostream& class Point { //类的声明同例6-16 ? }; class ArrayOfPoints { public: ArrayOfPoints(int n) { numberOfPoints=n; points=new Point[n];} ~ArrayOfPoints() { cout&&&Deleting...&&& numberOfPoints=0; delete[] } Point& Element(int n) { return points[n]; } 返回对象数组中的 private: 第n+1个 Point * Point类对象 int numberOfP };125 int main() { cout&&&Please enter the number of points:&; cin&& //创建对象数组 ArrayOfPoints points1(number); //通过指针访问数组元素的成员 points1.Element(0).Move(5,10); //通过指针访问数组元素的成员 points1.Element(1).Move(15,20); }126 运行结果如下: Please enter the number of points:2 Default Constructor called. Default Constructor called. Deleting... Destructor called. Destructor called.127 动态创建多维数组动 态 存 储 分 配new 类型名T[下标表达式1][下标表达式2]?;如果内存申请成功,new运算返回一个指向 新分配内存首地址的指针,是一个T类型的 数组,数组元素的个数为除最左边一维外各 维下标表达式的乘积。例如: char (*fp)[3]; fp = new char[2][3]; char (*fp)[3];fpfp[0][0]fp[0][1] fp[0][2]fp+1fp[1][0] fp[1][1] fp[1][2]129 int p[3];//首先从 P处开始,先与[]结合,说明 P 是一个数组,然后与 int结合, 说明数组里的元素是整型的,所以 P是一个由整型数据组成的数 组int *p[3];//首先从 P处开始,先与[]结合,因为其优先级比*高,所以 P是一个数 组,然后再与*结合,说明数组里的元素是指针类型,然后再与 int结合, 说明指针所指向的内容的类型是整型的,所以P 是一个由返回整型 数据的指针所组成的数组int (*p)[3];//首先从 P处开始,先与*结合,说明 P是一个指针然后再与[]结合(与 &()&这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一 个数组,然后再与 int 结合,说明数组里的元素是整型的.所以 P 是一 个指向由整型数据组成的数组的指针 例6-18动态创建多维数组动 态 存 储 分 配#include&iostream& int 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&& } cout&& } }132 动态存储分配函数动 态 存 储 分 配?void *malloc( size );参数size:欲分配的字节数返回值:成功,则返回void型指针。 失败,则返回空指针。 头文件:&cstdlib& 和 &cmalloc& 动态内存释放函数动 态 存 储 分 配?void free( void *memblock );参数memblock:指针,指向需释放的内存。返回值:无头文件:&cstdlib& 和 &cmalloc& 浅 拷 贝 与 深 拷 贝6.4 浅拷贝与深拷贝?浅拷贝?实现对象间数据元素的一一对应复制。?深拷贝?当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指 针所指的对象进行复制。 例6-20对象的浅拷贝#include&iostream& class Point { //类的声明同例6-16 ? }; class ArrayOfPoints { public: ArrayOfPoints(int n) { numberOfPoints=n; points=new Point[n];} ~ArrayOfPoints() { cout&&&Deleting...&&& numberOfPoints=0; delete[] } Point& Element(int n) { return points[n]; } private: Point * int numberOfP }; int main() { cin&& ArrayOfPoints pointsArray1(number); pointsArray1.Element(0).Move(5,10); pointsArray1.Element(1).Move(15,20); ArrayOfPoints pointsArray2(pointsArray1); cout&&&Copy of pointsArray1:&&& cout&&&Point_0 of array2: & &&pointsArray2.Element(0).GetX() &&&, &&&pointsArray2.Element(0).GetY()&& cout&&&Point_1 of array2: & &&pointsArray2.Element(1).GetX() &&&, &&&pointsArray2.Element(1).GetY()&&137 pointsArray1.Element(0).Move(25,30); pointsArray1.Element(1).Move(35,40); cout&&&After the moving of pointsArray1:&&& cout&&&Point_0 of array2: & &&pointsArray2.Element(0).GetX() &&&, &&&pointsArray2.Element(0).GetY()&& cout&&&Point_1 of array2: & &&pointsArray2.Element(1).GetX() &&&, &&&pointsArray2.Element(1).GetY()&& }138 运行结果如下: Please enter the number of points:2 Default Constructor called. Default Constructor called. Copy of pointsArray1: Point_0 of array2: 5, 10 Point_1 of array2: 15, 20 After the moving of pointsArray1: Point_0 of array2: 25, 30 Point_1 of array2: 35, 40 Deleting... Destructor called. Destructor called. Deleting... 接下来程序出现异常,也就是运行错误。139 pointsArray1的数组元 素占用的内存pointsArray1 points numberOfPoints拷贝前pointsArray1 的 数 组 元 素占用的内存 pointsArray1 points numberOfPoints拷贝后pointsArray2points numberOfPoints浅拷贝:实现对象间数据元素的 一一对应复制。 140 例6-20对象的深拷贝#include&iostream& class Point { //类的声明同例6-16 ? }; class ArrayOfPoints { public: ArrayOfPoints(int n) { numberOfPoints=n; points=new Point[n];} ~ArrayOfPoints() { cout&&&Deleting...&&& numberOfPoints=0; delete[] } Point& Element(int n) { return points[n]; } private: Point * int numberOfP }; ArrayOfPoints ::ArrayOfPoints (ArrayOfPoints& pointsArray) { numberOfPoints =pointsArray.numberOfP points=new Point[numberOfPoints]; for (int i=0; i&numberOfP i++) points[i].Move( pointsArray.Element(i).GetX(), pointsArray.Element(i).GetY()); }142 int main() //同上例 { cin&& ArrayOfPoints pointsArray1(number); pointsArray1.Element(0).Move(5,10); pointsArray1.Element(1).Move(15,20); ArrayOfPoints pointsArray2(pointsArray1); cout&&&Copy of pointsArray1:&&& cout&&&Point_0 of array2: & &&pointsArray2.Element(0).GetX() &&&, &&&pointsArray2.Element(0).GetY()&& cout&&&Point_1 of array2: & &&pointsArray2.Element(1).GetX() &&&, &&&pointsArray2.Element(1).GetY()&&143 pointsArray1.Element(0).Move(25,30); pointsArray1.Element(1).Move(35,40); cout&&&After the moving of pointsArray1:&&& cout&&&Point_0 of array2: & &&pointsArray2.Element(0).GetX() &&&, &&&pointsArray2.Element(0).GetY()&& cout&&&Point_1 of array2: & &&pointsArray2.Element(1).GetX() &&&, &&&pointsArray2.Element(1).GetY()&& }144 程序的运行结果如下: Please enter the number of points:2 Default Constructor called. Default Constructor called. Default Constructor called. Default Constructor called. Copy of pointsArray1: Point_0 of array2: 5, 10 Point_1 of array2: 15, 20 After the moving of pointsArray1: Point_0 of array2: 5, 10 Point_1 of array2: 15, 20 Deleting... Destructor called. Destructor called. Deleting... Destructor called. Destructor called.145 pointsArray1 的 数 组 元素占用的内存 pointsArray1 points numberOfPoints拷贝前pointsArray1 的 数 组 元素占用的内存 pointsArray1 points numberOfPoints拷贝后pointsArray2 points numberOfPoints146 6.5 用字符数组存储和处理字符串字符数组的声明和引用字 符 串字符串 字符串常量,例如:&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 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 ? \0151 若改为: static char str[13]; cin&& 运行时输入数据: How are you?内存中变量 str 内容如下: str: H o w \0?152 字符串处理函数字 strcat(连接),strcpy(复制), 符 strcmp(比较),strlen(求长度), 串 strlwr(转换为小写),strupr(转换为大写) 头文件&cstring& string类?构造函数原型?string(); ?string(const string& rhs); ?string(const char *s); ?string(const string& rhs, unsigned int pos,unsigned int n); ?string(const char *s, unsigned int n); ?string(unsigned int n, char c); string类?常用成员函数?string appened(const char *s); ?string assign(const char *s); ?int compare(const string& str) ?string& insert(unsigned int p0, const char *s); ?string sunbstr(unsigned int pos, unsigned int n) ?unsigned int find(const basic_string& str) ?unsigned int length() ?void swap(string& str); string类?string类的操作符 +, =, +=, ==, !=, &, &=, &, &=, [] 字符串比较?设两个字符串s1和s2,二者大小的比较规则 如下:?如果s1与s2长度相同,且所有字符完全相同,则s1等于s2; ?如果s1与s2所有字符不完全相同则比较第一对不 相同字符的ASCII码,较小字符所在的串为较小 的串; ?如果s1的长度n1小于s2的长度n2,且两字符串的 前n1个字符完全相同,则s1小于s2。 例6.21 string类应用举例字 #include &string& 符 #include &iostream& 串 void trueFalse(int x) { cout&&(x? &True&: &False&)&& } int main() { string S1=&DEF&, S2=&123&; char CP1[ ]=&ABC&; char CP2[ ]=&DEF&; cout&&&S1 is &&&S1&& cout&&&S2 is &&&S2&& cout&&&length of S2:&&&S2.length()&& cout&&&CP1 is &&&CP1&& cout&&&CP2 is &&&CP2&& cout&&&S1&=CP1 returned &; trueFalse(S1&=CP1); cout&&&CP2&=S1 returned &; trueFalse(CP2&=S1); S2+=S1; //运算符重载 cout&&&S2=S2+S1:&&&S2&& cout&&&length of S2:&&&S2.length()&& }163 小结与复习建议?主要内容? 数组、指针、动态存储分配、指针与数组、指针与函数、字符串?达到的目标? 理解数组、指针的概念,掌握定义和使用方法,掌握动态存储分配技术,会用数组存储和处理字符串,会使用 string类。?实验任务? 实验六
赞助商链接}

我要回帖

更多关于 指向一维数组的指针 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信