第9章 数组类型_第1页
第9章 数组类型_第2页
第9章 数组类型_第3页
第9章 数组类型_第4页
第9章 数组类型_第5页
已阅读5页,还剩76页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第9章数组类型

9.1一维数组9.2二维数组9.3数组和函数9.4字符数组9.5指针数组9.1一维数组一维数组的定义一维数组的定义格式为:存储类型数据类型数组名[数组长度];例如,语句“floata[6],b[10];”说明:数组的存储类型可以是auto或static,但不能为register。数组的数据类型既可以是基本类型,也可以是构造类型等。数组名应符合标识符的命名规则,数组名代表的不是整个数组,而是数组所占内存空间的起始地址。数组长度表示数组元素的个数。数组长度只能是整型常量或整型常量表达式。C编译系统为数组分配连续的内存单元。数组元素的相对次序由下标来表示。数组元素的下标是从0开始的整数。9.1一维数组一维数组的引用在C语言中不能引用整个数组,只能引用单个数组元素。一个数组元素就是相当于一个变量,它的使用与同类型的普通变量是相同的。一维数组元素的引用形式为:数组名[下标]数组名后方括号内是数组下标,下标表示该元素是数组的第几个元素。数组名后面的方括号内的内容只有在数组定义时才是数组的长度,其他时候都是数组下标。数组元素的下标是整型的常量、变量或表达式。下标的取值范围是[0,数组长度-1]的整型值。C程序运行时,编译系统并不检查数组元素的下标是否越界,需要编程人员自己保证数组元素的下标不要越界。9.1一维数组一维数组的初始化如果在数组定义之后进行初始化操作,则只能对每个数组元素一一赋值。intarr[10],i;for(i=0;i<10;i++)arr[i]=i;如果在定义数组时完成数组的初始化操作,则需要将数组元素的初值依次放在一对花括弧中,并用赋值号与数组连接。定义数组时赋初值的形式为:存储类型数据类型数组名[数组长度]={初值列表};花括弧内各个初值之间用逗号分隔,数值类型必须与数组类型一致。系统将按初值的排列顺序,顺次给数组元素赋值。例如,语句“intarr[10]={0,1,2,3,4,5,6,7,8,9};”花括弧中初值的数量必须小于等于数组长度。当初值数量小于数组长度时,数值型数组的后面没有初值的元素由系统自动赋值为0。9.1一维数组若给数组的所有元素赋初值,可以省略数组的长度。系统会根据所赋初值的个数确定数组的长度。例如,intarr[]={1,2,3,4,5,6,7,8,9};如果是auto存储类型的数组未赋初值,数组元素的值是不确定的。而static存储类型的数值型数组未赋初值,编译系统会在编译时将元素全部初始化为0。9.1一维数组一维数组应用举例【例9.1】求100个整数的平均值。#include“stdio.h”main(){inta[100],i;floatave,sum;printf("pleaseenter100numbers:\n");for(i=0;i<100;i++) /*输入元素*/

scanf("%d",&a[i]);for(sum=0,i=0;i<100;i++) /*求和*/

sum=sum+a[i];

ave=sum/100;

/*求平均值*/

for(i=0;i<100;i++)printf("%6d",a[i]);

printf("\naverage=%7.2f",ave);}9.1一维数组【例9.2】编写程序,找出10个整数中的最小值及其位置。解题思路:首先输入10个整数,然后找出其中的最小值及其位置,最后输出结果。其中最主要的功能是求最小值及其位置,完成这一功能的主要步骤为:①假定最小值为第一个数,也就是位置min为0;②将min位置的数和数组的下一个数进行比较,如果min位置上的数大,则更改min值为更小数的位置;③如果比较完数组中所有的数,位置min上的数就是最小值,否则转向②继续执行。假设数组x的10个数依次为3、2、7、1、4、8、5、11、4、9,则寻找最小值及其位置的过程应该为:9.1一维数组9.1一维数组#include"stdio.h"main(){intx[10],i,min;

printf("pleaseenter10numbers:");

for(i=0;i<10;i++)/*输入10个元素*/

scanf("%d",&x[i]);

min=0;

/*给min置初值*/

for(i=1;i<10;i++)/*从第1个元素开始查找最小值位置*/

if(x[i]<x[min])min=i;

