数组及其应用
什么是数组?程序中为何要使用数组?在学习数组之前,先看一个简单的例子:
输入一个学生5门课的成绩,要求按与输入次序相反的顺序输出。
【编程思路】
(1)5个成绩需要存储在5个变量中,先定义接收成绩的5个变量。
(2)输入5个成绩,依次将其赋给5个变量。
(3)从最后一个变量开始依次往前输出每个变量的值。
【程序代码】
#include<stdio.h>
int main()
{
float s1,s2,s3,s4,s5;
printf("请输入5个成绩:\n");
scanf("%f%f%f%f%f",&s1,&s2,&s3,&s4,&s5);
printf("成绩逆序输出:\n");
printf("%7.2f",s5);
printf("%7.2f",s4);
printf("%7.2f",s3);
printf("%7.2f",s2);
printf("%7.2f",s1);
return 0;
}
【运行结果】
【程序分析】
由于一个float类型的变量中只能存放一个成绩,所以程序中定义了5个变量来存放5个成绩。然而5门课的成绩同属于一个同学,它们是一组相关数据,而在该程序中由于这5个变量是各自独立的,并没有反映出这些成绩的整体关系。另外,该程序实现的是5个成绩的逆序输出,假如有10个成绩、20个成绩,那么程序中就需要10个、20个变量,显然这是不现实的,程序也无法做到。这样就出现下面的问题:
一个人的N门成绩怎样存储和处理?
一个班的N门成绩怎样存储和处理?
分析这些数据,不难发现它们有一个共同的特点,就是数量大而且数据类型相同。为了能方便处理这种类型数据,C语言提供了一种构造数据类型,即数组。
数组是一组相同类型的变量的集合,用一个数组名标识,其中每个变量(称为数组元素)通过它在数组中的相对位置(称为下标)来引用。
1)数组中存放的是1个或者多个数据,但是数组元素个数不能为0;
2)数组中存放多个数据,数据类型是相同的。
数组有一维数组和多维数组,常用的是一维数组和二维数组。
例如,存储一个学生的5门课成绩,可以使用一维数组。语句“ float score[5];”定义了一个数组,其中 score 是数组名,该数组有5个元素,分别表示为 score[0]、score[1]、score[2]、score[3]、score[4],可以存放一个学生的5门课的成绩。一个班的N门课的成绩的存储和处理可以使用二维数组完成。
利用一维数组处理以上的例子:
【程序代码】
#include<stdio.h>
int main()
{
int i;
float score[5]; //定义数组
printf("请输入5个成绩:");
for(i=0,i<5,i++) //输入成绩,依次存入5个数据元素中
scanf("%f",&score[i]);
printf("成绩按逆序输出:");
for(i=4;i>=0;i--) //逆序输出每个数组元素
printf("%7.2f",score[i]);
return 0;
}
【运行结果】
注意:在程序中,将数组和循环结构结合起来,利用循环对数组的元素进行操作,可使算法大大简化,程序更容易实现。
1、一维数组
一维数组是最简单的数组,是指只有一个下表的数组,通常用于存放一组数据类型相同的多个数据,因此需要占据一定大小的存储空间。在C语言中,所有数组在使用之前必须先定义,即指定数组的名字、大小和类型。一旦定义了数组,系统就为数组在内存中按需要分配一段一段大小固定且连续的存储空间。因此,一维数组的名称、大小和数据类型,要通过数组定义来确定。
1.1一维数组的定义
一维数组的定义格式:
数据类型 数组名[常量表达式]; 注意:常量表达式可以包含常量和符号常量,不能包含变量。
其中,数据类型是各数组元素的数据类型,数组名遵循C语言标识符规则。常量表达式表示数组中有多少个元素,即数组的长度。例如:int x[10];
通过上面的数组定义语句,可以了解到有关该数组的以下信息:
(1)数组名:数组名为 x 。在C语言中,数组名表示该数组的首地址,即第一个元素的地址(&x[0])。
(2)数组维数:一维。
(3)数组元素的个数(即数组长度):10个。C语言规定第一个元素的下标为0,第二个元素的下标为1,依次往后,那么数组x的最后一个元素的下标为9,这样数组的各个元素依次表示为:x[0]、x[1]、x[2]、···、x[9]。
(4)数组元素的类型:类型名 int 规定了数组 x 的类型,即数组中的所有元素均为整型,那么这样的一个元素可以存放一个整数。
(5)数组元素在数组集合中的位置:编译时,会为数组 x 分配10个连续的存储单元,如下图所示,其中每个数组元素依据下标依次连续存放。
(6)允许一个类型同时定义多个该类型的数组和变量,例如:
float b[8],c[14],x,y;
定义名为b的一维实型数组有8个元素,名为c的一维实型数组有14个元素,名为x和y的两个实型变量 。
(7)对定义的数组(含一维数组、二维数组及字符数组等),要给其赋初值。如果不给数组赋初值,系统默认数组各个元素的初始值是毫无意义的随机值。
以下数组的定义也是正确的:
#define N10
float score1[N];
int num[10+N];
定义一维数组时,需要注意的是:
(1)表示数组长度的常量表达式,必须是正的整型常量表达式。
(2)相同类型的数组、变量可以在一个类型说明符下一起说明,互相之间用逗号隔开,例如: int a[5],b[10],i。
(3)C语言不允许定义动态数组,即数组的长度不能是变量或变量表达式,下面这种数组定义方式是不允许的:
int i;
scanf("%d",&i);
int a[i];
1.2 一维数组元素的引用
一维数组的数组元素由数组名和下标来确定,引用形式如下:
数组名[下标表达式]
例如,有定义“float a[8],x=3,y=1;”,那么,a[0]、a[x]、a[x+y]都是数组a中元素的合法引用形式,0、x、x+y是下标表达式,由于定义数组a大小为8,所以下标表达式的值必须大于或等于0,并且小于8。
引用数组元素时需要注意:
(1)数组元素实际上就是变量,因此它的使用规则与同类型的普通变量是相同的。
(2)数组不能整体引用。例如,对上面定义的数组a,不能用数组名a代表a[0]到a[7]这8个元素,即用以下语句整体输出a数组是不正确的:
printf("%d",a); //错误用法
(3)要输出数组a的值,必须输出每个元素的值,比如:
for(j=0;j<8;j++)
printf("%d\t",a[j]);
注意:
(1)一维数组中数组元素的位置由其下标决定。
(2)程序中常用循环语句控制下标变化的方式来访问数组元素。
(4)在c语言程序中,所有数组元素的下标都是从0开始的,在引用数组元素时,引用的下标要在数组定义的范围之内,不要越界。比如,有数组定义:
float a[8];
数组a元素的正确引用范围为a[0]~a[7],如果在程序中出现a[8]或者a[9]之类的引用即越界。需要注意的是,C语言程序编译时不进行越界检测,倘若数组引用越界,编译系统不会给出错误提示,那么程序在运行时,很有可能破坏其他数据或使用错误数据,导致程序的运行结果出错甚至破坏系统。
(5)在C语言中数组的访问提供了一个操作符“ [ ] ”,这个操作符叫:下标引用操作符。
有了下标引用操作符我们就可以轻松的访问到数组的元素了,比如我们访问下标为7的元素,我们就使用“ a[7]”,想要访问下标为3的元素,就可以使用“ a[3]”。
举一个简答的例子理解一下吧:
【程序代码】
#include<stdio.h>
int main()
{
int a[10],i;
for(i=0;i<10;i++)
a[i]=i;
for(i=9;i>=0;i--)
printf("%d",a[i]);
printf("\n下标为7的元素是:%d\n",a[7]);
return 0;
}
【输出结果】
1.3一维数组的初始化
程序在编译时,仅仅为数组在内存中分配了一串连续的存储单元,这些存储单元中并没有确定的值,可以用以下形式,在定义时为数组赋初值:
(1)定义时,为每个元素都指定值。
int x[5]={78,87,77,91,60};
所赋初值放入大括号中,用逗号隔开,数组类型必须与说明的数组类型一致,系统会按这些值的排列顺序,从第一个元素开始依次给数组x中的每个元素赋初值。
初始化后,数组x的存储情况为:
在初值的个数与数组大小一致时,可以省略数组的大小,例如:
int x()={ 78,87,77,91,60};
此时,系统会根据提供的数据个数确定数组的大小。
(2)指定部分元素的值。
int x[5]={ 78,87,77};
初始化后,数组x的存储情况为:
定义数组x有5个元素,后面只提供了3个初值,那么没有取到值的2个元素,系统会自动赋初值为0。利用这种方式可以很方便地给数组中的所有元素清0,例如:
int x[5]={0};
1.4 一维数组应用举例
例1:输入10名学生的成绩,找出最高分和最低分。
【编程思路】
(1)本题实际上是最大数与最小数的问题。
(2)定义一个大小为10的数组来存储这10个成绩,定义两个变量max、min,分别用来存放最高分和最低分。
(3)最高分与最低分的确定需要比较才能得出。先将第一个成绩存入max和min中,然后用max与min依次与其他成绩进行比较,在比较过程中把最高的成绩放入max,把较低的成绩放入min中,最后输出max和min即可。
【程序代码】
#include<stdio.h>
int main()
{
float score[10],max,min;
int i;
printf("请输入10个成绩:\n");
for(i=0;i<10;i++)
scanf("%f",&score[i]);
max=min=score[0]; //将第一个成绩存入max、min中
for(i=1;i<10;i++) //从第二个成绩开始查找最高分和最低分
{
if(max<score[i])
max=score[i];
if(min>score[i])
min=score[i];
}
printf("最高分:%.2f,最低分:%.2f",max,min);
return 0;
}
【输出结果】
例2:程序的功能是随机产生10个50以内的整数放入数组中,求产生的10个数中偶数的个数及平均值。
【编程思路】
(1)产生0和50之间的随机整数用库函数 rand()%50,该函数使用时需要包含头文件“#include<stdlib.h>”。
(2)取出每个数进行判断,如果是偶数则计算累加和,同时统计偶数的个数。
【程序代码】
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a[10]; //定义数组
int k,j;
float aver,s;
k=0;s=0.0;
for(j=0;j<10;j++) //用数组存放10个随机整数
a[j]=rand()%50;
printf("数组中的值:");
for(j=0;j<10;j++)
printf("%6d",a[j]); //输出10个随机整数
printf("\n");
for(j=0;j<10;j++)
{
if(a[j]%2==0) //如果数组元素的值为偶数
{s+=a[j];k++;}
}
if(k!=0)
{
aver=s/k;
printf("偶数的个数:%d\n偶数的平均值:%f\n",k,aver);
}
return 0;
}
【输出结果】
例3:利用一维数组输出斐波那契数列的前20项,要求每行输出5个数。
【编程思路】
(1)定义一个大小为20的int型数组存放数列的前20项,为前两个元素均赋值1,从第3个元素开始,其值为前两个元素之和,即a[i]=a[i-2]+a[i-1]。
(3)因为数组元素下标从0开始,下标值总比元素的顺序小1,如a[4]为数组中第5个元素,所以当输出a[4]、a[9]、a[14]······时应该换行,而4、9、14······这些值加1即5的倍数。
【程序代码】
#include<stdio.h>
#define N 20
int main()
{
int a[N],i;
a[0]=a[1]=1;
for(i=2;i<N;i++)
a[i]=a[i-2]+a[i-1];
for(i=0;i<N;i++)
{
printf("%d\t",a[i]);
if((i+1)%5==0)
printf("\n");
}
return 0;
}
【运行结果】
注意:
“ \t ”是制表符,作用是,输出时,在输出位置之间插入一定量的空格,使输出数据更加美观。
2、二维数组
2.1二维数组的定义
从逻辑上可以把二维数组看成具有若干行和若干列的表格或矩阵,因此,在程序中用二维数组存放排列成行列结构的表格数据。
定义二维数组时,除了给出数组名、数组元素的类型外,同时应给出二维数组的行数和列数。二维数组的定义格式为:
数据类型 数组名[常量表达式1] [常量表达式2];
其中,常量表达式1指定数组中所包含的行数,常量表达式2指定每行所包含的列数。
例如:int a[3][4];
通过上面的数组定义语句,可以了解到有关该数组的以下信息:
(1)定义了一个名为a的二维数组,数组中每个元素的类型均为整型。
(2)数组a中包含了3*4=12个数组元素,其行列下标都从0开始,依次加1,各数组元素分别为:
二维数组a的逻辑结构恰似一个3行四列的表格,在程序中可用来存放有3行4列位置要求的表格数据。
(3)二维数组在内存中也是占据一片连续的存储单元,其物理结构与一维数组一样,各数组元素是按行存放的,即内存中先顺序存放第一行元素,再接着存放第二行元素。二维数组在内存中的存储结构如图:
在定义二维数组时需要注意,两个常量表达式的值只能是正整数,分别表示行数和列数,书写时要分别括起来。例如,以下定义是不正确的:
int a[3,4]; //错误定义
2.2二维数组元素的引用
二维数组中的每个元素需要由数组名和两个下标来确定,引用形式如下:
数组名[下标表达式 1][下标表达式 2]
例如,有以下定义:
float b[4][5];
int x=3,y=1;
下面是对该数组元素的引用:
b[0][3]、b[x][y]、b[x-2][y+1] //正确引用
b[0,3]、b[x,y]、b[x-2,y+1] //不正确的引用,格式错误
b[4][5] //不正确的引用,行、列下标都超出了引用范围
二维数组也不能整体引用,必须引用到数组中的元素,比如:
for(i=0;i<4;i++)
for(j=0;j<5;j++)
printf("%f",b[i]b[j]);
以上语句的执行结果是数组b中所有元素都在一行输出。如果要按行、列的形式输出,则需要在每行元素输出完后输出一个回车换行符,上面的语句可以改写为:
for(i=0;i<4;i++)
{
for(j=0;j<5;j++)
printf("%f",b[i][j]);
printf("\n");
}
注意:二维数组中每个元素都由两个下标确定,通常引用二维数组需要用到两层循环嵌套,外层循环控制行号,内层循环控制列号。
二维数组的输入和输出:
【程序代码】
#include<stdio.h>
int main()
{
int x[3][4],i,j;
printf("请输入数组的值:\n");
for(i=0;i<3;i++)
for(j=0;j<4;j++)
scanf("%d",&x[i][j]);
printf("输出数组的值:\n");
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
printf("%6d",x[i][j]); //输出数组元素的值
printf("\n");
}
}
【运行结果】
2.3二维数组的初始化
二维数组的初始化方式有多种,其中常用以下几种形式:
(1)所赋初值个数与数组元素的个数相同。每行的初值放在一个大括号中,所有行的初值再放在一个大括号中。
例如:int a[3][2]={ {1,2},{3,4},{5,6} };
初始化后,每个数组元素均被赋值,其中a[0][0]=1,a[0][1]=2,a[1][0]=3,a[1][1]=4,a[2][0]=5,a[2][1]=6,用行列的形式表示为:
初始化时,第1维的大小可以省略不写。比如上面的语句也可以写成:
int a[ ][2]={ {1,2},{3,4},{5,6} };
(2)只为数组的部分元素赋值,剩余的元素被自动赋0值,例如:
int a[3][2]={ {1},{2,3},{4} };
第0行只提供了一个初值,该值被赋给第0行的第一个元素,即a[0][0],a[0][1]会被系统自动赋0值。每个数组的元素分别用行和列的形式表示为:
例4:利用初始化的方法给二维数组赋值并输出。
【程序代码】
#include <stdio.h>
int main()
{
int x[3][4]={{1,2},{3,4,5},{6,7,8,9}},i,j;
printf("输出数组的值:\n");
for(i=0;i<3;i++) //产生行号,不是数组表示的值
{
for(j=0;j<4;j++) //产生列号
printf("%6d",x[i][j]);
printf("\n");
}
}
2.4 二维数组的应用举例
例5:假设某班有N名学生,期末考4门课程。编制程序,要求输入每位学生的各门单科成绩,然后计算出每人的总分。
【编程思路】
(1)全班N名学生的单科成绩和总成绩按以下形式存储:
(2)定义一个二维数组a{N][5],数组每行存放一名学生的数据,每行前4列存放学生的4门单科成绩,第5列存放学生的总分。
(3)输入N个学生的单科成绩,存入二维数组a中。
(4)通过变量sun累加计算每位学生的总分,然后赋值给每行的最后一个元素。
(5)输出数组第5列上的值,即每个学生的总分。
#include<stdio.h>
#define N 6 //以6个学生为例
int main()
{
int a[N][5],i,j,sum;
for(i=0;i<N;i++) //产生行号
{
printf("请输入第%d个学生的4门成绩:",i+1);
for(j=0;j<4;j++) //产生列号
scanf("%d",&a[i][j]); //输入数据
}
for(i=0;i<N;i++)
{
sum=0;
for(j=0;j<4;j++)
sum+=a[i][j];
a[i][4]=sum;
}
for(i=0;i<N;i++)
printf("第%d个学生的成绩总分是:%d\n",i+1,a[i][4]);
return 0;
}
【输出结果】
程序说明:
程序中可以不使用变量sum,做法是先将最后一列元素全部清0,然后将每位学生的成绩直接累加到a[i][4]上,比如:
for(i=1;i<6;i++)
a[i][4]=0;
for(i=0;i<6;i++)
for(j=0;j<4;j++)
a[i][4]+=a[i][j];
例6:利用二维数组输出杨辉三角形,如下图所示。
【编程思路】
先将杨辉三角形的值存放在一个二维数组的下三角元素中,然后输出这些值即可。
杨辉三角具有以下特点:
(1)第0列和对角线上的元素均为1.
(2)其他元素的值为上一行上的同列和上一行前一列的元素之和。
【程序代码】
#include<stdio.h>
#define N 10
int main()
{
int a[N][N],i,j;
for(i=0;i<N;i++)
{
a[i][0]=1;
a[i][i]=1;
}
for(i=2;i<N;i++)
for(j=1;j<i;j++)
a[i][j]=a[i-1][j-1]+a[i-1][j];
for(i=0;i<N;i++)
{
for(j=0;j<=i;j++)
printf("%8d",a[i][j]);
printf("\n");
}
return 0;
}
3、字符串及其处理
字符串及其字符数组
字符串是指用双引号括起来的一串字符,例如“Good”。字符串在内存中用字符数组来存放。字符数组实际上是数组元素为char类型的一维数组,其用法与普通数组基本相同。
3.1字符数组的定义及初始化
1)字符数组的定义
例如:char str[10];
数组str为字符数组,包含10个数组元素,即str[0]、str[1]、····、str[9],其中的每个元素只能存放一个字符。
2)字符数组的初始化
(1)举例1:逐个字符赋值,比如:
char str[5]={'H','E','L','L','O'}; //每个数组元素各存放一个字符
初始化后,数组str的存储情况为:
(2)举例2:逐个字符赋值:
char ch[5]={'c','a','t'}; //数据不够时,其余元素取空字符'\0'
初始化后,数组ch的存储情况为:
字符串由若干字符组成,其末尾必须有字符串结束标记'\0',所以上面的字符数组str中存放的是一组字符,不是字符串,而字符数组ch存放的是一个字符串。
注意:字符数组可以存放一组字符数据,也可以存放一个字符串。
(3)举例3:字符串赋值,用字符串初始化字符数组,比如:
char str[6]={"HELLO"};
char str[6]="HELLO";
char str[ ]="HELLO";
以上三种形式的初始化定义结果都一样,其中第3种书写形式经常被使用。初始化后,字符数组str的存储情况为:
注意:以下操作是错误的,错误原因是数组名str是地址常量,不能用于赋值语句。
char str[10];
str="student"; //错误
3.2字符串的输入、输出
C语言提供了格式说明符%s,利用它可以进行整串的输入、输出操作。
(1)scanf()函数中使用格式说明符%s实现字符串的整串输入,例如:
char str[10];
scanf("%s",str);
输入的字符串被存放到数组str中,并且会自动在尾部加上结束标记 '\0'。
使用格式符%s输入字符串时,空格和回车符都作为输入数据的分隔符而不能被读入。
上例中如果从键盘输入“a student <回车> ”,则在数组str中存的是字符串“a”,而不是字符串“a student”。
注意:数组名str是数组的首地址,因此scanf()函数的输入项是str,而不是 &str 。
(2)printf()函数中使用格式说明符%s实现字符串的整串输出,例如:
char str[10]="China";
printf("%s"'str);
输出结果为:China 。
用printf()输出时,输出项是待输出字符的位置。本例将从字符串的首字符开始,依次输出每个字符,直到遇见字符串结束标记‘\0’为止。
例7:输入一个由字母组成的字符串,统计串种大写字母的个数。
【编程思路】
(1)从字符串中依次取出各个字符进行判断,直到遇到'\0'为止。
(2)用变量n统计大写字母的个数。
【程序代码】
#include<stdio.h>
#includde<string.h>
int main()
{
char str[30];
int i,n;
n=0;
printf("请输入字符串:\n");
scanf("%s",str);
i=0;
while(str[i]!='\0')
{
if(str[i]>='A'&&str[i]<='Z')
n++;
i++; //指示下一个字符
}
printf("字符串中的大写字母个数为:%d",n);
}
【运行结果】
程序说明:
程序中变量i用来作数组元素下标,每次增1实现顺序取出字符串中的字符,变量n统计大写字母的个数,只有在当前字符为大写字母时其值才增1。
3.3常用字符串处理函数
在C语言程序中,很多字符串的处理都要借助字符串函数完成。C语言提供了大量的字符串处理库函数,使用这些函数时,必须包含头文件" string.h"。下面介绍几种常用的字符串处理函数。
1)字符串输入函数gets()
例如:
char str[50];
gets(str);
str为字符数组名,函数gets()用来接收从键盘输入的字符串(可以包含空格符),直到遇到换行符为止,系统自动将换行符用'\0'代替。
提示:注意函数gets(str)与scanf("%s",str)的区别。
2)字符串输出函数puts()
例如:
char str[ ]="Hello Word!";
puts(str);
str为待输出字符串的起始地址,puts()函数将从指定位置开始输出字符串,遇 '\0' 结束输出。
3)字符串长度函数strlen()
例如:
char str[ ]="Hello Word !";
printf("%d",strlen(str));
函数strlen()能测试字符串的长度,函数的返回值为字符串的实际长度(不包括'\0'),上面语句输出结果是12。
4)字符串复制函数strcpy()
例如:
char str1[20],str2[ ]="Hello";
strcpy(str1,str2);
函数strcpy()将字符串2原样复制到字符数组1中去。使用该函数时,字符数组1必须定义得足够大,以便容纳被拷贝的字符串。
注意:对于字符串复制操作,语句"str1=str2";是错误的写法。
5)字符串连接函数strcat()
例如:
char str1[20]="abcde",str2[ ]="xyz";
strcat(str1,str2);
puts(str1);
运行结果为:abcdexyz
函数strcat()将两个字符串连接成1个长的字符串。连接后的字符串放在字符数组1中,因此字符数组1必须足够大,以便容纳连接后的新字符串。
6)字符串比较函数strcmp()
例如:
strcmp("ask","active")
该函数将两个字符串从左至右逐个字符进行比较(比较ASCII码值),直到出现不同的字符或遇到'\0'为止(前面有大的或者小的就不用比较后面的了),比较的结果由函数值返回。函数返回值有以下几种情形:
(1)字符串1=字符串2,函数值为0;
(2)字符串1>字符串2,函数值为正数;
(3)字符串1<字符串2,函数值为负数。
举例:
if(strcmp("ask","active")>0)
puts("ask");
else
puts("active");
其运行结果为: ask
例8:连接两个字符串后计算所得到的字符串的长度。
【程序代码】
#include<stdio.h>
#include<string.h>
int main()
{
char str1[30],str2[10];
printf("请输入第一个字符串:");
gets(str1);
printf("请输入第二个字符串:");
gets(str2);
strcat(str1,str2);
printf("连接后的新字符串为:");
puts(str1);
printf("新串长度为:%d",strlen(str1));
}
【运行结果】
3.4多个字符串的存储与处理
一维数组可以存放和处理一个字符串,而多个字符串的存储和处理可以借助二维字符数组完成。
在C语言中,二维数组可以看成一种特殊的一维数组。例如,有以下数组定义:
char x[3][7];
可以把数组x看作一个包含3个元素x[0]、x[1]、x[2]的一维数组,而x[0]、x[1]、x[2]又分别包含了各自的7个元素,即可将x[0]、x[1]、x[2]都是数组名,数组名也是数组的首地址,因此x[0]是第0行的首地址,x[1]是第1行的首地址,x[2]是第2行的首地址。其关系如下图所示:
这样,数组中的每行可以存放一个字符串,那么多行就可以存放多个字符串。例如有以下初始化定义:
char fruit[ ][7]={"Apple","Orange","Grape","Pear","Peach"};
数组fruit 共有5个元素fruit[0]、fruit[1]、fruit[2]、fruit[3]、fruit[4],每个元素又是一个有7个元素的一维字符数组,其中可以存放长度小于7的字符串。
初始化后,数组fruit的存储结构如图:
例7:有5种水果,要求输出第2种和第5种水果的名称。
【程序代码】
#include<stdio.h>
int main()
{
char fruit[ ][7]={"Apple","Orange","Grape","Pear","Peach"};
printf("第二种水果是:");
printf("%s\n",fruit[1]);
printf("第五种水果是:");
puts(fruit[4]);
}
注意:二维字符数组也称为字符串数组。比如有定义“char a[5][20];”那么数组a是一个字符串数组,最多可以存放5个长度小于20的字符串。
3.4字符串的应用实例
例8:删除字符串s中所有的‘*’,剩下的字符组成一个新的字符串存入数组 t 中。
【编程思路】
(1)依次取出s中的每个字符进行判断,将不是‘ \0’且不是‘*’的字符依次存入数组t中,最后t末尾加结束标志。
(2)定义变量i和j,分别用作数组s、t的元素下标,以顺序访问每个元素。
【程序代码】
#include<stdio.h>
int main()
{
char s[20],t[20];
int i,j;
printf("输入字符串:");
gets(s); //输入原始字符串
i=0,j=0;
while(s[i]!='\0') //当字符串没有结束时,继续执行
{
if(s[i]!='*')
{
t[j]=s[i]; //如果当前字符不是‘*’,则存入数组t中
j++;
}
i++;
}
t[j]='\0'; //加字符串结束标记
puts(t); //输出新串
}
【编译结果】
例9:输入5个国家的名称,要求按字母顺序找出排在最后的国家名称。
【编程思路】
(1)在5个串中找到最大的字符串,其解决思路与在5个数中找最大数一样。
(2)定义一个字符串数组str存放5个国家的名称,定义一个字符数组maxstr存放最大的串。
(3)将第一个字符串存入数组maxstr中,然后将数组maxstr和剩余字符串依次进行比较,最终找出最大的串。
【程序代码】
#include<stdio.h>
#include<string.h>
int main()
{
char maxstr[20];
char str[5][20];
int i;
printf("请输入5个国家的名称:\n");
for(i=0;i<5;i++)
gets(str[i]);
strcpy(maxstr,str[0]); //将第一个字符串放入maxstr中
for(i=1;i<5;i++)
if(strcmp(str[i],maxstr)>0) //将剩余的字符串依次进行比较
strcpy(maxstr,str[i]); //将较大的串放入数组maxstr中
printf("排在最后的国家名称是:%s\n",maxstr);
}
【运行结果】
4.总结:
(1)数组的概念:数组是一组相同类型的变量构成的集合。数组中的变量称为数组元素。
(2)数组的地址:数组占据连续的一段存储空间,数组名是其首地址。
(3)数组元素的引用:
1)一维数组元素的引用形式:数组名[下标]
2)二维数组元素的引用形式:数组名[行下标][列下标]
引用一维数组元素时,用单循环实现,循环变量作为元素的下标,顺序引用每个元素
二维数组借助二层循环,通常外层循环控制行下标,内层循环控制列下标
(引用元素时注意不能超过引用范围;注意与字符数组的引用区别)
(4)一维数组的应用:
一维数组可以存放一批类型相同的数据,并且利用一维数组可以对这批数据进行处理,如查找数据、插入数据、删除数据、对数据进行排序等操作。
(5)二维数组的应用:
二维数组用来存放类型相同的多行多列形式的数据,如表格或矩阵数据,利用二维数组的逻辑结构可以直观地反映出数组的行列位置。
(7)字符数组:
字符数组就是数组元素为char类型的数组,其用法与数值型数组基本相同。
(字符串的存储:字符串在内存中都用字符数组来存放,程序中常用字符串的结束符'\0'来判断字符串是否结束)
(8)字符串处理函数。C语言提供1了很多字符串处理函数,比如字符串的输入或输出、复制、连接、比较等,调用它们可以方便地处理字符串。注意:使用字符串处理函数时,程序前要加上头文件(命令行)"#include<string.h>" 。