1
第七章 数组的概念及应用
2
本讲主要内容
? 数组的概念
? 一维数组
? 二维及多维数组
? 字符数组
? 综合举例
3
数组的概念
——概念引入
用基本数据类型可以解决所有问题吗?
例如,对 某班学生的成绩按由高到底的次序进
行排序。
3 名?
30 名?
4
数组的概念
数组 是具有一定 顺序关系 的若干 相同
类型变量的集合体,组成数组的变量称为
该数组的 元素 。
数组属于构造类型。
5
一维数组
——定义与引用
? 一维数组的定义
类型说明符 数组名 [ 常量表达式 ];
例如,int a[10]
表示 a 为整型数组,有 10个元素,a[0]...a[9]
可以是 常量 和 符号常量,不能用变量。
引用
必须先定义,后使用。
只能逐个引用数组元素,而不能一次引用整个数组。
例如,a[0]=a[5]+a[7]-a[2*3]
数组名的构成方法与一般变量名相同。
6
一维数组
——存储顺序
数组元素 在内存中顺次存放,它们的
地址是连续的 。
例如:具有 10个元素的数组 a,在内存中
的存放次序如下,
数组 名字 是数组 首元素的内存地址 。
数组名是一个 常量,不能被赋值。
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] a
7
一维数组 ——初始化
可以在编译阶段使数组得到初值,
? 在定义数组时对数组元素赋以初值。
例如,int a[10]={0,1,2,3,4,5,6,7,8,9};
? 可以只给一部分元素赋初值。
例如,int a[10]={0,1,2,3,4};
int b[10]={,1,,3,,5};
? 不能给数组整体赋初值。
? 在对全部数组元素赋初值时,可以不指定数组长度。
例如,int a[]={1,2,3,4,5}; 程序举例
9
存储顺序
按行存放,上例中数组 a的存储顺序为,
二维数组 ——定义及引用
? 二维数组的定义
类型说明符 数组名 [常量表达式 ][常量表达式 ]
例如,float a[3][4];
a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23
a[0]——a00 a01 a02 a03
a[1]——a10 a11 a12 a13
a[2]——a20 a21 a22 a23
a 可以理解为,
引用
例如,b[1][2]=a[2][3]/2;
下标不要越界
10
二维数组
——初始化
? 分行给二维数组赋初值
例如,int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
? 将所有数据写在一个 {}内,按顺序赋值
例如,int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
? 可以对部分元素赋初值
例如,int a[3][4]={{1},{0,6},{0,0,11}};
程序举例
12
字符数组
? 定义和引用
用来存放字符数据的数组。
Char c[10]={?I?,??,?a?,?m?,??,?h?,?a?,?p?,?p?,?y?}
注意,初值的字符个数应小于或等于数组长度,如果初值个数小于数
组长度,则只将这些字符赋给数组中前面那些元素,其余的元素自
动定为空字符 (即 '\0')
Char c[]={?I?,??,?a?,?m?,??,?h?,?a?,?p?,?p?,?y?}
表示初值的个数即为数组的长度
程序举例 1 程序举例 2
15
有效字符串的长度 与 字符数组的长度
Char c[10]={?i?,? ?,?a?}
有效长度,与数组长度分别为 3,10
C语言规定了一个, 字符串结束标志,,以字符 ‘ \0?代表,
它是一个空操作符,一个辨别标志。
合法定义,
Char c[]={“I am happy”}
Char c[]=“I am happy”
注意,C数组的长度是字符串常量的长度 +1
字符串与字符串结束标志
16
有字符串常量,例如,"china"
没有字符串变量,用字符数组来存放字符串
一般来说,字符串以‘ \0?为结束标志,但字符数组并不
要求它的最后一个字符一定为‘ \0?
例,char str[4]={?s?,?c?,?a?,?u?};
char str[8]={112,114,111,103,114,97,109,0};
char str[8]={'p','r','o','g','r','a','m','\0'};
char str[8]="program";
char str[]="program";
字符串
17
字符数组的输入 /输出
? 方法
? 逐个字符输入输出
? 将整个字符串一次输入或输出
例,char c[]="China"; printf("%s",c);
char c[10]; scanf(“%s”,c);
? 注意
? 输出字符不包括 '\0'
? 用, %s”输出字符串时,输出项是字符数组名(不加 &),
输出时遇到第一个 ‘ \0?结束 (字符中可能有多个 ‘ \0?)。
? 用 scanf输入多个字符串时,以空格分隔;输入单个字符
串时其中不能有空格。
例如,
程序中有下列语句,
static char str1[5],str2[5],str3[5];
scanf("%s%s%s",str1,str2,str3);
运行时输入数据,
How are you? 内存中变量状态如下,
str1,H o w \0
str2,a r e \0
str3,y o u? \0
若改为,
static char str[13];
scanf("%s",str);
运行时输入数据,
How are you?
内存中变量 str 内容如下,
str,H o w \0
18
若干注意问题
1.数组名称代表该数组的起始地址
scanf(“%s”,&str) <----- 错
scanf(“%s”,str) <----- 对
2.用 scanf输入字符串时以回车或空格作为结束标记
3,C语言中不允许用赋值表达式对字符数组赋值 ;
char str[6]; str=“China”; <----错
Char str[6]=“china”; <----对
例,p131_cha.c
19
字符串处理函数
?puts 输出字符串
gets 输入字符串
(#include<stdio.h>)
?strcat 字符串连接
strcpy 字符串复制
strcmp 字符串比较
strlen 字符串长度
strlwr 将字符串中的大写字符转换为小写字符
strupr 将字符串中的小写字符转换为大写字符
(#include<string.h>)
20
Puts and gets
Puts:将一个字符串 (以 ‘ \0?结束的字符序列)输出到终端,
其中输出的字符串中可以包含转义字符。
puts(str);
Gets:从终端输入一个字符串到字符数组,并且得到一个函
数值,该函数值是字符数组的起始地址。
gets(str); 以回车键作为结束标志
注意,puts和 gets函数只能输入或输出一个字符串。
21
strcat
strcat(字符数组 1,字符数组 2)
连接两个字符数组中的字符串,把字符串接到字符串
的后面,结果放在字符数组 1中,函数调用后得到一个函
数值 ——字符数组 1的地址。
char str1[30]={"People's Republic of "};
char str2={"China"};
printf("%s",strcat(strl,str2));
输出,People's Republic of China
注意:字符数组 1必须足够大,以便容纳连接后的新字符串
, 字符数组 1”必须写成数组名形式(如 strl),,字
符串 2”可以是字符数组名
22
Strcpy-字符串复制
Strcpy(str1,str2); 将字符串 2复制到字符数组 1中
相当于 str1=str2,但不能直接赋值
Strcpy(str1,str2,5);
23
例如,strcmp(str1,str2);
strcmp("China","Korea");strcmp(str1,"Beijing");
规则,对两个字符串自左至右逐个字符相比 ( 按 ASCII码值大小比较 ),直到出
现不同的字符或遇到 ‘ \0?为止 。 全部字符相同, 则认为相等;若出现不相
同的字符, 则以第一个不相同的字符的比较结果为准 。 比较的结果由函数值
带回,
① 如果字符串 1=字符串 2,函数值为 0。
②如果字符串 1>字符串 2,函数值为一正整数。
③如果字符串 1<字符串 2,函数值为一负整数。
注意,对两个字符串比较,不能用以下形式,
if(strl==str2) printf("yes");
而只能用 if(strcmp(str1,str2)==0) prinif("yes");
Strcmp(字符串 1,字符串 2)-字符串比较
24
其他字符串函数
Strlen ---字符串长度,有效长度
Char str[10]=“scau”;printf(“%d”,strlen(str)); 输出为 5
Strlwr ---小写
Strupr ---大写
25
应用举例 -1
? 题目,
? 接受键盘输入的两个字符串,并将其首尾相接后输出。
每个字符串内部不含空格,两个字符串之间以空白符分
隔。
? 分析,
? 数据结构,
? 字符串的存储需要用字符数组
? 算法要点,
? 字符串输入,可以用具有词处理功能的 Scanf()函数
? 字符串拼接方法:先找到第一个字符串的末尾,然后
将第二个串的字符逐个添加到末尾。注意,要去掉第
一个串的结束符 '\0',但第二个串的结束符 '\0'要添加
进去。
26
main()
{
char str1[50],str2[20];
int i,j;
printf("Enter string No.1:\n");
scanf("%s",str1);
printf("Enter string No.2:\n");
scanf("%s",str2);
i=j=0;
while(str1[i]!='\0')
i++;
while((str1[i++]=str2[j++])!='\0') ;
printf("string No.1->%s\n",str1);
}
27
运行结果,
Enter string No.1,
acceding
Enter string No.2,
IJKLMNOPQRS
string No.1->abcdefghIJKLMNOPQRS
28
应用举例 -2
? 题目:从键盘输入若干行文本,每行以回车结束,
以 ctrl+z 作为输入结束符,统计其行数。
? 分析,
? 数据结构,
? 由于只统计行数,所以不必使用数组存储文本内容,
只须定义一个字符变量暂存读入的字符。
? 算法要点,
? 读入字符可以用 getchar() 函数。
? 每读入一个字符,要判断是否输入结束
? 要判断读入的是否回车符,定义一个整型变量回车符
进行计数,以实现统计行数的功能。
29
#include<stdio.h>
main()
{
int c,nl;
nl=0;
while((c=getchar())!=EOF)
if(c=='\n')
++nl;
printf("%d\n",nl);
}
30
运行结果,
This supplement is designed as a tutorial
for a student who uses Data Structures
with C++ without the language
background
or who wishes for a quick review of basic
C++ concepts,
5
31
应用举例 -3
? 题目:把输入的字符串逆序排列,并显示。
? 分析,
? 数据结构,
? 输入的字符串用字符数组存放。
? 算法要点,
? 逆序排列用交换算法,求出字符串最后一个字符
的下标,然后将第一个和最后一个交换,第二个
和倒数第二个交换,...。
32
main()
{
char str[80];
int c,i,j;
printf("Enter a string:\n");
scanf("%s",str);
for(i=0,j=strlen(str)-1;i<j;i++,j--)
{
c=str[i];
str[i]=str[j];
str[j]=c;
}
printf("\nReversed string:\n%s\n",str);
}
33
运行结果,
Enter a string,
abcdefgh
Reversed string,
hgfedcba
34
应用举例 -4
? 题目:从键盘输入字符,以 ctrl+z 结束,统计输入
的数字 0~ 9、空白符和其它字符的个数。
? 分析,
? 数据结构,
? 定义一个具有 10 个元素的整型数组来存放数字 0~ 9
的个数。
? 定义两个整型变量来存放空白符和其它字符的个数。
? 算法要点,
? 计数用的数组和变量要初始化为 0。
? 用循环结构处理字符读入,内嵌分支结构处理计数。
35
#include<stdio.h>
main()
{ int c,i,nwhite,nother,ndigit[10];
nwhite=nother=0;
for(i=0;i<10;i++)
ndigit[i]=0;
while((c=getchar())!=EOF)
if(c>='0'&&c<='9')
++ndigit[c-'0'];
else if(c==' '||c=='\n'||c=='\t')
++nwhite;
else
++nother;
for(i=0;i<10;i++)
printf("digit '%d':%d\n",i,ndigit[i]);
printf("white space:%d\n",nwhite);
printf("other character:%d\n",nother);
}
36
运行结果,
The use of the double colon in front of
the variable name,in lines 11,13,and
16,instructs the system that we are
interested in using the global variable
named index,
digit '1':4
digit '2':0
digit '3':1
digit '4':0
digit '5':0
digit '6':1
digit '7':0
digit '8':0
digit '9':0
white space:34
other character:132
37
应用举例 -5
? 题目,
? 从键盘输入一个字符串(长度不超过 20,其中不含空
格),将其复制一份,复制时将小写字母都转换成为
大写字母)。
? 分析,
? 数据结构
? 定义两个数组,存放字符串。
? 算法要点
? 将小写字母 转换为大写字母,小写字母 -'a'+'A'。
38
main()
{
char a[20],b[20];
int i;
printf("Enter a string:\n");
scanf("%s",a);
i=0;
do
{
b[i]=(a[i]>='a'&&a[i]<='z')?
a[i]-'a'+'A':a[i];
}while(a[i++]!='\0');
printf("Copyed string:\n%s\n",b);
}
39
运行结果,
Enter a string,
Programmer
Copyed string,
PROGRAMMER
40
应用举例 -6
? 题目,
? 从一个三行四列的整型二维数组中查找第一个出现
的负数。
? 分析
算法要点
? 用两层嵌套的 for 循环来遍历数组元素,判断是否
为负数。
? 当找到第一个负数时就应该退出循环,为此,应定
义一个标记变量,用于标记找到与否的状态,并将
此标记加入循环控制条件中,以控制循环在适当时
候退出。
41
main()
{ int i,j,found,num[3][4];
printf("Enter 12 integers:\n");
for(i=0;i<3;i++)
for(j=0;j<4;j++)
scanf("%d",&num[i][j]);
found=0;
for(i=0;i<3 && !found;i++)
for(j=0;j<4 && !found;j++)
found=num[i][j]<0;
if(!found)
printf("not found\n");
else
printf("minus number num[%d][%d]:%d\n",i-1,j-1,num[i-1][j-1]);
}
42
运行结果,
Enter 12 integers,
3 5 56 1 45 -6 43 -1 1 4 -8 15
minus number num[1][1]:-6
43
应用举例 -7
? 题目
? 用筛选法求 100以内的素数
? 分析
? 数据结构
? 定义一个具有 100 个元素的数组,用来标记整数 1~
100是否素数。 0表示非素数,1表示素数。
? 算法要点
? 本例使用筛选法,1不是素数,从 2开始,每找到一个
素数,便将其倍数全部标记为非素数,最后省下的便
是素数。
44
N-S图
定义及初始化变量
将 1 标记为非负数
n=1; n<=100; n++
n是素数?
Y N
输出 n
将 n 的所有倍数都标
记为非负数
45
#include<stdio.h>
#define SIZE 100
#define PWIDTH 10
main()
{
char sieve[SIZE];
int i,n,printcol;
for(i=0;i<=SIZE;i++)
sieve[i]=0;
sieve[0]=1;
printcol=0;
46
for(n=1;n<=SIZE;n++)
if(sieve[n-1]==0)
{
printf("%5d",n);
if(++printcol>=PWIDTH)
{
putchar('\n');
printcol=0;
}
for (i=n;i<=SIZE;i=i+n)
sieve[i-1]=1;
}
}
47
运行结果,
2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97
48
作 业
? P141 7.2,6.4,6.9
? 预习, C程序设计, 第 8章