第六章 数组
构造数据类型之一
数组,有序数据的集合,用数组名标识
元素,属同一数据类型,用数组名和下标确定
§ 6.1 一维数组
一维数组的定义
定义方式,数据类型 数组名 [常量 表达式 ];
合法标识符 表示元素个数下标从 0开始
[ ],数组运算符单目运算符优先级 (1)
左结合不能用 ( )
例 int a[6];
a[0]0
1
4
5
a[1]
a[2]
a[3]
a[4]
a[5]
2
3
a
编译时分配连续内存内存字节数 =数组维数 *
sizeof(元素数据类型 )数组名表示内存首地址,是 地址常量
一维数组的引用
数组必须 先定义,后使用
只能逐个引用数组元素,不能一次引用整个数组
数组元素表示形式,数组名 [下标 ]
其中:下标可以是常量或整型表达式例 int i=15;
int data[i]; (?不能用变量定义数组维数 )
例 int a[10];
printf(“%d”,a); (?)
必须 for(j=0;j<10;j++)
printf(“%d\t”,a[j]); (?)
例 int data[5];
data[5]=10; //C语言对数组不作越界检查,使用时要 注意
一维数组的初始化
初始化方式在定义数组时,为数组元素赋初值
(在编译阶段使之得到初值)
int a[5]={1,2,3,4,5};
等价于,a[0]=1; a[1]=2; a[2]=3; a[3]=4; a[4]=5;
说明:
数组不初始化,其元素值为随机数
对 static数组元素不赋初值,系统会自动赋以 0值
当全部数组元素赋初值时,可不指定数组长度如 int a[5]={6,2,3};
等价于,a[0]=6; a[1]=2;a[2]=3; a[3]=0; a[4]=0;
如 int a[3]={6,2,3,5,1}; (?)
static i t ;
等价于,a[0]=0; a[1]=0; a[2]=0; a[3]=0; a[4]=0;
只给部分数组元素赋初值
int a[]={1,2,3,4,5,6};
编译系统根据初值个数确定数组维数
程序举例例 读 10个整数存入数组,找出其中最大值和最小值步骤,
1,输入,for循环输入 10个整数
2,处理,
(a) 先令 max=min=x[0]
(b) 依次用 x[i]和 max,min比较 (循环 )
若 max<x[i],令 max=x[i]
若 min>x[i],令 min=x[i]
3,输出,max和 min
#include <stdio.h>
#define SIZE 10
main()
{ int x[SIZE],i,max,min;
printf("Enter 10 integers:\n");
for(i=0;i<SIZE;i++)
{ printf("%d:",i+1);
scanf("%d",&x[i]);
}
max=min=x[0];
for(i=1;i<SIZE;i++)
{ if(max<x[i]) max=x[i];
if(min>x[i]) min=x[i];
}
printf("Maximum value is %d\n",max);
printf("Minimum value is %d\n",min);
}
例 用数组求 Fibonacci数列前 20个数
f[0]
f[1]
f[2]
f[3]
f[4]
f[5]
f[19]
……...
1
1
f[19]
0
1
4
5
2
3
19
2
3
5
#include <stdio.h>
main()
{ int i;
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]);
}
}
例 用冒泡法对 10个数排序排序过程:
( 1)比较第一个数与第二个数,若为逆序 a[0]>a[1],则交换;然后比较第二个数与第三个数;依次类推,直至第 n-1个数和第
n个数比较为止 ——第一趟冒泡排序,结果 最大 的数被安置在最后一个元素位置上
( 2)对前 n-1个数进行第二趟冒泡排序,结果使 次大 的数被安置在第 n-1个元素位置
( 3)重复上述过程,共经过 n-1趟冒泡排序后,排序结束输入 n 个数给 a[1] 到 a[n]
for j=1 to n-1
for i=1 to n-j
a[i]>a[i+1]真 假
a[i]?a[i+1]
输出 a[1] 到 a[n]
#include <stdio.h>
main()
{ int a[11],i,j,t;
printf("Input 10 numbers:\n");
for(i=1;i<11;i++)
scanf("%d",&a[i]);
printf("\n");
for(j=1;j<=9;j++)
for(i=1;i<=10-j;i++)
if(a[i]>a[i+1])
{t=a[i]; a[i]=a[i+1]; a[i+1]=t;}
printf("The sorted numbers:\n");
for(i=1;i<11;i++)
printf("%d ",a[i]);
}
例 用简单选择法对 10个数排序排序过程:
( 1)首先通过 n-1次比较,从 n个数中找出最小的,将它与第一个数交换 —第一趟选择排序,结果 最小 的数被安置在第一个元素位置上
( 2)再通过 n-2次比较,从剩余的 n-1个数中找出关键字 次小 的记录,
将它与第二个数交换 —第二趟选择排序
( 3)重复上述过程,共经过 n-1趟排序后,排序结束例 初始,[ 49 38 65 97 76 13 27 ]
k
j
i=1 13 49
一趟,13 [38 65 97 76 49 27 ]i=2 27 38
二趟,13 27 [65 97 76 49 38 ]
三趟,13 27 38 [97 76 49 65 ]
四趟,13 27 38 49 [76 97 65 ]
五趟,13 27 38 49 65 [97 76 ]
六趟,13 27 38 49 65 76 [97 ]
k
kk
k
j j j j j
j j j j j
Ch5_201.c
输入 n 个数给 a[1] 到 a[n]
for i=1 to n-1
for j=i+1 to n
a[j]<a[k]真 假
k=j
输出 a[1] 到 a[n]
k=i
a[i]?a[k]
i != k真 假
#include <stdio.h>
main()
{ int a[11],i,j,k,x;
printf("Input 10 numbers:\n");
for(i=1;i<11;i++)
scanf("%d",&a[i]);
printf("\n");
for(i=1;i<10;i++)
{ k=i;
for(j=i+1;j<=10;j++)
if(a[j]<a[k]) k=j;
if(i!=k)
{ x=a[i]; a[i]=a[k]; a[k]=x;}
}
printf("The sorted numbers:\n");
for(i=1;i<11;i++)
printf("%d ",a[i]);
}
#define N 6
main()
{ int a[N],b[?B?-60],c[]={1,2,3,4,5,6},i;
for(i=0;i<N;i++)
scanf(“%d%d”,&a[i],&b[i]);
for(i=0;i<N;i++)
printf(“%d,,a[i]);
printf(“\n”);
for(i=0;i<N;i++)
printf(“%d,,b[i]);
printf(“\n”);
for(i=0;i<N;i++)
c[i]=a[i]+b[N-i-1];
for(i=0;i<N;i++)
printf(“%d,,c[i]);
}
数组定义:必须用 常量 表达式数组元素引用
Ch6_001.c
§ 6.2 二维数组及多维数组
二维数组的定义
定义方式:
数据类型 数组名 [常量表达式 ][常量表达式 ];
数组元素的存放顺序
原因,内存是一维的
二维数组:按行序优先
多维数组:最右下标变化最快例 int a[3][4];
float b[2][5];
int c[2][3][4];
int a[3,4]; (?)
行数 列数元素个数 =行数 *列数
int a[3][2]
a[0][1]
a[1][0]
a[1][1]
a[2][0]
a[2][1]
0
1
4
5
2
3
a[0][0]
a[0][0] a[0][1]
a[1][0] a[1][1]
a[2][0] a[2][1]
int c[2][3][4]
0
1
2
34
5
6
7……….
..
20
21
22
23
c[0][0][0]
c[0][0][1]
c[0][0][2]
c[0][0][3]
c[0][1][0]
c[0][1][1]
c[0][1][2]
c[0][1][3]
c[0][2][0]
c[0][2][1]
c[0][2][2]
c[0][2][3]
c[1][0][0]
c[1][0][1]
c[1][0][2]
c[1][0][3]
c[1][1][0]
c[1][1][1]
c[1][1][2]
c[1][1][3]
c[1][2][0]
c[1][2][1]
c[1][2][2]
c[1][2][3]
二维数组理解例 int a[3][4];
2016
17
2018
19
2020
21
2022
23
2008
9
2010
11
2012
13
2014
15
2000
1
2002
3
2004
5
20006
7a[0][0] a[0][1] a[0][2] a[0][3]
a[1][0] a[1][1] a[1][2] a[1][3]
a[2][0] a[2][1] a[2][2] a[2][3]
每个元素 a[i]由包含 4个元素的一维数组组成二维数组 a是由 3个元素组成
a[0]
a[1]
a[2]
行名
0
1
4
5
2
3
a[0][1]
a[0][2]
a[0][3]
a[1][0]
a[1][1]
a[0][0]
a[1][3]
a[2][0]
a[2][1]
a[2][2]
a[2][3]
a[1][2]6
7
10
11
8
9
a[0]
a[1]
a[2]
二维数组元素的引用形式,数组名 [下标 ][下标 ]
二维数组元素的初始化
分行初始化:
例 int a[2][3]={{1,2,3},{4,5,6}};
a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]
1 2 3 4 5 6
全部初始化
按元素排列顺序初始化例 int a[2][3]={{1,2},{4}};
a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]
1 2 0 4 0 0
部分初始化例 int a[][3]={{1},{4,5}};
a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]
1 0 0 4 5 0
第一维 长度省略初始化例 int a[2][3]={1,2,3,4,5,6};
a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]
1 2 3 4 5 6
全部初始化例 int a[2][3]={1,2,4};
a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]
1 2 4 0 0 0
部分初始化例 int a[][3]={1,2,3,4,5};
a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]
1 2 3 4 5 0
第一维 长度省略初始化
程序举例例 将二维数组行列元素互换,存到另一个数组中
a= 1 2 34 5 6 b= 1 42 5
3 6
#include <stdio.h>
main()
{ int a[2][3]={{1,2,3},{4,5,6}};
int b[3][2],i,j;
printf("array a:\n");
for(i=0;i<=1;i++)
{ for(j=0;j<=2;j++)
{ printf("%5d",a[i][j]);
b[j][i]=a[i][j];
}
printf("\n");
}
printf("array b:\n");
for(i=0;i<=2;i++)
{ for(j=0;j<=1;j++)
printf("%5d",b[i][j]);
printf("\n");
}
}
例 求二维数组中最大元素值及其行列号
max=a[0][0]
for i=0 to 2
for j=0 to 3
a[i][j]>max真 假
max=a[i][j]
row=i
colum=j
输出,max和 row,colum
#include <stdio.h>
main()
{ int a[3][4]={{1,2,3,4},
{9,8,7,6},
{-10,10,-5,2}};
int i,j,row=0,colum=0,max;
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);
}
例 读入下表中值到数组,分别求各行、各列及表中所有数之和
12 4 6
15 7 9
8 23 3
2 5 17
12 4 6 22
15 7 9 31
8 23 3 34
2 5 17 24
37 39 35 111
#include <stdio.h>
main()
{ int x[5][4],i,j;
for(i=0;i<4;i++)
for(j=0;j<3;j++)
scanf("%d",&x[i][j]);
for(i=0;i<3;i++)
x[4][i]=0;
for(j=0;j<5;j++)
x[j][3]=0;
for(i=0;i<4;i++)
for(j=0;j<3;j++)
{ x[i][3]+=x[i][j];
x[4][j]+=x[i][j];
x[4][3]+=x[i][j];
}
for(i=0;i<5;i++)
{ for(j=0;j<4;j++)
printf("%5d\t",x[i][j]);
printf("\n");
}
}
§ 6.3 字符数组和字符串
字符数组
定义
字符数组的初始化
逐个字符赋值
用字符串常量
字符数组的引用例 char c[10],ch[3][4];
例 char ch[5]={?H?,?e?,?l?,?l?,?o?};
ch[0]
H e l l o
逐个字符赋值
ch[1] ch[2] ch[3] ch[4]
有问题 !
例 char ch[5]={?H?,?e?,?l?,?l?,?o?};
ch[0]
H e l l o
逐个字符赋值
ch[1] ch[2] ch[3] ch[4]
例 char ch[5]={?B?,?o?,?y?};
ch[0]
B o y \0 \0
逐个字符赋值
ch[1] ch[2] ch[3] ch[4]
例 r [ =“Boy”;
[
\ \
用字符串常量
[ [ [ [
例 char ch[6]={“H llo”};
char ch[6]=“Hello”;
char ch[]=“Hello”;
用字符串常量
ch[0]
H e l l o
ch[1] ch[2] ch[3] ch[4]
\0
ch[5]
例 char diamond[][5]={{'.','.','*'},{'.','*','.','*'},
{'*','.','.','.','*'},{'.','*','.','*'},{'.','.','*'}};
二维字符数组初始化
.,* \0 \0
,*,* \0
*,,,*
,*,* \0
.,* \0 \0
diamond[0]
diamond[1]
diamond[2]
diamond[3]
diamond[4]
例 char fruit[][7]={“Apple”,”Orange”,
”Grape”,”Pear”,”Peach”};
二维字符数组初始化
fruit[0]
fruit[1]
fruit[2]
fruit[3]
fruit[4]
A p p l e \0 \0
O r a n g e \0
G r a p e \0 \0
P e a r \0 \0 \0
P e a c h \0 \0
例 输出一个字符串
#include <stdio.h>
main()
{ char c[10]={'I',' ','a','m',' ','a',' ','b','o','y'};
int i;
for(i=0;i<10;i++)
printf("%c",c[i]);
printf("\n");
}
I
a
m
a
b
o
y
0
1
2
3
4
5
6
7
8
9
字符串
字符串及其结束标志
无字符串变量,用字符数组处理字符串
字符串结束标志:‘ \0’
例? hello”共 5个字符,在内存占 6个字节 字符串长度 5
h e l l o \0
104 101 108 108 111 0
内存存放字符 ASCII码
字符串的输入输出
逐个字符 I/O,%c
整个字符串 I/O,%s
例 用 %c
main()
{ char str[5];
int i;
for(i=0;i<5;i++)
scanf(“%c”,&str[i]);
for(i=0;i<5;i++)
printf(“%c”,str[i]);
}
例 用 %s
main()
{ char str[5];
scanf(“%s”,str);
printf(“%s”,str);
}
用字符数组名,不要加 &
输入串长度 <数组维数遇空格或回车结束自动加‘ \0?
用字符数组名,
遇‘ \0?结束例 main( )
{ char a[5]={?H?,?e?,?l?,?l?,?o?};
printf(“%s”,a);
}
例 main( )
{ char a[ ]=“Hello”;
printf(“%s”,a);
}
结果,Hello#-=*
h e l l o
0 2 31 4
结果,Hello
用? %s”输出时,遇 ‘ \0?结束
main()
{
char a[]={'h','e','l','\0','l','o','\0'};
printf("%s",a);
}
例输出,hel h e l \0 l o \0
数组中有多个 ‘ \0?时,
遇第一个结束
main()
{
int i;
char a[5];
scanf("%s",a);
for(i=0;i<5;i++)
printf("%d,",a[i]);
}
运行情况:
( 1)若输入 hel,正常
( 2)若输入 hell,正常
( 3)若输入 hello,用 %s 输出时,会出现问题
h e l \0
h e l l \0
h e l l o
输入字符串长度 <数组维数例 字符串输入举例
H o w \0
a r e \0
y o u? \0
#include <stdio.h>
main()
{ char a[15],b[5],c[5];
scanf("%s%s%s",a,b,c);
printf("a=%s\nb=%s\nc=%s\n",a,b,c);
scanf("%s",a);
printf("a=%s\n",a);
}
运行情况:
输入,How are you?
输出,a=How
b=are
c=you?
输入,How are you?
输出,a=How
scanf中 %s输入时,遇空格或回车结束运行情况:
输入,How are you?
例 若准备将字符串,This is a string.”记录下来,
错误 的输入语句为:
( A) scanf(“%20s”,s);
( B) for(k=0;k<17;k++)
s[k]=getchar();
( C) while((c=getchar())!=?\n?)
s[k++]=c;
常用的字符串处理函数包含在头文件 string.h
字符串输出函数 puts
格式,puts(字符数组 )
功能:向显示器输出字符串(输出完,换行)
说明:字符数组必须以‘ \0?结束
字符串输入函数 gets
格式,gets(字符数组 )
功能:从键盘输入一以 回车结束 的字符串放入字符数组中,
并自动加‘ \0’
说明:输入串长度应小于字符数组维数例 #include <stdio.h>
main( )
{ char string[80];
printf(“Input a string:”);
gets(string);
puts(string);
}
输入,How are you?
输出,How are you?
字符串连接函数 strcat
格式,strcat(字符数组 1,字符数组 2)
功能:把字符数组 2连到字符数组 1后面返值:返回字符数组 1的首地址说明,?字符数组 1必须足够大
连接前,两串均以‘ \0’结束 ;连接后,串 1的‘ \0’取消,
新串最后加‘ \0’
字符串拷贝函数 strcpy
格式,strcpy(字符数组 1,字符串 2)
功能:将字符串 2,拷贝到字符数组 1中去返值:返回字符数组 1的首地址说明,?字符数组 1必须足够大
拷贝时‘ \0’一同拷贝
不能使用赋值语句为一个字符数组赋值 例 char str1[20],str2[20];str1={“Hello!”}; (?)
str2=str1; (?)
例 strcpy与 strcat举例
#include <string.h>
#include <stdio.h>
void main()
{ char destination[25];
char blank[] = " ",c[]= "C++",
turbo[] = "Turbo";
strcpy(destination,turbo);
strcat(destination,blank);
strcat(destination,c);
printf("%s\n",destination);
}
Turbo C++
T
r
b
o
C
+
+
0
1
2
3
4
5
6
7
8
9
u
\0
24
…….
T
r
b
o
0
1
2
3
4
5
6
7
8
9
u
\0
24
…….
…….
T
r
b
o
\0
0
1
2
3
4
5
6
7
8
9
u
24
…….
…...
字符串比较函数 strcmp
格式,strcmp(字符串 1,字符串 2)
功能:比较两个字符串比较规则:对两串从左向右逐个字符比较( ASCII码),
直到遇到不同字符或‘ \0’为止返值:返回 int型整数,a,若字符串 1< 字符串 2,返回 负整数
b,若字符串 1> 字符串 2,返回 正整数
c,若字符串 1== 字符串 2,返回 零说明,字符串比较不能用? ==?,必须用 strcmp
字符串长度函数 strlen
格式,strlen(字符数组 )
功能:计算字符串长度返值:返回字符串实际长度,不包括‘ \0’在内例 对于以下字符串,strlen(s)的值为:
( 1) char s[10]={?A?,?\0?,?B?,?C?,?\0?,?D?};
( 2) char s[ ]=“\t\v\\\0will\n”;
( 3) char s[ ]=“\x69\082\n”; 答案,1 3 1
#include <string.h>
#include <stdio.h>
main()
{ char str1[] =,Hello!",str2[] =,How are you?”,str[20];
int len1,len2,len3;
len1=strlen(str1); len2=strlen(str2);
if(strcmp(str1,str2)>0)
{ strcpy(str,str1); strcat(str,str2); }
else if (strcmp(str1,str2)<0)
{ strcpy(str,str2); strcat(str,str1); }
else strcpy(str,str1);
len3=strlen(str);
puts(str);
printf(”Len1=%d,Len2=%d,Len3=%d\n”,len1,len2,len3);
}
例 strcmp与 strlen举例
How are you?Hello!
Len1=6,Len2=12,Len3=18
例 有三个字符串,找出其中最大者
H o w \0
H e l l o \0
H i g h \0
str[0]
str[1]
str[2]
#include <stdio.h>
#include <string.h>
main()
{ char string[20],str[3][20];
int i;
for(i=0;i<3;i++)
gets(str[i]);
if(strcmp(str[0],str[1])>0)
strcpy(string,str[0]);
else
strcpy(string,str[1]);
if(strcmp(str[2],string)>0)
strcpy(string,str[2]);
printf("\nThe largest string \
is:\n%s\n",string);
}
例 有十个学生的成绩,求平均分
92 85 68 75 54 88 98 45 61 79
92
85
68
54
88
98
45
75
61
79
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
a[8]
a[9]
a#include <stdio.h>
main()
{ int k,a[10];
for(k=0;k<10;k++)
scanf(“%d”,&a[k]);
for(k=0;k<10;k++)
sum+=a[k];
printf(“Average is %d\n”,sum/10);
}
例 有三个学生四门课成绩
92 85 68 75
54 88 98 45
61 79 81 40
张三李四王二数学 化学英语 物理二维数组例 比较 int a[2][3]={{5,6},{7,8}};
与 int a[2][3]={5,6,7,8};
5 6 0
7 8 0
5 6 7
8 0 0
例 int a[][10];
float f[2][]={1.2,2.2};
例 int a[5];
a={2,4,6,8,10};
例 int a[10];
float i=3;
a[i]=10;
例 char name[0];
float weight[10.3];
int array[-100];
例 char str[]=“Hello”;
char str[]={?H?,?e?,?l?,?l?,?o?};
h e l l o
0 2 31 4
h e l l o \0
0 2 31 4 5