printf("minimumisx[%d]=%d",min,x[min]);/*输出最小值*/}输入3、2、7、1、4、8、5、11、4、9的程序运行结果为:pleaseenter10numbers:32714851149↙minimumisx[3]=19.1一维数组【例9.3】采用选择法对数列进行排序。解题思路:选择法排序(设对N个数进行排序)是每次从待排序数据中选择最小的数,与相应位置上的数交换。假设待排序的数列存放在一维数组a中,且找最小值位置的方法同例9.2,则选择法排序的过程为:第一次从N个元素(a[0]到a[N])中找到最小值位置min,如果min不等于0,将a[min]与a[0]交换;第二次从剩下的N-1个元素(a[1]到a[N])中找到最小值位置min,如果min不等于1,将a[min]与a[1]交换,……,直至第N-1次从最后两个数(a[N-2]到a[N-1])中找到最小值位置min,如果min不等于N-2,将a[min]与a[N-2]交换9.1一维数组9.1一维数组假设数组a有10个数据,依次为3、2、7、1、4、8、5、12、45、9,则排序过程为:第一趟排序(i=0)的过程中,找到的a[0]到a[9]10个元素中的最小元素下标放在min中:327148512459

min=3127348512459min!=0,交换a[0]与a[3]第二趟排序(i=1)过程中,找到的a[1]到a[9]9个元素中的最小元素下标放在min中:127348512459min==1,元素已在合适的位置,不需交换。第三趟排序(i=2)过程中,找到的a[2]到a[9]8个元素中的最小元素下标放在min中:127348512459min=3123748512459min!=2,交换a[2]与a[3]依此类推,在经过九趟排序后得到有序序列:1234578912459.1一维数组#defineN10#include"stdio.h"main(){inta[N],i,j,min,temp;printf("pleaseenter%dnumbers:",N);for(i=0;i<N;i++) /*输入数列*/scanf("%d",&a[i]);for(i=0;i<N-1;i++)/*N-1趟排序*/{min=i;for(j=i+1;j<N;j++)/*查找最小值,让min指向它*/

if(a[j]<a[min])min=j;if(min!=i)/*若最小值未在第i个位置,交换a[i]、a[min]*/{temp=a[i];a[i]=a[min];a[min]=temp;}}

9.1一维数组printf("thesortedarrayis:\n");/*输出排序后的数列*/

for(i=0;i<N;i++)printf("%6d",a[i]);}【例9.4】在递减的有序数列中,插入一个数x,使得数列仍然有序(如果有相同的数则不插入)。和前面的例题一样,用数组存放数列。则本题相当于在一个有序的数组中寻找合适的位置插入一个元素。问题的解决可分为两个步骤:①寻找插入位置:由于是非递增序列,所以插入位置应该是在第一个小于x的数组元素的前面(假定找到的位置为k);②如果第k个元素等于x,则不须插入,否则执行插入操作:a. 第k个元素及其后面的元素都后移一位。b. 插入元素在k位置。9.1一维数组#defineN11#include"stdio.h"main(){intarr[N],x,j,k;printf("\npleaseenterthearray(%d):",N-1);for(j=0;j<N-1;j++)scanf("%d",&arr[j]);/*输入数组元素*/

printf("pleaseenterthenumber:");scanf("%d",&x);/*输入待插入元素*/

for(j=0;x<arr[j]&&j<N-1;j++);/*寻找插入位置*/

k=j;/*k记录插入位置*/

9.1一维数组

if(arr[k]==x&&k<N-1)/*数已经存在,不执行插入操作,原样输出数组*/

for(j=0;j<N-1;j++)printf("%4d",arr[j]);else{for(j=N-2;j>=k;j--)arr[j+1]=arr[j];/*移动插入位置以后的元素*/

arr[k]=x;

/*插入元素*/

printf("thearrayis:\n");for(j=0;j<N;j++)printf("%4d",arr[j]);/*输出数组*/}}某次程序运行结果为:pleaseenterthearray(10):6743393330282615107↙pleaseenterthenumber:27↙thearrayis:6743393330282726151079.1一维数组一维数组和指针数组元素的地址数组元素的地址也可用元素前面加地址操作符的方式来获得:

&数组名[下标]数组名C语言规定数组名代表数组的首地址,是一个地址常量。一维数组的数组名是基类型为数组元素类型的指针类型。可以通过数组名来表示数组元素的地址,还可以指针方式引用数组元素。设a为一维数组的数组名,则:a+i表示数组第i个元素的地址(和&a[i])等价),a+0和a是等价的。*(a+i)表示数组的第i个元素。9.1一维数组【例9.5】输入一个有10个数的数列,然后输出。注意数组的引用形式。#include"stdio.h"main(){inta[10],i;printf("pleaseenterthe10number:");

for(i=0;i<10;i++)/*输入数组元素*/

scanf("%d",a+i);

for(i=0;i<10;i++)/*输出数组元素*/

