当前位置:文档之家› 10数组与指针

10数组与指针

10数组与指针
10数组与指针

数组与指针

一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址,所谓数组元素的指针就是数组元素的地址。引用数组元素可以用下标(如a[3]),也可以用指针法,即通过指向数组元素的指针找到所需的元素。使用指针法能使目标程序质量高(占内存少,运行速度快)。

一维数组和指针

1.指向数组元素的指针

例:int a[10]; /*定义a为包含10个整型数据的数组*/

int *p; /*定义p为指向整型变量的指针变量*/

p=&a[0]; 把a[0]元素的地址赋给指针变量p。也就是说,p指向a数组的第0号元素。C 语言规定数组名代表数组中第一个元素(即序号为0的元素)的地址,因此下面两个语句等价:p=&a[0]; 与p=a 等价。注意:数组名不代表整个数组,“p=a”的作用把a数组的首元素的地址赋给指针变量p,而不是把数组a各元素的值赋给p.

在定义指针变量时,可以对它赋初值:int *p=&a[0];或int *p=a;

2.通过数组的首地址引用数组元素

由以上可知:a是a数组元素的首地址,a(即:a+0)的值就等于&a[0];则a+1的值,就等于&a[1], a+2就等于&a[2],……a+9就等于&a[9]

这里,可以通过”取地址运算符*”来引用地址所在的存储单元,因此,对于数组元素a[0],可以通过表达式*&a[0]来引用,也可以用*(a+0)来引用,对此也可以写成:*a;而对于数组元素a[1],可以用表达式*&a[1]来引用,也可以用*(a+1)来引用……对于a[9]可以用*&a[9]来引用,也可以用*(a+9)来引用。

因此可以通过以下的语句输出a数组元素中的值:

for(k=0;k<10;k++) printf(“%4d”,*(a+k));

就相当于:for(k=0;k<10;k++) printf(“%4d”,a[k]);

3.通过指针引用数组元素

假如p已定义为一个指向整型数据的指针变量,并已给它赋了个整型数组元素的地址,使它指向某一个数组元素。如果有以下定义语句:*p=1;表示对p当前所指向数组元素赋予一个值1。

按C的规定,如果指针变量p已指向数组元素中的一个元素,则p+1指向同一数组中的下一个元素(而不将p的值简单的加1)。

