第六章 数组
6.1 一维数组
6.1.1 一维数组的定义与引用
1.一维数组是用于存储一维数列中数据的集合。定义方式如下:
类型说明符 数组名[常量表达式];
- “数组名”就是这个数组型变量的名称,命名规则和变量名一致。
- 数组中存储元素的类型由“类型说明符”给出,可以是任意的数据类型(整型、实型、字符型等)。
- “常量表达式”定义了数组中存放的数据元素的个数,即数组长度。
注:数组a[5]中只能使用a[0]、a[1]、a[2]、a[3]、a[4]而不能使用a[5],若使用a[5]会出现下标越界的错误。
2.一维数组的引用:数组必须先定义再使用。数组元素的表示形式如下:
数组名[下标]
下标可以是整型常量或整形表达式。
例6.1 任意输入5个数据,编程实现将这5个数据逆序存放
#include<stdio.h>
main()
{
int i,a[5],b;
printf("input a array:");
for(i=0;i<5;i++)
{
scanf("%d",&a[i]);
}
for(i=4;i>=2;i--)
{
b=a[i];
a[i]=a[4-i];
a[4-i]=b;
}
printf("output:");
for(i=0;i<5;i++)
{
printf("%d ",a[i]);
}
}
6.1.2 一维数组的初始化
(1)在定义数组时直接对数组元素赋初值。
int a[8]={0,1,2,3,4,5,6,7};
(2)只给一部分元素赋值,为负值的部分元素值为0。
int a[8]={0,1,2,3};
(3)在对全部数组元素赋初值时,可以不指定数组长度。
int a[ ]={0,1,2,3,4,5,6,7};
6.2 二维数组
6.2.1 二维数组的定义和引用
1.二维数组的定义
定义方式如下:
类型说明符 数组名[常量表达式1][常量表达式2];
“常量表达式1”表示第1维下标的长度,“常量表达式2”表示第2维下标的长度。如:a[2][4];
声明了一个2行4列的数组,数组名为a,其下标变量的类型为整型,共有2×4个。在C语言中,二维数组是按行排列的,即先存放a[0]行,再存放a[1]行。每行4个元素也是一次存放。
2.二维数组的引用
表示形式:
数组[下标][下标]
下标可以是整型常量或整形表达式。与一维数组一样,要注意下标越界问题。
6.2.2 二维数组的初始化
1.分行给二维数组赋初值:
int a[2][3]={{1.2,3},{4,5,6}};
第一个大括号内的元素赋给第1行的元素,第2个打括号内的元素赋给第2行。
2.可以按数组排列顺序在一个大括号内对各个元素赋初值:
int a[2][3]={5,4,3,2,1,0};
3.可以对部分元素赋初值(1、2均使用),未赋初值的元素其值自动为0:
int a[2][3]={5,4,3,2};
4.如果对全部元素都赋初值,则定义数组时对1维的长度可以不指定,但第2维的长度不能省略:
int a[][3]={5,4,3,2,1,0};
6.3 字符数组
6.3.1 字符数组的定义和引用
标准形式如下:
char 数组名[常量表达式]
6.3.2 字符数组的初始化
(1)逐个字符赋给数组中各元素
char a[5]={'*','*','*','*','*'};
当提供的初值个数大于数组长度,则按语法错误处理。如果初值个数小于数组长度,则只将这些字符赋给数组中前面的元素,其余元素自动定为空字符,即’\0’。
(2)如果初值个数与预定的数组长度相同,在定义时可以省略数组长度,系统会自动根据初值个数确定数组长度。如:
char a[]={'*','*','*','*','*'};
(3)利用字符串给字符数组赋初值。通常用一个字符数组来存放一个字符串,字符串总是以’\0’作为结束符,因此当把一个字符串存入一个数组时,也把结束符’\0’存入数组,并以此作为该字符串结束的标志。有了’\0’标志后,字符数组的长度就不再重要了,但定义字符数组时还是要估计实际字符串长度, 保证数组长度始终大于字符串实际长度。如果在一个字符数组中先后存放多个不同长度的字符串,则应使数组长度大于最长的字符串的长度。
char c[]={"hello world"};
或写成:
char c[]="hello world";
用字符串方式赋值比用字符逐个赋值多占一个字节,多占的这个字节用于存放字符串结束标志’\0’。’\0’是由C编译系统自动加上的。
6.3.3 字符数组的输入/输出
(1)格式字符%c,实现字符数组中字符的逐个输入与输出。
例6.11 字符逐个输入到字符数组中后逐个输出
#include<stdio.h>
main()
{
int i;
char array[12];
printf("please input string:\n");
for(i=0;i<12;i++)
{
scanf("%c",&array[i]);
}
printf("the string is:\n");
for(i=0;i<12;i++)
{
printf("%c",array[i]);
}
}
(2)格式字符%s,将整个字符串依次输入或输出。
例6.12 字符串输入输出
#include<stdio.h>
main()
{
int i;
char array[22];
printf("please input string:\n");
scanf("%s",array);
printf("the string is:\n");
printf("%s",array);
}
其中scanf("%s",array);
其中array是字符数组名,前面没有“&”,C语言中规定数组名代表该数组的起始地址。printf输出项也是字符数组名,而不是数组元素名。
如果一个字符数组中包含多个空格’\0’,则在遇到第一个时便结束输出。若想将输入的字符串全部输出,则程序代码应改为:
#include<stdio.h>
main()
{
int i;
char array1[10],array2[10],array3[10],array4[10];
printf("please input string:\n");
scanf("%s%s%s%s",array1,array2,array3,array4);
printf("the string is:\n");
printf("%s %s %s %s",array1,array2,array3,array4);
}
6.3.4 字符串处理函数
1.puts函数
字符串输出函数puts格式如下:
puts(字符数组名)
功能:把字符数组中的字符串输出到终端。
puts(c);
功能等价于printf("%s",c);
2.gets函数
字符串输入函数gets格式如下:
gets(字符数组名)
功能:从终端输入一个字符串。本函数得到一个函数值,即为该字符数组的首地址。
例6.15 gets函数应用
#include<stdio.h>
#include<string.h>
main()
{
char a[20];
printf("input string:\n");
gets(a);
puts(a);
}
与scanf不同,gets函数不以空格’\0’为结束标志,只以回车作为输入结束。
3.strcat函数
字符串连接函数strcat的格式如下:
strcat(字符数组名1,字符数组名2)
功能:把字符数组2的字符串连接到字符数组1中字符串的后面,并删去字符串1后的串结束标志’\0’。本函数返回值是字符数组1的地址。其中字符数组1的长度要足够大,否则不能装下链接后的字符串。
例6.16 将已按升序排好的字符串a和b按升序归并到字符串c中并输出
#include<stdio.h>
#include<string.h>
main()
{
char a[100], b[100], c[200], *p;
int i = 0, j = 0, k = 0;
printf("please input string a:\n");
scanf("%s", a); /*输入字符串1放入a数组中*/
printf("please input string b:\n");
scanf("%s", b); /*输入字符串2放入b数组中*/
while (a[i] != '\0' && b[j] != '\0')
{
if (a[i] < b[j]) /*判断a中字符是否小于b中字符*/
{
c[k] = a[i]; /*如果小于,将a中字符放到数组c中*/
i++; /*i自加*/
}
else
{
c[k] = b[j]; /*如不小于,将b中字符放到c中*/
j++; /*j自加*/
}
k++; /*k自加*/
}
c[k] = '\0'; /*将两个字符串合并到c中后加结束符*/
if (a[i] == '\0') /*判断a中字符是否全都复制到c中*/
p = b + j; /*p指向数组b中未复制到c的位置*/
else
p = a + i; /*p指向数组a中未复制到c的位置*/
strcat(c, p); /*将p指向位置开始的字符串连接到c中*/
puts(c); /*将c输出*/
}
4.strcpy函数
字符串复制函数strcpy格式:
strcpy(字符数组名1,字符数组名2)
功能:把字符数组2中的字符串复制到字符数组1中。串结束标志’\0’也一同复制。
- 要求字符数组1应有足够的长度,否则不能全部装入所复制的字符串。
- “字符数组1”必须写成数组名形式,而“字符数组2”可以是字符数组名,也可以是一个字符串常量,这是相当于把一个字符串赋予一个字符数组。
- 不能用赋值语句将一个字符串常量或字符数组直接赋给一个字符数组。
例6.17 strcpy函数应用
#include<stdio.h>
#include<string.h>
main()
{
char str1[30],str2[20];
printf("please input string1:\n");
gets(str1);
printf("please input string2:\n");
gets(str2);
strcpy(str1,str2);
printf("Now the string1 is:\n");
puts(str1);
}
5.strcmp函数
字符串比较函数strcmp格式如下:
strcmp(字符数组名1,字符数组名2)
功能:按照ASCⅡ码顺序比较两个数组中的字符串,并由函数返回值返回比较结果。
- 字符串1=字符串2,返回值为0
- 字符串1>字符串2,返回值为一正数
- 字符串1<字符串2,返回值为一负数
本函数也可以用于比较两个字符串常量,或比较数组和字符串常量。例如:
两个数组进行比较strcmp(str1,str2);
一个数组与一个字符串进行比较strcmp(str1,“hello”);
两个字符串进行比较strcmp("hello","how");
进行比较时若出现不同的字符,则以第1个不同的字符的比较结果作为整个比较的结果。
例6.19 strcmp函数应用
#include<stdio.h>
#include<string.h>
main()
{
char str1[30],str2[20];
int i;
printf("please input string1:\n");
gets(str1);
printf("please input string2:\n");
gets(str2);
i=strcmp(str1,str2);
if(i>0)
printf("str1>str2\n");
else
if(i<0)
printf("str1<str2\n");
else
printf("str1=str2\n");
}
6.strlen函数
测量字符长度函数strlen的格式如下:
strlen(字符数组名)
功能:测量字符串的实际长度(不包含字符串结束标志’\0’),函数返回值为字符串的实际长度。
例6.20 strlen函数应用
#include<stdio.h>
#include<string.h>
main()
{
char str[20];
int len;
printf("please input string:\n");
gets(str);
len=strlen(str);
printf("the length of string is:%d\n",len);
}
7.strlwr函数
将字符串转换成小写字母函数strlwr的格式如下:
strlwr(字符串)
功能:将字符串中的大写字母变成小写字母,其它字母不变。
8.strupr函数
将字符串转换成大写字母函数strupr的格式如下:
strupr(字符串)
功能:将字符串中的小写字母变成大写字母,其它字母不变。
6.4 多维数组
C语言中允许出现二维以上的数组,通常称之为多维数组。多维数组的一般形式如下:
类型 数组名[长度1][长度2]……[长度N];
二维以上的数组在编写程序的过程中很少使用,主要是因为这些数组要占用大量的存储空间。
6.5 数组应用举例
例6.23 班级竞选班长,共有3个候选人,输入参加选举的人数及每个人选举的内容,输出3各候选人最终得票数及无效选票数。
#include<stdio.h>
main()
{
int i,n,a[50],v0=0,v1=0,v2=0,v3=0;
printf("input number of electorate:");
scanf("%d",&n);
printf("input 1 or 2 or 3:\n");
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<n;i++)
{
if(a[i]==1)
v1++;
else if(a[i]==2)
v2++;
else if(a[i]==3)
v3++;
else
v0++;
}
printf("v1=%d v2=%d v3=%d non=%d",v1,v2,v3,v0);
}
例6.24 用冒泡法对任意输入的10个数进行由小到大排序
#include<stdio.h>
main()
{
int i,j,t,a[10];
printf("input 10 numbers:\n");
for(i=0;i<10;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<9;i++)
{
for(j=0;j<9-i;j++)
{
if(a[j]>a[j+1])
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
printf("the sorted numbers:");
for(i=0;i<10;i++)
{
printf("%d ",a[i]);
}
}
例6.25 将一个二维数组的行和列元素互换,存到另一个二维数组中
#include<stdio.h>
main()
{
int i,j,i1,j1,a[101][101],b[101][101];
printf("please input the number of rows(<=100)\n");
scanf("%d",&i1);
printf("please input the number of columns(<=100)\n");
scanf("%d",&j1);
printf("please input the element\n");
for(i=0;i<i1;i++)
{
for(j=0;j<j1;j++)
{
scanf("%d",&a[i][j]);
}
}
printf("array a:\n");
for(i=0;i<i1;i++)
{
for(j=0;j<j1;j++)
{
printf("%d,",a[i][j]);
}
printf("\n");
}
for(i=0;i<i1;i++)
{
for(j=0;j<j1;j++)
{
b[j][i]=a[i][j];
}
}
printf("array b:\n");
for(i=0;i<j1;i++)
{
for(j=0;j<i1;j++)
{
printf("%d,",b[i][j]);
}
printf("\n");
}
}
例6.27 输入一组字符,要求分别统计出其中英文字母、数字、空格以及其它字符的个数
#include<stdio.h>
main()
{
char c;
int letters = 0, space = 0, digit = 0, others = 0;
printf("please input some characters\n");
while ((c = getchar()) != '\n') /*当输入的不是回车时执行while循环体部分*/
{
if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
letters++; /*当输入的是英文字母时变量letters加1*/
else if (c == ' ')
space++; /*当输入的是空格时变量space加1*/
else if (c >= '0' && c <= '9')
digit++; /*当输入的是数字时变量digit加1*/
else
others++;
}
printf("char=%d space=%d digit=%d others=%d\n", letters, space, digit, others);
}