printf("%3d",*(a+i));}程序运行结果:pleaseenterthe10number:9876543210↙98765432109.1一维数组指向数组元素的指针变量一维数组定义之后,可以定义指针变量指向该数组的元素。通过指针变量可以对数组元素进行操作。语句“inta[10],*p=a;”之后,数组元素a[i]可以有四种方式表示:①a[i]②p[i]③*(a+i)④*(p+i)而数组元素a[i]的地址也相应有四种方式表示:①&a[i]②&p[i]③a+i④p+i指针变量的值是可以变化的,所以既可引用指针变量的值,也可重新给它赋值。例如,若p的值是&a[1],那么下面的操作均合法:p++、++p:表示指针变量p向后移动一个数组元素的存储单元,相当于p=&a[2];p--、--p表示指针变量p向前移动一个数组元素的存储单元,相当于p=&a[0]。9.1一维数组p+x、p-x(x表示某个整型的变量、常量或表达式)分别表示以指针变量p为基准向后、向前移动x个数组元素的存储单元,例如p+2表示&a[3],p-1表示&a[0]。p-q(p、q是指向同一个数组的数组元素的指针变量,否则无意义)表示这两个指针变量所指向数组元素的下标之差,例如q=&a[0];则p-q的值为1。指向同一个数组的数组元素的指针变量以及该数组的数组名之间可以进行比较,比较的是地址值大小。因此,p<a的值为真,p>a的值为真,p==a的值为假,p!=a的值为真。可利用指针间的关系做数组操作的循环条件。9.1一维数组【例9.6】输入一个有10个数的数列,然后输出。#include"stdio.h"main(){inta[10],*p,*q;

printf("pleaseenterthe10number:");

for(p=a;p<a+10;p++)/*输入数组元素scanf("%d",p);*/

for(p=&a[0],q=a+10;p<q;p++)/*输出数组元素*/printf("%3d",*p);}

*(p++)表示先取p所指向的数组元素的值作为表达式的值,再将指针变量p向后移动一个数组元素的存储单元;*(--p)表示先将指针变量p向前移动一个数组元素的存储单元,再取p所指向的数组元素的值作为表达式的值。9.1一维数组【例9.7】输入一个有10个数的数列,然后按正序、逆序分别输出。#include"stdio.h"main(){inta[10],*p,*q;printf("\npleaseenterthe10number:");for(p=a;p<a+10;)/*输入数组元素*/

scanf("%d",p++);for(p=&a[0],q=a+10;p<q;)/*正序输出数组元素*/

printf("%3d",*(p++));

printf("\n");for(p=a+9;p>=a;)/*逆序输出数组元素*/

printf("%3d",*(p--));}pleaseenterthe10number:0123456789↙012345678998765432109.2二维数组二维数组的定义二维数组定义的具体格式为:存储类型数据类型数组名[长度1][长度2];例如,语句“staticintb[4][3];”

二维数组定义中,数组名、数据类型、存储类型的定义方式以及数组长度类型的选取和一维数组相同,不同的只是数组名后面紧跟两个方括号,定义了两个长度。二维数组定义中的第一个长度说明数组的数据行数,第二个长度说明每行的数据个数。数组的元素个数就是两个长度之积。二维数组只是在逻辑上是二维的,从存储上看,二维数组仍是一维线性空间。C语言中,按照行优先方式存储二维数组,即先存放第0行的元素,再存放第1行的元素……;同一行中再按列顺序存上面定义的b在内存中的存储示意图如图9.2二维数组二维数组的引用只能引用二维数组的单个数组元素,不能引用整个数组。二维数组元素的引用形式为:数组名[下标1][下标2]二维数组的下标可以是整型的变量、常量或表达式。第一维下标的取值范围是[0,第一维长度-1],第二维下标的取值范围是[0,第二维长度-1]。9.2二维数组二维数组的初始化定义之后进行数组的初始化操作,则只能对每个数组元素一一赋值,intarr[4][10],i,j;for(i=0;i<4;i++)for(j=0;j<10;j++)

arr[i][j]=0;如果在定义数组时完成数组的初始化操作,赋值格式有两种。将数组元素的初值依次放在一对花括弧中并用赋值号与数组连接。具体格式为:存储类型数据类型数组名[数组长度]={初值列表};二维数组花括弧内各个初值之间用逗号分隔,初值类型必须与数组类型一致。系统自动按数组元素在内存的顺序将初值依次赋给相应的元素。若数值型数组的初值数量不足时,将0赋给其余数组元素。例如,语句“intx[2][3]={1,2,3,4,5};”之后,x[0][0]=1,x[0][1]=2,x[0][2]=3,x[1][0]=4,x[1][1]=5。其余元素被自动赋值为0:x[1][2]=0。②赋初值时,每一行的初值放在一个花括号中,所有行的初值再放在一个花括号中。系统将第一个花括号内数据依次赋值给数组的第0行,将第二个花括号内数据依次赋值给数组的第1行,依次类推。具体格式为:存储类型数据类型数组名[数组长度]={{第0行初值列表},{第1行初值列表},…};9.2二维数组