如果p的初值为&a[0],即p=a或p=&a[0],也可以使用“间接访问运算符*”,通过指针变量p不引用a数组中的元素,对于数组a[0],可以用表达式*(p+0)即*p来引用,a[1],也可以用表达式*(p+1)来引用,p+1的值就是数组元素a[1] 的地址……对于数组元素a[9]就可以用*(p+9)来引用。所以当指针变量p指向a数组的起始地址时,可以通过以下语句输出a数组的元素:for(p=a,k=0;k<10;k++) printf(“%4d”,*(p+k);

指针变量p可以移动:

for(p=a,k=0;k<10;k++) { printf(“%4d”, *p), p++;}

4用带下标的指针变量引用数组元素

若有以下的定义:int *p , s[10],i ; p=s;

可以用&s[i], s+i; 和p+i三种表达式来表示s[i]的地址,同时可以用s[i], *(s+i)和*(p+i)三种表达式来表示数组元素s[i];s[i]可以用表达式*(s+i)来表示,同理*(p+i)也应该可以用表达式p[i]的形式来表示。因此,当p指向s数组的首地址时,表示数组元素s[i]的表达式有以下四种:

(1)s[i] (2) *(s+i) (3)*(p+i) (4)p[i]

这里,面s和p有着明显的区别,s是不可变的,而p中的地址却是可变的,因此,s++, s=p,p=&s 等运算都是不合法的,而p++,p=s,p=&s[i]则都是合法的表达式。

说明:

(1)p+i和a+i就是a[i]的地址,或者说它们指向a数组的第i个元素,这里a代表数组元素的

首地址,a+i也是地址。

(2)*(p+i)或*(a+i)是p+i或a+i所指向的数组元素,即a[i],即按数组首元素的地址加上相对位移

量得到要找的元素的地址,然后找出该单元中的内容。

(3)指向数组的指针变量也可以带下标,如p[i]与*(p+i)等价。

注意:指针变量的运算:先使p指向数组a的首元素,则

①p++或(p+=1),使p指向下一元素,即a[1]。若再执行*p,取出下一个元素a[1]值。

②*p++,由于++和*同优先级,结合方向自右至左,因此它等价于*(p++)。作用是先得到p

指向的变量的值(即*p),然后再使p+1=>p.

③*(p++)与*(++p)不同,前者是先取*p的值,然后使p加1。后者是先使p加1 ,再取*p。若p初值为a(即a[0]),输出*(p++)时,得a[0]的值;而输出*(++p),则得a[1]的值。

④(*p)++表示p所指向的元素值加1,即(a[0])++,如果a[0]=3;则(a[0])++的值为4。

函数与数组

1用数组名作函数参数

前面已经介绍过可用数组名和数组元素作函数参数。数组元素实际上代表内存中的一个存储单元,和普通变量一样。实参数组名代表该数组首元素的地址。而形参是用来接收从实参传递过来的数组首元素的地址。因此,形参应该是一个指针变量(只有指针能存放地址)。例:编写程序,通过函数给数组输入若干大于等于0的整数,用负数作为输入结束的标志;调用函数输出该数组中的数据。

#define M 100

void arrout(int *,int);

arrin(int * );

main()

{ int s[M],k;

k=arrin(s);

arrout(s,k);

}

arrin(int *a)

{ int i,x;

i=0;

scanf("%d",&x);

while(x>=0)

{ *(a+i)=x;

i++;

scanf("%d",&x);

}

return i;

}

void arrout(int *a,int n)

{ int i;

for(i=0;i

printf(((i+1)%5==0)?"%4d\n": "%4d",*(a+i));

printf("\n");

}

当数组名作为实参时,对应的形参除了应该是指针外,形参还可以用另外两种形式。对于函数调用arrin(s),对应的函数首部可以写成以下三种形式:

(1)arrin(int *a)

(2)arrin(int a[])

(3)arrin(int a[M])

但的C的编译程序都将把a处理成第一种的指针形式。

2数组元素地址作为实参

当数组元素的地址作为实参时,因为是地址值,所以对应的形参也应当是基类型相同的指针变量。

例:编写函数,对于具有10个元素的char类型的数组,从下标为4的元素开始,全部设置为”*”号,保持前四个元素中的内容不变。

#define M 10

#define B 4

void setstar(char *,int);

void arrout(char *,int);

main()

{ char c[M]={'A','B','C','D','E','F','G','H','I','J'};

setstar(&c[4],M-B);

arrout(c,M);

getch();}

void setstar(char *a,int n)

{ int i;

for(i=0;i

*(a+i)='*';

}

void arrout(char *a,int n)

{ int i;

for(i=0;i

printf("%c",a[i]);

printf("\n");

}

setstar的首部还可以写成:

setstar(char a[], int n) 或setstar(char a[M-B], int n)

多维数组和指针

1.二维数组a由若干个一维数组组成

若有定义:int *p, a[3][4];

a 是一个数组名,a数组包含3行,即3个元素:a[0],a[1],a[2]。而每一元素又是一个一维数组,它包含4个元素。可以有a[0][0],a[0][1]……来引用a[0]中的每一个元素,其它依次类推。

前面已介绍过:一维数组名是一个地址常量,其值为第一个元素的地址。而在二维数组中,a[0],a[1],a[2]都是一维数组名,同样也代表一个不可变的地址常量,其值依次为二维数组的每行的第一个元素的地址。

指针变量p与a[i]相同,因此,p=a[i]是合法的。对于a[i],可以写成:*(a+i),故也可以写成:p=*(a+i);

2.二维数组名也是一个地址常量

a 代表二维数组首元素的地址,现在的首元素不是一个整型变量,而是由4个整型元素所组成的一维数组,因此a代表的是首行(即第0行)的首地址,a+1 代表第1行的首地址,如果二维数组的首行地址为2000,,则a+1为2008。因此a+1的含义是a[1]的地址。

a[0],a[1],a[2]既然是一维数组名,而C规定数组名代表数组元素首地址,因此a[0]代表一维数组第0列元素地址,即&a[0][0]。a[1]的值是&a[1][0],a[2]的值是&a[2][0]。那么,第0行第1列元素地址呢?

3.二维数组元素的地址

a[0]为一维数组名,该一维数组中第2个元素显然应该用a[0]+1来表示,此时,“1”代表1个列元素的字节数。所以a[0]+0,a[0]+1,a[0]+2,a[0]+3,分别是a[0][0],a[0][1],a[0][2],a[0][3]元素的地址。即:&a[0][0],&a[0][1],&a[0][2],&a[0][3]

前面已经讲过a[0]和*(a+0)等价,a[1]和*(a+1)等价,a[i]和*(a+i)等价。因此,a[0]+1和*(a+0)+1的值都是&a[0][1], a[1]+2和*(a+1)+2的值都是&a[1][2].

若想得到a[0][1]的值,用地址法怎么表示呢?既然a[0]+1和*(a+0)+1是a[0][1]的地址,那么,*(a[0]+1)就是a[0][1]的值,同理,*(*(a+0)+1)或*(*a+1)也是a[0][1]的值。所以:*(a[i]+j)或*(*(a+i)+j))是a[i][j] 的值。请务必记住:*(a+i)和a[i]的等价的。

例:用指针变量输出数组元素的值。

main()

{ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

int *p;

for(p=a[0];p

{ if((p-a[0])%4==0)

printf("\n");

printf("%4d",*p);

}

getch(); }

可以输出p的值:printf("addr=%x,value=%d\n",p,*p);

如果想输出某个指定的数组元素,则应事先计算在数组中的相对位置(即相对于数组起始位置的相对位移量)。计算a[i][j]在数组中的相对位置的计算公式为:

i*m+j 其中,m为二维数组的列数

例如:3X4的二维数组,它的第2行第3列元素a[2][3]对a[0][0]的相对位置为2*4+3=11。如果开始时使指针变量p指向a[0][0],为了得到a[2][3]的值,可以用*(p+2*4+3)表示。所以a[i][j]的地址为a[0]+i*m+j;

例如:输出二维数组任一行任一列元素的值:

main()

{ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

int i,j;

scanf("%d%d",&i,&j);

printf("a[%d,%d]=%d\n",i,j,*(*(a+i)+j));

getch();}

总结:

a[i][j]的地址可用以下五种表达式求得:

(1)&a[i][j]

(2)a[i]+j

(3)*(a+i)+j

(4)&a[0][0]+4*i+j

(5)a[0]+4*i+j

相应的引用二维数组元素有以下五种方式:

(1)a[i][j]

(2)*(a[i]+j)

(3)*(*(a+i)+j)

(4)(*(a+i))[j]

(5)*(&a[0][0]+4*i+j)

注:a[i]从形式上看是a数组中第i个元素。如果a是一维数组名,则a[i]代表a数组第i个元素所占的内存单元的内容,a[i]是有物理地址的,是占内存单元的。但如果a是二维数组,则a[i]是代表一维数组名,这时它只是一个地址。

4.通过建立一个指针数组来引用二维数组元素

若有以下定义:int *p[3], a[3][2], i ,j ;

[]优先级大于*, 所以p先与[]结合构成:p[3], p是一个数组名,系统为它开辟3个存储单元;*号则说明数组p是指针类型。若有以下赋值:

for(i=0;i<3;i++) p[i]=a[i]; a[i]是常量,表示数组a每行的首地址,p[i]是指针变量,结果是使p[0],p[1],p[2]分别指向a数组每行开头。则a数组元素a[i][j]的引用形式*(a[i]+j)和*(p[i]+j)是完全等价的。

可以通过指针数组p来引用a数组元素:

(1)*(p[i]+j)

(2)*(*(p+i)+j)

(3)(*(p+i))[j]

(4)p[i][j]

5.建立一个行指针来引用二维数组元素:

若有以下定义:int a[3][2], (*prt)[2];

说明符:(*prt)[2]中,说明prt是一个指针变量,再与[2]结合,说明指针变量prt是一个包含两个int 元素的数组,与a基类型相同,所以prt=a合法。prt+1等价与a+1,等价a[1],当prt指向数组的开头时,可通过以下形式来引用a[i][j];

(1)*(prt[i]+[j])

(2)*(*(prt+i)+j)

(3) (*(prt+i)[j]

(4) prt[i][j]

6.二维数组名和指针数组作为实参

(I)二维数组名作为实参时:

当二维数组名作为实参时,对应的形参必须是一个行指针变量。例:若主函数中有以下的定义的函数调用语句:

#define M 5

#define N 3

main( )

{ double s[M][N];

……

fun(s);

……

}

则函数的首部可以是以下三种形式:

(1)fun(double (*a)[N])

(2)fun(double a[][N])

(3)fun(double a[M][N])

注意列一标不可缺,无论哪种方式,系统都将把子a处理成一个行指针。数组名传递给函数的是一个地址值,因此,对应的形参也必定是一个类型相同的指针变量。

(II)指针数组作为实参时:

当指针数组作为实参时,对应的形参应当是一个指向指针的指针,若主函数中有以下定义和函数调用语句:

#define M 5

#define N 3

main()

{ double s[M][N], *ps[M];

……

for(i=0;i

fun(ps);

……

}

则fun 函数的首部可以是以下三种形式:

(1)fun (double *a[M];

(2)fun(double *a[]);

(3)fun(double **a)

传送的是一维指针数组。

字符串与指针

1.字符串的表示形式:两种方法

(1)用字符数组存放一个字符串,然后输出该字符串

例:定义一个字符数组,对它初始化,然后输出该字符串

main()

{ char string[]="I love China!";

printf("%s\n",string);

getch();

}

string是数组名,它代表字符数组的首元素地址,string[4]就是*(string+4),指向字符v.

(2)用字符指针指向一个字符串

{ char *string="I love China!";

printf("%s\n",string);

getch();

}

通过字符数组名或字符指针变量可以输出一个字符串。而对一个数值型数组,是不能企图用数组名输出它的全部元素的。int i[10]; printf(“%d\n”,i);是不行的,只能逐个元素输出。

3.定义字符型指针数组并通过赋初值来构成一个字符串数组。

char *pa[3]={“a”,”bb”,”ccc”};指针数组pa的每个元素指向一个字符串。也就是说数组pa 的每个元素中存放着一个字符串的首地址。

这里,指针元素指向长度不同的无名一维数组,各字符数组之间并不占连续的存储单元,它们的连系全依赖于pa 指针数组元素;一旦pa指针数组元素中的地址被重新赋值,如果没有其它的指针指向相应的字符串,则相应的字符串将丢失。

由于指针数组已指向确定的存储空间,因此,也可以输入语句给这些字符串重新赋值:如:gets(pa[2]); pa中的地址没变,仍指向具有4个元素的无名字符数组,执行以上语句时,只能在一行输入包含3个字符的字符串。

可以用表达式:*(pa[2]+1),pa[2][1]……等形式引用pa数组所指字符串中的字符。

2.字符指针变量和字符数组的比较

(1)字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第一个字符的地址),决不是将字符串放到字符变量中。

(2)赋值方式,对字符数组只能各个元素赋值,不能用以下方法对数组元素赋值。

char str[14];

str=”I love China!”

而对指针变量,可以采用以下方法:

char *a;

a=”I love China”;

注意,赋给a的不是字符,而是字符串第一个元素的地址。

(3)对字符指针变量赋初值:char *a=”I love China!”;

就等价与:char *a;

a=”I love China”;

而对数组的初始化:char str[4]={“I love China!”}

不能等价与:char str[14];

str[ ]= {“I love China!”};

即数组可以在定义时整体赋初值,但不能在赋值语句中整体赋值。

(4)指针变量的值是可以改变的:

main()

{ char *a="I love China!";

a=a+7;

printf("%s",a);

getch(); }

例:编写函数scopy(char *s,char *t),将指针t所指的字符串复制到指针s所指的存储空间中。

#include "stdio.h"

void scopy(char *s,char *t)

{ int i;

while((s[i]=t[i])!='\0') /*先将t[i]赋给s[i],然后再判断s[i]的值是否等于’\0’*/

i++;

}

main()

{char str1[20],str2[]="ABCDEFGH";

scopy(str1,str2);

puts(str1);

getch();}

也可以通过指针s和t,使它们依次去指向对应的存储单元,通过学习*s=*t 的方式,将t所指源串中的字符逐个赋予s所指存储单元。因此,以上函数又可以写成:

void scopy(char *s,char *t)

{ while((*s=*t)!='\0')

{ s++;

t++; }

}

进一步while循环还可以改为:while((*s++=*t++)!=’\0’);

指针数组及指向一维数组的指针讲解

一、指针数组及指向一维数组的指针(数组指针)讲解 1、数组指针(也称行指针) 定义 int (*p)[n]; ()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。 如要将二维数组赋给一指针,应这样赋值:int a[3][4];int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。 p=a; //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0] p++; //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][] 所以数组指针也称指向一维数组的指针,亦称行指针。 2、指针数组 定义 int *p[n]; []优先级高,先与p结合成为一个数组,再由int *说明这是一个整型指针数组,它有n个指针类型的数组元素。这样赋值是错误的:p=a;只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。 如要将二维数组赋给一指针数组: int *p[3]; int a[3][4]; for(i=0;i<3;i++) p[i]=a[i]; 这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p [1]、p[2]所以要分别赋值。 这样两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。 还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。 比如要表示数组中i行j列一个元素: *(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j] 优先级:()>[]>* 例1、下列给定程序中,函数fun()的功能是:从N个字符串中找出最长的那个串,并将其地址作为函数值返回。 #include #include #define N 4

数组名和指针的区别(小结)

在Win 32 中: 1. (1) 对数组名进行sizeof运算时,结果是整个数组占用空间的大小; (2) 但是数组作为函数参数时,对数组名进sizeof 运算,结果为4; (2) 对指针进行sizeof运算得到的值是编译器分配给指针(也就是一个地址)的内存空间,即为4。 2. (1) 对数组名作&运算,得到的还是数组第一个元素的地址; (2) 对指针取地址时得到的结果是指针所在的地址,也就是指向这个指针的指针,与指针的值不同。 BOOL mytest(char param[100]) { //参数数组名:paramBytes int paramBytes = sizeof(param); printf("paramBytes \t%d\n",paramBytes); //数组:mych1[] char mych1[] = "abcdefg123"; //若定义为mych1[100] int mych1Bytes = sizeof(mych1); printf("mych1Bytes \t%d\n",mych1Bytes);//输出:100 //数组:mych[200] char mych[200] = {0}; int myBytes = sizeof(mych); printf("myBytes \t%d\n",myBytes); printf("---addr \t%d\n",mych); printf("---addr \t%d\n",&mych); //指针:pch char* pch = "12345abc"; int pchBytes = sizeof(pch); printf("pchBytes \t%d\n",pchBytes); //pch = mych; printf("---addr \t%d\n",pch); printf("---addr \t%d\n",&pch); return TRUE; } 运行:

指针与数组练习题

指针与数组练习题 1、下面程序实现如下功能:输入一个整数字符串转换为一个整数值,如”1234”转换为1234,”-1234”转换为-1234。读懂main函数,编写转换函数chnum #include #include void main() { char s[6]; int n; int chnum(char *p); gets(s); if (*s=='-') n=-chnum(s+1); else n=chnum(s); printf("%d\n",n); } int chnum(char*p) { int sum=0; while(*p!='\0') { if(*p>='0'&&*p<='9') sum=sum*10+*p-'0'; p++; } return sum; } 2、从键盘输入一个字符串,去掉所有非十六进制字符后转换成十进制数输出。读懂以下main函数,编写相应的函数del16和htod。 #include #include void main() { char s1[10],s2[10]; void del16(char*,char*); int htod(char*); gets(s1); //读入一字符串 del16(s1,s2); //去掉所有非十六进制字符到s2 printf("%d\n",htod(s2)); //把s2转换为10进制 }

void del16(char*s1,char*s2){ for(;*s1!='\0';s1++) if(*s1>='0'&&*s1<='9'||*s1>='a'&&*s1<='f'||*s1>='A'&&*s1<='F'){ *s2 = *s1; s2++;} *s2='\0'; } int htod(char*s2){ int sum=0; for(;*s2!='\0';s2++){ if(*s2>='0'&&*s2<='9') sum=sum*16+*s2-'0'; else if(*s2>='a'&&*s2<='f') sum=sum*16+*s2-'a'+10; else if(*s2>='A'&&*s2<='F') sum=sum*16+*s2-'A'+10; } return sum; } 3、编写函数insert(char *s1,char *s2,int pos),实现在字符串s1中的指定位置pos处插入字符串s2。 Happy Year New 7 Happy New Year #include #include int main(void) { void insert(char *s1,char *s2,int pos); char s1[80],s2[80]; int pos; gets(s1); gets(s2); scanf("%d",&pos); insert(s1,s2,pos); puts(s1); return 0; } void insert(char *s1,char *s2,int pos) {

数组及指针 知识点总结

第9章数组 第1课 知识点一 定义一维数组 格式: 类型名数组名[元素个数] 例1 定义一个包含4个整数的数组a int a[4]; 例2 定义一个包含3个双精度数的数组b double b[3]; 注意: C语言中数组的下界从0开始计数。 例如: a[4]的4个元素分别为a[0]、a[1]、a[2]、a[3] 知识点二 一维数组的初始化 用一对大括号将数组的初值括起来。 例1 int a[3]={1, 2, 3}; 此例中a[0]值为1、a[1]值为2、a[2]值为3

例2 int a[5]={0}; 此例中数组a的全部元素值均为0 例3 int a[3]={1, 2, 3, 4}; 此例中由于初值个数多于数组元素个数,所以非法。例4 int a[ ]={0, 0, 0, 0}; 此例中省略数组元素个数,初值为4个0 等价于int a[4]={0}; 注意: 数组名是一个常量值,不能对它赋值。 例如: int a[3]; a=5; 此语句非法,应改为a[0]=5; 知识点三 一维数组应用 例1 从键盘上输入10个整数,输出最大数和最小数。 #include main() { int a[10],i,max,min; printf("请输入10个整数:\n");

for(i=0;i<=9;i++) scanf("%d",&a[i]); max=a[0]; min=a[0]; for(i=1;i<=9;i++) { if(a[i]>max) max=a[i]; if(a[i]

语言程序设计实验答案数组指针与字符串

实验06 数组、指针与字符串(4学时) (第6章数组、指针与字符串) 一、实验目的 二、实验任务 6_1(习题6-25)编写并测试3×3矩阵转置函数,使用数组保存3×3矩阵。 6_2(习题6-26)使用动态内存分配生成动态数组来重新完成上题(n阶方阵),使用指针实现函数的功能。 6_3 编程实现两字符串的连接。要求使用字符数组保存字符串,不要使用系统函数。

6_4 使用string类声明字符串对象,重新实现上一小题。 6_5(习题6-27)声明一个Employee类。 其中包括姓名、街道地址、城市和邮编等属性,以及change_name()和display()等函数。display()显示姓名、街道地址、城市和邮编等属性,change_name()改变对象的姓名属性,实现并测试这个类。 6_6(习题6-27)声明包含5个元素的对象数组,每个元素都是Employee 类型的对象。 6_7 修改实验4中的people(人员)类。 具有的属性如下:姓名char name[11]、编号char number[7]、性别char sex[3]、生日birthday、身份证号char id[16]。其中“出生日期”声明为一个“日期”类内嵌子对象。 用成员函数实现对人员信息的录入和显示。 要求包括:构造函数和析构函数、拷贝构造函数、内联成员函数、聚集。 在测试程序中声明people类的对象数组,录入数据并显示。 三、实验步骤 1.(编程,习题6-25)编写矩阵转置函数,输入参数为3×3整型数组。 使用循环语句实现矩阵元素的行列对调,注意在循环语句中究竟需要对哪些元素进行操作,编写main()函数实现输入输出。程序名:。 参考运行结果:

全国计算机二级:C语言之指针、数组和函数

全国计算机二级:C语言之指针、数组和函数 基本解释 1、指针的本质是一个与地址相关的复合类型,它的值是数据存放的位置(地址);数组的本质则是一系列的变量。 2、数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。 3、当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。 问题:指针与数组 听说char a[]与char *a是一致的,是不是这样呢? 答案与分析: 指针和数组存在着一些本质的区别。当然,在某种情况下,比如数组作为函数的参数进行传递时,由于该数组自动退化为同类型的指针,所以在函数内部,作为函数参数传递进来的指针与数组确实具有一定的一致性,但这只是一种比较特殊的情况而已,在本质上,两者是有区别的。请看以下的例子: char a[] = "Hi, pig!"; char *p = "Hi, pig!"; 上述两个变量的内存布局分别如下: 数组a需要在内存中占用8个字节的空间,这段内存区通过名字a来标志。指针p则需要4个字节的空间来存放地址,这4个字节用名字p来标志。其中存放的地址几乎可以指向任何地方,也可以哪里都不指,即空指针。目前这个p指向某地连续的8个字节,即字符串“Hi, pig!”。 另外,例如:对于a[2]和p[2],二者都返回字符‘i’,但是编译器产生的执行代码却不一样。对于a[2],执行代码是从a的位置开始,向后移动2两个字节,然后取出其中的字符。对于p[2],执行代码是从p的位置取出一个地址,在其上加2,然后取出对应内存中的字符。 问题:数组指针 为什么在有些时候我们需要定义指向数组而不是指向数组元素的指针?如何定义? 答案与分析: 使用指针,目的是用来保存某个元素的地址,从而来利用指针独有的优点,那么在元素需要是数组的情况下,就理所当然要用到指向数组的指针,比如在高维需要动态生成情况下的多维数组。 定义例子如下: int (*pElement)[2]。

c数组指针题含答案

数组指针01:逆序输出 从键盘输入n个整数(n<100),存放在一个一维数组中,逆序输出能被3整除的元素,并逆序输出数组下标为3的倍数的元素。 输入格式:第一个整数为个数n,后续为n个整数 输出格式:第一行能被3整除的元素,第二行为下标为3的倍数的元素,各个数值之间用空格分隔。 输入:10 2 7 9 10 5 4 3 6 8 20 输出: 6 3 9 20 3 10 2 #include using namespace std; const int MAX=100; int main() { int a[MAX],n,i; cin>>n;

for(i=0;i>a[i]; for(i=n-1;i>=0;i--) if(a[i]%3==0) cout<=0;i--) if(i%3==0) cout<

输出格式:下标为3的倍数的元素,各个数值之间用空格分隔。输入:10 2 7 9 10 5 4 3 6 8 20 输出:20 3 10 2 #include using namespace std; const int MAX=100; int main() { int a[MAX],b[MAX],n,i; cin>>n; for(i=0;i>a[i]; b[n-1-i]=a[i]; } for(i=0;i

C语言中指针、数组和引用例子实例

一、指针:内容是指示一个内存地址的变量;类型是指示编译器怎么解释指针内容指向地址中的内容,以及该内存区域有多大; 例子: [cpp] int i = 0; int * pi = &i; printf(“pi = %x \n”, pi); // 打印pi的内容: 0x2000 printf(“*pi= %d \n” , *pi); // 打印pi指向地址中的值: 5 printf(“&pi= %x \n”, &pi); // 打印pi的地址: 0x100 从汇编的角度来看,指针是这样的: int i = 0; 010E139E mov dword ptr [i],0 int * pi = &i; 010E13A5 lea eax,[i] 010E13A8 mov dword ptr [pi],eax 二、数组:是一个单一数据类型对象的集合。其中单个对象没有被命名,通过索引访问。 数组名和指针的区别:数组名的内涵在于其指代实体是一种数据结构,这种数据结构就是数组。数组名的外延在于其可以转换为指向其指代实体的指针,而且是一个指针常量。指向数组的指针则是另外一种变量类型,仅仅意味着数组的存放地址 注意:虽然数组名可以转换为指向其指代实体的指针,但是它只能被看作一个指针常量,不能被修改,如下:天骄无双:https://www.doczj.com/doc/ad7972046.html, [cpp] int intArray[10]; intArray++; // 错误 “指针和数组等价”说的是什么?索引操作相同,例如:p[2]; a[2]; 三、引用(reference)是一个对象的别名。用对象初始化引用后,对象的名字和引用都指向该对象; 引用是如何实现的?从汇编语言的角度来看,指针和引用是一样的: [cpp] int i = 0; 00E9139E mov dword ptr [i],0 int & ref = i; 00E913A5 lea eax,[i] 00E913A8 mov dword ptr [ref],eax int * pi = &i; 00E913AB lea eax,[i] 00E913AE mov dword ptr [pi],eax 指针和引用的区别(从C++使用角度来看): 不存在空引用 引用要初始化 引用初始化后,不能指向另一个对象 这是由编译阶段保证的。 备注:一个指向非常量的引用不能用字面值或者临时值初始化;但是一个指向常量的引用可以。天骄无双:https://www.doczj.com/doc/ad7972046.html,

C语言指针数组函数练习(含参考答案)

作业(使用指针、数组、函数完成) 1. 编写一个通用函数,该函数可以实现判断:一个含有五位数字的整数是否是回文数。回文数的含义是从左向右与从右向左看,数是相同的。如:23732是回文数,而23564则不是。编写主程序调用该函数实现求所有5位数字中满足条件的数的个数。 #include int Judge(int num) { int w,q,b,s,g; w=num/10000; q=num%10000/1000; s=(num%100)/10; g=num%10; if((w==g)&&(q==s)) return 1; else return 0; } void main() { int count=0; int i; for(i=10000;i<=99999;i++) if(Judge(i)) count++; printf("%d\n",count); } 2.编写一个通用函数,该函数可以实现对数值型数组的倒序。倒序的含义是把数组的元素值前后颠倒。例数组:20,19,18,15,13,10倒序的结果为:10,13,15,18,19,20。编写主程序,数组初始化方式不限,并输出,然后调用该函数实现倒序后再输出倒序的结果。#include #define N 6 void Transfer(double *b,int n) { double temp; double *i=b; double *j=b+n-1; while(j>i) { temp=*i; *i=*j; *j=temp; i++;

j--; } } void main() { double array[N]={20,19,18,15,13,10}; int i; for(i=0;i #include double Cal(double *p,int n) { int i,j; double sum=0; for(i=0;i

计算机二级c语言第九章 数组和指针习题与答案

第九章数组和指针 1、有以下程序 main() { int a[]={2,4,6,8,10}, y=0, x, *p; p=&a[1]; for(x= 1; x< 3; x++) y += p[x]; printf("%d\n",y); } 程序运行后的输出结果是 A)10 B)11 C)14 D)15 2、有以下程序 void sum(int a[]) { a[0] = a[-1]+a[1]; } main() { int a[10]={1,2,3,4,5,6,7,8,9,10}; sum(&a[2]); printf("%d\n", a[2]); } 程序运行后的输出结果是 A)6 B)7 C)5 D)8 3、有以下程序 main() { int p[8]={11,12,13,14,15,16,17,18},i=0,j=0; while(i++< 7) if(p[i]%2) j+=p[i]; printf("%d\n",j); } 程序运行后的输出结果是 A)42 B)45 C)56 D)60 4、设有定义语句 int x[6]={2,4,6,8,5,7},*p=x,i; 要求依次输出x数组6个元素中的值,不能完成此操作的语句是 A)for(i=0;i<6;i++) printf("%2d",*(p++)); B)for(i=0;i<6;i++) printf("%2d",*(p+i)); C)for(i=0;i<6;i++) printf("%2d",*p++); D)for(i=0;i<6;i++) printf("%2d",(*p)++); 5、有以下程序 #include < stdio.h > main() { int a[]={1,2,3,4,5,6,7,8,9,10,11,12,},*p=a+5,*q=NULL; *q=*(p+5); printf("%d %d\n",*p,*q); } 程序运行后的输出结果是 A)运行后报错 B)6 6 C)6 11 D)5 10