语句“intx[4][4]={{1,2,3,4},{4,5,6},{},{7}};”之后,系统将1、2、3、4依次赋给x[0][0]、x[0][1]、x[0][2]和x[0][3];4、5、6依次赋给x[1][0]、x[1][1]和x[1][2],没有列出x[0][3]的初值,系统自动赋0;对应第2行的“{}”,系统给x[2][0]、x[2][1]、x[2][2]和x[2][3]均赋值0;第3行对应{7},则系统将7赋值给x[3][0],x[3][1]、x[3][2]和x[3][3]均被系统赋值为0。注意:在赋初值时需指定第二维数组长度,可省略第一维的长度。编译系统会根据赋初值的情况,自动得到第一维的长度。语句“intx[][3]={{1,2,3},{4}};”,编译系统可分析出第一维的长度是2。二维数组二维数组应用举例【例9.8】编写程序求一个M行N列的矩阵和一个N行W列的矩阵的乘积。#defineM4#defineN5#defineW4main(){inta[M][N],b[N][W],c[M][W],i,j,k;printf("pleaseenterarraya(%d*%d):\n",M,N);for(i=0;i<M;i++)/*输入第一个矩阵*/

for(j=0;j<N;j++)

scanf("%d",&a[i][j]);

printf("pleaseenterarrayb(%d*%d):\n",N,W);9.2二维数组for(i=0;i<N;i++)/*输入第二个矩阵*/

for(j=0;j<W;j++)scanf("%d",&b[i][j]);for(i=0;i<M;i++)/*两个矩阵相乘,求乘积矩阵中的每一元素*/

for(j=0;j<W;j++){c[i][j]=0;for(k=0;k<N;k++)c[i][j]+=a[i][k]*b[k][j];}

printf("c=a*b:\n");for(i=0;i<M;i++){for(j=0;j<W;j++)printf("%6d",c[i][j]);/*按行输出乘积矩阵*/

printf("\n");}}9.2二维数组【例9.9】编程序查找矩阵的鞍点并输出。矩阵中所谓鞍点就是在其所在行最小,所在列最大的元素。根据鞍点的定义,每行都可能有一个鞍点,所以要逐行查找。查找第i行鞍点的过程可分为两个步骤:①找出第i行最小值的列位置k;②判断第i行第k列元素在第k列是否最大。如果最大则是鞍点;如果不是,则第i行中无鞍点。这里判断是否为最大值的方式是看是否有比a[i][k]大的值。#defineM9#defineN7main(){inta[M][N];inti,j,k,m,flag=0;printf("\npleaseenterarray:\n");for(i=0;i<M;i++)/*输入数组元素*/

for(j=0;j<N;j++)scanf("%d",&a[i][j]);9.2二维数组for(i=0;i<M;i++){k=0;for(j=1;j<N;j++)/*找第i行的最小元素,k为其列标*/

if(a[i][j]<a[i][k])k=j;for(m=0;m<M;m++)/*判断第k列是否有元素比a[i][k]大*/

if(a[m][k]>a[i][k])break;if(m>=M)/*若第k列无元素比a[i][k]大,该元素是鞍点,flag为1表示找到过鞍点*/{flag=1;printf("a[%d][%d]=%d",i,k,a[i][k]);}}if(flag==0)printf("\nnone.");/*整个矩阵不存在鞍点,输出none*/}9.2二维数组二维数组和指针数组元素的地址二维数组数组元素的地址可用数组元素前面加地址操作符的方式来表示:

&数组名[下标1][下标2]数组名二维数组的数组名是二维数组的首地址,是地址常量。二维数组名的基类型不是数组元素的类型,而是一维数组类型,是一个行指针类型。二维数组a的第i行的地址可表示为:①a+i②&a[i]二维数组第i行、第j列的元素地址可表示为:①&a[i][j]②a[i]+j③*(a+i)+j④&a[0][0]+i*4+j⑤a[0]+i*4+j二维数组第i行、第j列的元素可表示为:①a[i][j]②*(a[i]+j)③*(*(a+i)+j)④(*(a+i))[j]⑤*(&a[0][0]+i*4+j)二维数组指向数组元素的指针