第七章字符数组与指针练习题参考答案

第七章字符数组与字符串 【题7.29】下面是对s的初始化,其中不正确的是。 A)char s[5]={“abc”};B)char s[5]={‘a’,‘b’,‘c’}; C)char s[5]=“”;D)char s[5]=“abcdef”; 【题7.30】下面程序段的运行结果是。 char c[5]={‘a’,‘b’,‘\0’,‘c’,‘\0’}; printf(“%s”,c); A)‘a’‘b’ B)ab C)ab c 【题7.31】对两个数组a和b进行如下初始化 char a[]=“ABCDEF”; char b[]={‘A’, ‘B’,‘C’,‘D’,‘E’,‘F’}; 则以下叙述正确的是。 A)a与b数组完全相同B)a与b长度相同 C)a和b中都存放字符串D)a数组比b数组长度长 提示:‘\0’是字符串结束的标志 【题7.32】有两个字符数组a、b,则以下正确的输入格式是。 A)gets(a,b); B)scanf(“%s %s”,a,b); C)scanf(“%s %s”,&a,&b);D)gets(“a”),get(“b”); 【题7.33】有字符数组a[80]和b[80],则正确的输出形式是。 A)puts(a,b); B)printf(“%s %s”,a[],b[]); C)putchar(a,b); D)puts(a),puts(b); 【题7.34】下面程序段的运行结果是。 char a[7]=“abcdef”; char b[4]=“ABC”; strcpy(a,b); printf(“%c”,a[5]); A)空格B)\0 C)e D)f 提示:复制后a[0]=‘A’,a[1]=‘B’,a[2]=‘C’,a[3]=‘\0’, a[4]=‘e’,a[5]=‘f’, a[6]=‘\0’,

C语言数组指针的小例子

1、功能:输入6个学生的5门课程成绩,计算出每个学生的平均分和每门课程的平均分。 2、C语言实现代码:(其实就是用二维数组来实现的,二维数组的引用传递使用数组指针来完成) 复制代码代码如下: #include <stdio.h> #define STUDENT 5 #define SCORE 6 void input_array(float (*score)[STUDENT]); void avg_score(float (*score)[STUDENT]); void avg_course(float (*score)[STUDENT]); /** * calculate student average score and course average socore. */ int main(){ float a[SCORE][STUDENT]; input_array(a); avg_course(a); avg_score(a); } void input_array(float (*score)[STUDENT]){ int i, j; for(i=0; i<SCORE; i++){ printf("input the %d student score:", i+1); for(j=0; j<STUDENT; j++){ scanf("%f", score[i] + j); } } } void avg_course(float (*score)[STUDENT]){ int i,j; float s; for(j=0; j<STUDENT; j++){ printf("course%d ", j); } printf("n"); for(i=0; i<SCORE; i++){ s=0; for(j=0; j<STUDENT; j++){ printf("%f ", *(score[i] + j)); s += *(score[i] + j); }

实验三 数组与指针实验

实验三数组与指针实验 【实验目的】 1.学习使用数组数据对象。 2.掌握指针的使用方法。 3.学习通过动态内存分配实现动态数组的定义和使用,并体会指针在其中的作用。4.练习通过Debug观察指针的内容及其所指对象的内容。 【实验内容】 1.运行下列程序,观察运行结果。 (1)#include class ArrayElem { int x; public: ArrayElem(int i){x=i;} //带参数的构造函数 int getx(){return x;} }; int main() { ArrayElem obs[4] ={-1,-2,-3,-4}; //创建对象数组并初始化 for(int i=0;i<4;i++) cout<<"obs["< class NumClass { int num; public: void set_num(int val){num=val;} void show_num(){cout<<"The num is :"<set_num(20);p->show_num(); //通过指针调用成员函数 return(0); } (3)#include class NumClass