定义指向二维数组的指针变量后,就可以通过指向元素的指针来引用二维数组的元素。【例9.10】注意程序中数组元素的引用形式。main(){inta[3][4],*p,*q,i,j;printf("enterarrayis(3x4):\n");for(i=0;i<3;i++)/*输入数组元素*/

for(j=0;j<4;j++)scanf("%d",*(a+i)+j);printf("thearrayis:\n");for(i=0;i<3;i++)/*输出数组元素*/{for(j=0;j<4;j++)printf("%3d",*(*(a+i)+j));printf("\n");}9.2二维数组printf("thearrayis:");for(p=&a[0][0],q=&a[2][3];p<=q;p++)/*输出数组元素*/{if((p-&a[0][0])%4==0)printf("\n");

printf("%3d",*p);}

printf("\nthefirstrankis:\n");/*输出每行第0个数组元素*/for(i=0;i<3;i++)printf("%d\n",*(*(a+i)));}程序的运行结果为:enterarrayis(3x4):1234↙5678↙9865↙9.2二维数组thearrayis:123456789865thearrayis:123456789865thefirstrankis:1599.2二维数组指向二维数组的行指针所谓行指针变量就是用来存放“行”地址的变量,即行指针变量是指向一维数组(一维数组被看作是一个整体)的指针变量,定义形式如下:类型名(*指针变量名)[数组长度];这类指针变量的基类型是一维数组,定义中的类型名是一维数组的类型,数组长度是一维数组的长度。如果行指针p指向二维数组a的第0行,则二维数组a的第i行的地址还可表示为:①p+i②&p[i]第i行、第j列的元素的地址还可表示为:①&p[i][j]②p[i]+j③*(p+i)+j④&p[0][0]+i*4+j⑤p[0]+i*4+j二维数组元素还可表示为:①p[i][j]②*(p[i]+j)③*(*(p+i)+j)④(*(p+i))[j]⑤*(&p[0][0]+i*4+j)二维数组【例9.11】注意程序中数组元素的引用形式。main(){inta[3][4],(*p)[4],*q,i,j;

printf("enterarrayis(3x4):\n");for(p=a,i=0;i<3;i++)/*输入数组元素*/

for(j=0;j<4;j++)scanf("%d",*(p+i)+j);printf("thearrayis:\n");for(p=a,i=0;i<3;i++){for(j=0;j<4;j++)printf("%3d",*(*(p+i)+j));

printf("\n");}9.2二维数组printf("thearrayis:\n");for(p=a;p<a+3;p++)/*输出数组元素*/{for(j=0;j<4;j++)printf("%3d",*(*p+j));printf("\n");}printf("thearrayis:");for(q=*a;q<=&a[2][3];q++)/*输出数组元素*/{if((q-&a[0][0])%4==0)printf("\n");

printf("%3d",*q);}printf("\nthefirstrankis:\n");/*输出每行第0个数组元素*/for(p=a;p<a+3;p++)printf("%d\n",**p);}9.2二维数组程序的运行结果为:enterarrayis(3x4):1234↙5678↙9865↙thearrayis:123456789865thearrayis:123456789865二维数组thearrayis:123456789865thefirstrankis:1599.3数组和函数数组元素作函数实参

数组元素作为实参的使用方法和同类型的普通变量一样。若将数组元素的地址作为实参,则可以在被调用函数中通过指针修改数组元素的值。【例9.12】请分析下列程序的输出结果。#include"math.h"#include"stdio.h"voidabs1(inta){a=abs(a);}voidabs2(int*a){*a=abs(*a);}9.3数组和函数

main(){intx[4]={-1,2,-3,4},k;for(k=0;k<4;k++)abs1(x[k]);for(k=0;k<4;k++)

printf("%5d",x[k]);printf("\n");for(k=0;k<4;k++)abs2(&x[k]);for(k=0;k<4;k++)

printf("%5d",x[k]);}程序的执行结果为:-12-341234

9.3数组和函数数组名作函数参数数组名作函数的参数时,要求形参和实参必须均为数组名或与同类型的指针(地址)。数组名做函数的实际参数时,并不是将所有数组元素的值传递给形参数组,而是传递数组的起始地址给形参。系统只需为形参开辟一个地址的存储空间,用来存放实参传递过来的数组起始地址。因而形参数组使用的是实参数组的存储空间,形参数组的变化会影响实参数组。【例9.13】数组逆置:将数组的第一个元素放到最后一个位置,将第二个元素放到倒数第二个位置……直至最后一个元素放到第一个位置(函数形参和实参都用数组名)。

9.3数组和函数#include"stdio.h"voidinvert(x,n)/*数组置逆函数*/intx[],n;{inti,j,t;for(i=0,j=n/2;i<=j;i++)/*将相应位置上的元素交换*/

{t=x[i];x[i]=x[n-i-1];x[n-i-1]=t;}}main(){inta[10],i;printf("pleaseenterthearray:");for(i=0;i<10;i++)/*输入数组元素*/

scanf("%d",&a[i]);invert(a,10);/*调用置逆函数*/9.3数组和函数

printf("nowthearrayis:");for(i=0;i<10;i++)/*输出数组元素*/

printf("%3d",a[i]);}如果输入1、2、3、4、5、6、7、8、9、10,程序运行结果为:pleaseenterthearray:12345678910↙nowthearrayis:10987654321【例9.14】数组逆置(函数形参用数组名,实参用指针)。#include"stdio.h"voidinvert(intx[],intn)/*数组置逆函数*/{inti,j,t;for(i=0,j=n/2;i<=j;i++)/*将相应位置上的元素交换*/{t=x[i];x[i]=x[n-i-1];x[n-i-1]=t;}}9.3数组和函数main(){inta[10],i,*p=a;printf("pleaseenterthearray:");for(i=0;i<10;i++)scanf("%d",&a[i]);/*输入数组元素*/