变量的指针和指针变量的区别是什么

2变量的指针和指针变量的区别是什么。 答;一个变量的地址指出了变量的存储单元在内存中的具体位置,能对变量进行存取操作。这个变量的地址就是变量的指针。指针是一种具有特殊意义的整型数,指针不能存放在一般的整型变量中,必须存放在专门指针的变量中,这类变量就是指针变量。 3 一维数组元素的引用有哪些方式。 答;下标法、地址法、指针法 4 2维数组列地址有哪些计算方法。 答;1 根据数组元素所在的行计算出行地址,然后把行地址转换成行中首元素的地址,再根据数组元素所在的列计算数组元素的地址。 2 根据2维数组的数组元素在存储空间上按行连续存放的特点,每个数组元素的地址等于2维数组元素的首元素地址加上该数组元素相对于首元素位置的偏移量。 3把2维数组的每一行当作一个一维数组,用一维数组元素地址的计算方法计算相应的2维数组元素的地址。 第9章结构体与共用体 1 什么是链表。其中单向链表具有哪些特点。 答;链表是若干个同样类型的结构通过依次串接方式构成的一种动态数据结构。链表中的每一个结构体数据成为结点,链表可以分成单向链表和双向链表 单向链表的特点;1 链表中的结点数据可以改变的 2 结点占用的内存是动态分配内存和动态释放内存函数。 2 对单向链表的常用操作有哪些。 答;对单向链表的常用操作有建立、显示、插入,删除和查找。 3 什么是共用体。 答;共用体是一个集合体。它的各个成员的数据类型可以是不相同的,所有成员共享同一段存储空间,存储空间的大小取决存储单元最大的成员的数据类型。 4 指向结构体类型变量的指针变量引用形式有哪些。 答;有两种形式;【星号指针变量名】。成员名和指针变量名-大于号成员名。 第10章位运算及编译预处理 1 C提供的编译预处理功能有哪些。如何实现。 答;功能有三种;宏定义、文件包含和条件编译,分别用宏定义命令、文件包含命令、条件编译命令实现。 2 文件包含的基本功能是什么。 答;文件包含处理是一个源文件可以将另一个源文件的全部内容包含到本文件中来,作为本文件的一部分,这可以节省程序设计人员的重复劳动。 【3【在C语言中提供了几种什么样的位运算符。 答;-、小于小于、大于大于、 4 文件包含需要注意哪些问题 答;一个井include命令只能指定一个被包含文件,包含多个文件侧需多个井include命令;文件包含可以嵌套,即一个被包含文件中可以包含另一个被包含的文件;在井include命令中,文件名可以用双引号或尖括号括起来。 第11章文件 1 文件的结束标志有哪些。 答;每个文件都有一个结束标志。当文件的位置指针移到文件的结束标志处时,表示文件结束。如何测试文件是否结束,常有2种方法 1 ASCII码文件的结束标志用【-1】表示。

C语言程序设计 实验8.1 指针与数组

实验8.1 指针与数组 题目信息表 序号题目名称题目满分题目得分题目编号 1 循环移动(调试示例error08_1) 2 在数组中查找指定元素 3 使用函数的选择法排序 4 报数 1 循环移动(调试示例error08_1) #include int main(void) { int i, m, n,k,j; int a[80]; scanf("%d%d", &n, &m); for(i = 0; i < n; i++) scanf("%d", &a[i]); for(i=0;i0;j--) a[j]=a[j-1]; a[0]=k; } /*-----程序填空,不要改变与输入输出有关的语句。 输入两个正整数n 和m (1

printf("\n"); return 0; } 2 在数组中查找指定元素 #include int main(void) { int i, n, res, x; int repeat, ri; int a[10]; scanf("%d", &repeat); for(ri = 1; ri <= repeat; ri++){ scanf("%d", &n); for(i = 0; i < n; i++) scanf("%d", &a[i]); scanf("%d", &x); res=-1; for(i=0;i

指针与数组 函数的组合

指针和数组 ? ? 1.指针数组:是其数组元素为指针的数组。记住:是一个存放着指针的数组,而不是一个指针 ?定义格式为:数据类型* 数组名[数组长度] ?如:int * a[10] ; [ ]的优先级高于*,意味着使得a是一个指针数组,表示具有10个元素的数组,每个元素是一个指向int 型的指针。 ? ?2,指向数组的指针:是一个指针,指向的是一个数组。 ?定义格式为:数据类型(*数组名) [数组长度] ?如:int (*a) [10];*先于a 结合,意味着a 是一个指针,指向具有10个int 值的数组, ? ? ?指针与函数 ? ?1, 函数的指针:首先它是一个指针,指向函数的入口地址;在C语言中,函数名就是来标识函数的入口地址。 ?与指向数组的指针不同,在数组中,可以对数组中的元素访问,可以进行算术运算。 而在函数中,只需考虑函数的入口地址,而不考虑函数中某具体指令或数据所在存 储单元的地址,即不能进行算术运算 ?定义格式:存储类型数据类型(*函数名) ( ) ?如:static int (*p) (); ?存储类型表示函数在文件中的存储方式 ?数据类型表示被指函数的返回值的类型 ?最后的空括号表示指针变量所指的是一个函数 ? ?如何用指向函数的指针变量的方式来调用相应的函数: ?1), 使用前,必须先定义并赋值 ?2), 指向函数的指针定义形式中的数据类型必须和赋给它的函数返回值类型相同 ?3), 指向函数的指针只能指向函数的入口,而不能使用*(p+1) 来表示函数的下一命令?4), 在函数指针赋值时,只需给出函数名而不需给参数,如p = max; ?5), 调用时,只需将(*p) 代替函数名即可,在p 后面的括号中根据需要写上实参,如: c = (*p) (a,b) ; ?如下程序:求直角三角形的斜边 ?#include ? #include ?main() ?{ ? int a ,b ,c , f() , (*f1)(); ? a = 3; b = 4;