invert(p,10);

/*调用置逆函数*/

printf("nowthearrayis:");for(i=0;i<10;i++)/*输出数组元素*/

printf("%3d",a[i]);}9.3数组和函数【例9.15】数组逆置(函数形参用指针,实参用数组名)。voidinvert(int*x,intn)/*数组置逆函数*/{int*i,*j,t;for(i=x,j=x+n-1;i<j;i++,j--)/*将相应位置上的元素交换*/{t=*i;*i=*j;*j=t;}}main(){inta[10],i;printf("pleaseenterthearray:");for(i=0;i<10;i++)scanf("%d",&a[i]);/*输入数组元素*/

invert(a,10);

/*调用置逆函数*/

printf("nowthearrayis:");for(i=0;i<10;i++)/*输出数组元素*/

printf("%3d",a[i]);}9.3数组和函数【例9.16】数组逆置(函数形参和实参都用指针)。voidinvert(int*x,intn)/*数组置逆函数*/{int*i,*j,t;for(i=x,j=x+n-1;i<=j;i++,j--)/*将相应位置上的元素交换*/

{t=*i;*i=*j;*j=t;}}main(){inta[10],i,*p=a;

printf("pleaseenterthearray:");for(i=0;i<10;i++)/*输入数组元素*/

scanf("%d",&a[i]);invert(p,10);/*调用置逆函数*/

printf("nowthearrayis:");for(i=0;i<10;i++)/*输出数组元素*/

printf("%3d",a[i]);}9.4字符数组字符数组的定义和引用一维字符数组的定义格式为:存储类型char数组名[数组长度];例如,语句“staticcharstr1[8];”二维字符数组的定义格式为:存储类型

char数组名[长度1][长度2];例如,语句“charstr2[6][80];”字符数组元素也可通过数组名和下标引用。字符数组也可以在定义时初始化,方法和其他类型的数组一样。若没有对字符数组全部元素赋值,编译系统会对剩余的元素自动赋值为空字符。空字符用'\0'来表示,是ASCII码值为0的字符,表示什么都不做,也不显示。在定义字符数组之后,只能逐个给数组元素赋值。9.4字符数组【例9.17】将一行字符中所有字母替换为在字母表中其后的第三个字母,即a替换为d、b替换为f、c替换为g……,x、y、z分别替换为a、b、c,然后输出。#include"stdio.h"#include"string.h"main(){charstr[80],i;printf("pleaseenterthecharacters:");i=0;while((str[i]=getchar())!='\n')i++;/*输入字符序列,当输入字符为回车时结束*/for(i=0;str[i]!='\n';i++){if(str[i]<='w'&&str[i]>='a')str[i]=str[i]+3;if(str[i]<='z'&&str[i]>='x')str[i]=str[i]-23;if(str[i]<='W'&&str[i]>='A')str[i]=str[i]+3;

9.4字符数组

if(str[i]<='Z'&&str[i]>='X')str[i]=str[i]-23;}for(i=0;str[i]!='\n';i++)/*输出字符序列*/

printf("%c",str[i]);}如果输入“AF5ab#$djaxf!”,程序的运行结果为:pleaseenterthecharacters:AF5ab#$djaxf!↙DI5de#$gmdai!9.4字符数组字符串和字符数组字符串的表示C语言中不保存字符串的长度,在字符串末尾加字符串结束标志空字符‘\0’以表示字符串结束。对于字符串常量,编译系统处理时会自动在字符串末尾处加上‘\0’。因此,含有n个字符的字符串常量在内存中占n+1个字节的空间,第n+1个字节存放‘\0’。字符串常量和字符常量是不同,主要区别有两点:形式不同,字符串常量是用双引号引起来的字符序列,字符序列可以为空,也可以是一个或多个字符;而字符常量是用单引号引起来的单个字符;存储不同,字符串常量要占用(字符串长度+1)个字节;而字符常量占用一个字节空间存放其本身。9.4字符数组

例如,‘s’

在内存保存的是字母s的ASCII码值,占一个字节;而“s”

在内存保存的是字母s和空字符‘\0’的ASCII码值,占两个字节。“”表示空串,在内存中保存的是空字符‘\0’的ASCII码值,占一个字节。“”表示一个含有一个空格的字符串,在内存中占两个字节;‘’表示空格字符,在内存中占一个字节。注意:对于字符串数组,系统不自动添加结束标志‘\0’9.4字符数组【例9.18】从键盘输入一行字符,存放在字符数组中,然后输出。#defineN80#include"stdio.h"main(){charstr[N];inti,j;printf("pleaseenterthecharacters:");for(i=0;(str[i]=getchar())!='\n';i++);/*输入字符序列,当输入回车时结束*/

str[i]='\0';/*添加字符串结束标志*/

for(i=0;str[i]!='\0';i++)printf("%c",str[i]);/*输出字符序列*/}9.4字符数组字符串常量赋给字符数组若在定义字符数组的同时赋初值,则可将字符串常量赋给它。例如,charc[20]={"Thegreatwall"};习惯上可以省略花括号,上面定义可写为:charc[20]="Thegreatwall";若定义字符数组时完成赋初值,则可以在定义中省略数组的长度。系统会根据所赋字符串常量的实际长度来确定字符数组的长度。例如,上述定义也可写为:charc[]="Thegreatwall";字符串常量末尾处有系统自动加的结束标志‘\0’,所以要求数组长度比字符串长度至少大1。例如,charc[14]="Thegreatwall";数组c不能满足字符串长度。除了数组定义时可以将字符串直接付给字符数组外,其它时刻只能对元素进行赋值。9.4字符数组【例9.19】写出程序结果,并考虑原因。#include"stdio.h"main(){charstr1[]="Thisisastring";charstr2[]={'T','h','i','s','','i','s','','a','','s','t','r','i','n','g','\0'};

charstr3[]={'T','h','i','s','','i','s','','a','','s','t','r','i','n','g'};

inti;

for(i=0;str1[i]!='\0'&&i<20;i++)

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

printf("\nlength:%3d\n",i);for(i=0;str2[i]!='\0'&&i<20;i++)

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

printf("\nlength:%3d\n",i);

9.4字符数组for(i=0;str3[i]!='\0'&&i<20;i++)

printf("%c",str3[i]);printf("\nlength:%3d\n",i);}程序运行结果为:Thisisastringlength:16Thisisastringlength:16ThisisastringΦ↔☺length:209.4字符数组常用字符串处理函数字符串输入函数gets格式:gets(字符数组)功能:接收从键盘输入的一个字符串(可包含空格),存放在字符数组中。函数的返回值是字符数组的起始地址。字符串输出函数puts格式:puts(字符数组)功能:将存放在字符数组中的字符串输出到显示器上。该函数没有返回值。字符串比较函数strcmp格式:strcmp(字符串1,字符串2)功能:比较两个字符串的大小。字符串1、2可以是字符串常量或已赋值的字符数组。若字符串1大于字符串2,返回一个正整数;若字符串1等于字符串2,返回整数0;若字符串1小于字符串2,返回一个负整数。9.4字符数组字符串复制函数

strcpy格式:strcpy(字符数组1,字符串2)功能:将字符串2的内容原样复制到字符数组1。函数的返回值是字符数组1的起始地址。字符数组1是已定义的足够长的字符数组;字符串2可以是字符串常量或者已赋值的字符数组。字符串连接函数strcat格式:strcat(字符数组1,字符串2)功能:将字符串2连接到字符数组1中的字符串之后,并且将连接后的新串存放于字符数组1中。函数的返回值是字符数组1的起始地址。测试字符串长度函数strlen格式:strlen(字符串)功能:求字符串的长度,返回值是字符串长度。函数的参数可以是字符串常量或者是已赋值的字符数组。字符串的长度指的是字符串实际长度,而不包含'\0'在内。9.4字符数组注意:六个字符函数都要求字符数组中存放的字符串有结束标志'\0'。【例9.20】比较两个字符串的大小。#include"stdio.h"#include"string.h"main(){charstr1[20],str2[20],str[20];intflag;printf("\npleaseenterthefirststring:");gets(str1);/*输入字符串1*/

printf("pleaseenterthesecondstring:");gets(str2);

/*输入字符串2*/flag=strcmp(str1,str2);/*比较字符串的大小*/9.4字符数组if(flag<0)strcpy(str,str2);

/*复制字符串*/

elsestrcpy(str,str1);/*复制字符串*/printf("thestringis:");puts(str);

/*输出字符串*/}如果输入字符串"bcdefgj"和"abcdef",程序运行结果为:pleaseenterthefirststring:bcdefgj↙pleaseenterthesecondstring:abcdef↙thestringis:bcdefgj9.4字符数组字符数组和函数字符数组和其他数组一样可以作为函数的形式参数或实际参数。【例9.21】输入一个字符串,再分别以大写字母和小写字母形式输出该字符串。#include"stdio.h"#defineN80voidlowercase(charstr[])/*以大写形式输出字符串*/{intk;for(k=0;str[k]!='\0';k++)