指向字符串的指针数组

在初学习C语言时,对于指针是最容易让人迷糊的,尤其对于指针数组,而且是指向字符串的指针数组,恐怕就更难理解了。下面本人给出一个例子,详细讲解指向字符串的指针数组的使用情况。希望给予学习C的朋友一点帮助。 下述程序执行后,输出结果是什么? #include char *p[2][3]={ "abc","defgh","ijkl","mnopqr","stuvw","xyz"}; main(){ printf("%c\n",***(p+1)); printf("%c\n",**p[0]); printf("%c\n",(*(*(p+1)+1))[4]); printf("%c\n",*(p[1][2]+2)); printf("%s\n",**(p+1)); } 答案是: m a w z mnopqr 答案解析: 这里相当于定义了2行3列共6个元素的数组,数组的每一个元素都是指向字符的指针变量。 其中p[0][0]指向串"abc",p[0][1]指向串"defgh",p[0][2] 指向串"ijkl",p[1][0]指向串"mnopqr",p[1][1]指向串"stuvw",p[1][2] 指向串"xyz"。 1、printf("%c\n",***(p+1)); 这里的***(p+1)相当于*(*(*(p+1)+0)+0),而*(*(p+1)+0)+0)的另一种容易懂的形式是p[1][0],在多维数组中这两种写法等价。如上面所写的p[1][0]是指向串"mnopqr",即保存的是串"mnopqr"的首地址,也即字母m的地址。因此***(p+1)是字母m 2、printf("%c\n",**p[0]); 这里的**p[0]等价于*(*(*(p+0)+0)+0),也即*(p[0][0]),而p[0][0])指向串"abc",所以*(p[0][0])是字符a 3、printf("%c\n",(*(*(p+1)+1))[4]); (*(*(p+1)+1))[4]等价于*((p[1][1])+4),而(p[1][1])指向串"stuvw",所以*((p[1][1])+4)是在串首向后移动4个单位的字符,也即w 4、printf("%c\n",*(p[1][2]+2)); 因为p[1][2]指向串"xyz",而p[1][2]+2 就是串首向后移动2个字节(一个字节保存一个字符),也就是指向字符z,所以*(p[1][2]+2)是字符z