if(str[k]>='a'&&str[k]<='z')putchar(str[k]-32);elseputchar(str[k]);printf("\n");}9.4字符数组voidcapital(charstr[])/*以小写形式输出字符串*/{intk;for(k=0;str[k]!='\0';k++)if(str[k]>='A'&&str[k]<='Z')putchar(str[k]+32);elseputchar(str[k]);

printf("\n");}main(){charc[N];intk;printf("pleaseenterthestring:");gets(c);/*输入字符串*/

lowercase(c);capital(c);}9.4字符数组输入“ds78TYTY(kdfdslQW8”时,程序运行结果为:pleaseenterthestring:ds78TYTY(kdfdslQW8↙DS78TYTY(KDFDSLQW8ds78tyty(kdfdslqw89.4字符数组字符指针指向字符数组的指针变量指向字符数组的指针变量也就是指向字符类型变量的指针。【例9.22】比较两个字符串大小(不使用库函数)。#include"stdio.h"intcompare(char*a,char*b)/*比较字符串a、b的大小,a比b大返回1,a等于b返回0,a小于b返回-1*/{for(;(*a==*b)&&(*a!='\0')&&(*b!='\0');a++,b++);if(*a>*b)return(1);elseif(*a==*b)return(0);elsereturn(-1);}9.4字符数组main(){chara[20],b[20];

intflag;printf("pleaseenterthefirststring:");gets(a);/*输入第一个字符串*/

printf("pleaseenterthesecondstring:");gets(b);/*输入第二个字符串*/

flag=compare(a,b);

printf("thefirststring");/*输出比较的结果*/if(flag==0)printf("=");elseif(flag<0)printf("<");elseprintf(">");

printf("thesecondstring\n");}9.4字符数组如果输入字符串"bc"和"afy57bcdef",程序运行结果为:pleaseenterthefirststring:bc↙pleaseenterthesecondstring:afy57bcdef↙thefirststring>thesecondstring9.4字符数组指向字符串常量的指针变量定义指针变量时直接赋值,格式为:存储类型char*指针变量=字符串常量;例如,语句“char*s1="thisisastring!";”定义指针变量之后再赋值,格式为:

指针变量=字符串常量;例如,在语句“char*s1;”之后,可用以下语句使s1指向字符串"thisisastring!":s1="thisisastring!";字符串常量存放在内存的某段连续存储单元中。这两种赋值都不是将字符串赋给指针变量,而只是将字符串常量在内存的首地址赋给字符指针变量。字符数组存放字符串的方式与字符串指针方式是不同的。字符型指针只是一个基类型为字符型的指针变量,用来指向一段无名的地址空间。字符数组占用固定的存储空间,每个元素有确定的地址,在这些空间内可以存放不超过数组长度的字符串。9.4字符数组【例9.23】将两个字符串连结成一个新的字符串。voidconnect(char*p,char*pa,char*pb)/*将字符串pa、pb连接成一个字符串p*/{for(;*pa!='\0';p++,pa++)*p=*pa;for(;*pb!='\0';p++,pb++)*p=*pb;*p='\0';}main(){char*pa="thefirststring“,*pb="thesecondstring";

charstr[80];connect(str,pa,pb);printf("thepurposestringis:%s",str);}程序的运行结果为:thepurposestringis:thefirststringthesecondstring9.5指针数组指针数组如果数组元素的类型是指针类型,则称该数组为指针数组。指针数组的定义形式为:类型名*数组名[数组长度];例如,语句“float*p[6];”定义了一个指针数组p,数组元素为基类型为实型的指针。指针数组一般都与其他数组或字符串相联系。指针数组的元素一般指向其他数组的数组元素、二维数组的行或字符串。【例9.24】按照数组元素的大小对数组元素地址进行排序(采用冒泡排序法)。若排序的结果要求是非递减的,则冒泡排序的思路是:对于n个元素,从前向后依次将相邻元素进行比较。若前面的元素大于后面的元素,则两个元素交换。这样通过n-1次比较,最大的元素移到了最后;然后,再对前n-1个元素做同样的操作,次大的元素移到了倒数第二个位置;……排序n-1趟,即得到一个有序的序列。9.5指针数组例如,数组a有67、4、87、32、45、1、2、7、17、20十个数,则排序过程为:第一趟冒泡排序对10个数进行操作:6748732451271720a[0]和a[1]比较,a[0]大于a[1],a[0]和a[1]互换:4678732451271720

a[1]和a[2]比较,a[1]小于a[2],不进行互换操作:4678732451271720a[2]和a[3]比较,a[2]大于a[3],a[2]和a[3]互换:4673287451271720

a[3]和a[4]比较,a[3]大于a[4],a[3]和a[4]互换:4673245871271720

a[4]和a[5]比较,a[4]大于a[5],a[4]和a[5]互换:4673245187271720a[5]和a[6]比较,a[5]大于a[6],a[5]和a[6]互换:9.5指针数组4673245128771720a[6]和a[7]比较,a[6]大于a[7],a[6]和a[7]互换:4673245127871720a[7]和a[8]比较,a[7]大于a[8],a[7]和a[8]互换:4673245127178720a[8]和a[9]比较,a[8]大于a[9],a[8]和a[9],最后:673245127172087第二趟冒泡排序对前9个数进行操作,方法和第一趟排序相同,结果为:43245127172067第三趟冒泡排序对前8个数处理的结果为:432127172045依次类推,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论