C语言 数组和指针练习题

若当堂没做完,下周四之前上交也可。 至ftp://211.64.82.253/ 用户名和密码:stu C语言程序设计练习题——数组 一、选择题 77、以下对一维数组a的正确说明是_d ___ A、char a(10); B、int a[ ]; C、int k=5,a[k]; D、char a[ ]={'a' , 'b' , 'c'}; 78、若有说明语句:int a[2][4];,则对a数组元素的正确引用是_a___ A、a[0][3] B、a[0][4] C、a[2][2] D、a[2][2+1] 79、以下能对二维数组y进行初始化的语句是_b__ A、static int y[2][ ]={{1,0,1}, {5,2,3}}; B、static int y[ ][3]={{1,2,3}, {4,5,6}}; C、static int y[2][4]={{1,2,3}, {4,5} , {6}}; D、static int y[ ][3]={{1,0,1,0}, { }, {1,1}}; 80、若有说明语句:int y[ ][4]={0,0};则下面叙述不正确的是_d___ A、数组y的每个元素都可得初值0 B、二维数组y的行数为1 C、该说明等价于int y[ ][4]={0}; D、只有元素y[0][0]和y[0][1]可得到初值0,其余元素均得不到初值0 81、以下各组选项中,均能正确定义二维实型数组s的选项是_c___ A、float s[3][4]; B、float s(3,4); float s[ ][4]; float s[ ][ ]={{0};{0}}; float s[3][ ]={{1},{0}}; float s[3][4]; C、 float s[3][4]; D、float s[3][4]; static float s[ ][4]={{0},{0}}; float s[3][ ]; auto float s[ ][4]={{0},{0},{0}}; float s[ ][4]; 82、若有说明语句:int a[ ][3]={1,2,3,4,5,6,7,8}; ,则a数组的行数为__a__ A、3 B、2 C、无确定值 D、1 83、若二维数组y有m列,则在y[i][j]前的元素个数为_B___ A、j*m+i B、i*m+j C、i*m+j-1 D、i*m+j+1 84、下面程序中有错误的行是__D__ 1、 main( ) 2、 { 3、 int x[3]={1}; 4、 int k; 5、 scanf("%d", &x); 6、 for (k=1; k<3; k++) 7、 x[0]=x[0]+x[i]; 8、 printf("x[0]=%d\n", x[0]); 9、 } A、3 B、6 C、7 D、5 85、若有以下语句,则正确的描述是__b__ char x[ ]="12345"; char y[ ]={'1', '2', '3', '4', '5'}; A、x数组与y数组的长度相同 B、x数组长度大于y数组长度 C、x数组长度小于y数组长度

一维数组与指针

指 针 1、 概述 1.1 地址和指针的概念 如果在C 语言中定义一个变量,系统会自动的给它存储空间。比如:int a,b,c;系统会自动的给a,b,c 分别分配2个字节的空间,内存中的表示如下图: 这样以来,就建立了变量和地址的对应关系。如果产生赋值行为,比如:a=1,b=3;,存储图如下: 如果产生具体的操作,比如:c=a+b ,具体的过程如下: 第一步:从2001-2002字节空间取出1; 第二步:从2003-2004字节空间中取出3; 第三步:将1和3相加后的结果4存入变量C 所指向的地址空间(2005-2006),图例如下: a b c a b c

以上的程序,在C 语言中称为“直接访问”。 既然有“直接访问”,肯定会存在“间接访问”,举例如下: 张三出差,住宾馆,房间号码为1001,从携带钥匙的方式上来看,有两种方式: 1、 钥匙自己带(直接方式); 2、 钥匙放在总台上,要开门,先到总台拿钥匙,而后开门(间接方式) 以上是生活中的例子,那么,在C 程序中,如何表示这种“间接方式”呢? 第一步:定义一个普通的变量并赋值(int a=3;) 第二步:定义一种变量,用来存储变量a 的地址(a_pointer ); 第三步:建立该变量和普通变量之间的联系,将变量a 的地址存储到a_pointer 中。 第四步:通过该变量(a_pointer )来访问a; 程序如下: b c

一种示意图: 以上的图形象的表示了一种“指向关系”。 “*”,表示指向。 在C 语言中,一个变量的地址被称为该变量的“指针”,存储该变量地址的“东东”,称为指针变量。 故,指针是一个地址,而指针变量是存放该地址的变量,它用来指向“指针”所表示的地址。 1.2 指针变量的定义和使用 定义格式: 数据类型(基本型) *指针变量 比如:int *pointer_1;指针变量是pointer_1,而不是*pointer_1; 有了以上的定义,pointer_1是我们定义的指针变量,*pointer_1是具体的内容。 从以上程序来看,*pointer_1和i 是一回事。 到此为止,我们已经知道了指针变量的定义,既然变量定义了,就要使用,如何使用呢?

相关主题
文本预览
相关文档 最新文档