第五章 数组
声明
本文内容大多取自《高级语言程序设计一书》,为本人学习笔记记录,切勿用于商业用途。
数组的定义:数组是具有相同数据类型的一组有序数据的集合
数组中的数据称为数组元素,数组元素通过数组名和下标引用,下标是数组 元素在数组中的位置序号,表示该数组元素在数组中的相对位置。
第一节 一维数组
一、一维数组的定义
数组中的数据称为数组元素,数组元素通过数组名和下标引用,下标是数组 元素在数组中的位置序号,表示该数组元素在数组中的相对位置。
数组同变量一样,必须先定义后使用。数组占用内存单元,在定义数组时必须指定数组元素的 数据类型和数组元素的个数,这样才能为其分配相应的内存单元。
一维数组是只有一个下标的数组,其定义的一般形式:
数据类型符 数组名 1[长度 1],数组名 2[长度 2],…;
其中:
1)“数据类型符”是指数组元素的数据类型。数据类型可以是任何基本类型。
2)“数组名”与变量名一样,必须遵循标识符的命名规则。
3)“长度”必须是整型的常量表达式,必须用一对方括号括起来,表示数组的元素个数(又称 数组长度),可由整型常量或符号常量组成,但其中不能出现变量。
需要注意的是,在数组定义时“长度”外面的一对方括号,以及数组元素引用时 “下标表达式”外面的一对方括号,都是C语言语法规则要求的。
4、数组元素的下标是元素相对于数组首地址或起始地址的偏移量,所以从0开始 顺序编号。
5、数组名表示整个数组所占用的内存空间的首地址。同一数组中的所有元素, 按其下标的顺序占用若干连续的存储单元。
6、一个数组定义语句中可以只定义一个数组,也可以定义多个数组,还可以同 时定义数组和变量。
【例 1】一维数组定义的例子。
int a[10],w; /*定义一个长度是 10 的整型数组 a 和一个整型变量 w*/
float b[20],x; /*定义一个长度是 20 的单精度实型数组 b 和一个单精度实型变量 x*/
double c[30],y; /*定义一个长度是 30 的双精度实型数组 c 和一个双精度实型变量 y*/
char d[40],z; /*定义一个长度是 40 的字符型数组 d 和一个字符型变量 z*/
二、一维数组元素的引用
引用一维数组中任意一个元素的方法:
数组名[下标]
其中:
1)“下标”可以是一个整型常量、整型变量或整型表达式,其取值范围是 0~(长度-1)。需 要注意的是,在 C 程序运行过程中,系统并不自动检查数组元素的下标是否越界,即下标可以不在 0~(长度-1)的合法范围内。
2)任何一个数组元素,本质上就是一个变量,它具有和相同类型单个变量一样的属性,可以被 赋值,可以接收键盘输入的数据,也可以组成表达式。如果数组元素参与表达式运算,则必须已被 赋值。
3)C 语言中,数组作为一个整体,不能参与数据运算,只能对单个的数组元素进行处理。
4)定义一维数组后,则需要为其所有的元素分配内存单元,一维数组占用的内存字节数=数组 长度×每一元素占用的字节数,而且所占用的内存单元是连续的,并按照元素顺序依次排列。
【例】
#include <stdio.h>
void main()
{
int i,a[10];
for(i=0;i<=9;i++)
a[i]=i;
for(i=9;i>=0;i--)
printf("%d\n",a[i]);
}
运行结果:
三、一维数组的初始化
数组元素和变量一样,可以在定义时对数组元素赋初值,称为数组的初始化。
一维数组初始化的一般格式:
数据类型符 数组名[长度]={初值表},…;
具体地,一维数组的初始化可以分为以下几种情况:
1、给一维数组的全部元素赋初值。
例如:设int a[4]={1,2,3,4};
2、给一维数组的部分元素赋初值。
设int a[4]={1,2};
3、初值的个数不能超过一维数组元素的个数。
例如:int a[4]={1,2,3,4,5};
一维数组a的长度是4,而初值的个数是5,初值的个数超出了数组长度,则编译 时系统会报错。
4、给一维数组的全部元素赋初值时允许省略数组长度的说明。
例如:
int a[4]={1,2,3,4}; 则可以写成:int a[]={1,2,3,4};
需要注意的是,只能给数组元素赋值,不能给数组名赋值,因为数组名代表数组 的首地址,数组名是常量。
【例】 用数组来处理求Fibonacci数列问题
#include <stdio.h>
void 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]);
}
printf("\n");
}
【例2】将 5 个整数保存到一维数组后输出。
#include <stdio.h>
int main()
{
int i,a[5]={1,2,3,4,5};
//下标从0开始,0,1,2,3,4
for(i=4;i>=0;i--)
{
printf("%d\n",a[i]);
}
}
【例3】从键盘输入数据为数组各元素赋值。
#include <stdio.h>
int main()
{
int i,a[5];
for(i=0;i<=4;i++)
{
scanf("%d",&a[i]);
}
for(i=4;i>=0;i--)
{
printf("%d\n",a[i]);
}
}
运行结果:
第二节 二维数组
二维数组的定义:
二维数组也需要先定义后使用,二维数组的定义形式:
数据类型符 数组名[行长度][列长度],…;
1、数据类型可以是任何基本类型。
2、数组名和变量名一样,必须遵循标识符的命名规则。
3、行长度说明二维数组有几行,列长度说明二维数组有几列。行长度和列长度 都是一个“整型常量表达式”,表达式中不能出现变量。
4、二维数组的元素个数=行长度*列长度。
5、二维数组元素在内存中的排列顺序是“按行存放”,即先顺序存放第一行的 各个元素,再存放第二行的各个元素,依此类推。
6、可以把二维数组看作是一种特殊的一维数组,其每个元素都是一个一维数组。
7、一个数组定义语句中可以只定义一个二维数组,也可以定义多个二维数组;可 以在一条定义语句中同时定义一维和二维数组,同时还可以定义变量。
二维数组的初始化
二维数组的初始化分为以下几种情况。
1、按行给二维数组的全部元素赋初值,其一般形式:
数据类型符 数组名[行长度][列长度]={{第0行初值表},{第1行初值表},…,{最后一行 初值表}};
2、按二维数组在内存中的排列顺序给各元素赋初值,即不分行给二维数组的全 部元素赋初值,其一般形式:
数据类型符 数组名[行长度][列长度]={初值表};
3、只对每行的前若干个元素赋初值,此时所有未赋初值的二维数组二维数组元 素均为0值(即对于整型二维数组是0,对于实型二维数组是0.0,对于字符型二 维数组是‘\0’)。
4、只对前若干行的前若干个元素赋初值,此时所有未赋初值的的数组元素均为0 值。
5、如果对全部元素都赋初值,则“行长度”可以省略。需要注意的是只能省略 “行长度”,但第二维的长度即“列长度”不能省略。使用这种方式赋初值,允 许给出的初值不是列长度的整数倍。此时,行长度=初值个数整除列长度后加1。
6、如果分行给所有行的前若干个元素赋初值,则行长度可以省略。
【例】
将二维数组行列元素互换,存到另一个数组中。
#include <stdio.h>
void main()
{
int a[2][3]={{1,2,3},{4,5,6}};
int b[3][2],i,j;
printf("array b:\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 a:\n");
for(i=0;i<=2;i++)
{
for(j=0;j<=1;j++)
printf("%5d",b[i][j]);
printf("\n");}
}
第三节 字符数组和字符串
一、字符数组
字符数组的定义和初始化:
一维字符数组,用于存储和处理一个字符串,其定义格式与一维数值型数组一样。 一维字符数组的定义形式:
char 数组名[数组长度]={初值表};
其功能是定义一维字符型数组,并为其赋初值。
【例】
char c[10], ch[3][4];
一维字符数组的初始化
1、一维字符数组的初始化
(1)用字符初始化字符数组
例如:
char str1[8]={‘p’,‘r’,‘o’,‘g’,‘r’,‘a’,‘m’,‘\0’};
char str2[5]={‘C’,‘h’,‘i’,‘n’,‘a’};
(2)用字符串初始化字符数组
例如:
char str1[8]={“program”}
字符串是用双引号括起来的一串字符。在字符串末尾系统会自动地添加一个字符 串结束标志符‘\0’,表示字符串在此位置结束。字符‘\0’的ASCⅡ码值为0, 称为空字符,它不作为字符串的有效标志,只起到标志结束的作用,但需要占用1 字节的内存空间。
(3)用字符的ASCⅡ码值初始化字符数组。
例如:
char str1[8]={112,114,111,103,114,97,109,0};
(4)初始化时如果只提供了部分元素的值。未提供初值的元素自动赋值为‘\0’。
例如:
char str1[10]={“program”}
二维字符数组的初始 化
(1)用字符初始化二维字符数组。
例如:
char s[2][10] ={
{ ‘c’,‘o’,‘m’,‘p’,‘u’,‘t’,‘e’,‘r’},
{‘s’,‘c’,‘i’,‘e’,‘n’,‘c’,‘e’}
};
(2)用字符串初始化二维字符数组。
例如:
char s[2][10]={“computer”,“science”};
二维字符数组在初始化时,未提供初值的元素自动赋值为‘\0’。
字符数组的输入和输 出
1、一维字符数组的输入和输出
(1)使用scanf()和printf()函数
逐个字符输入和输出。在scanf()函数或printf()函数中用“%c”格式说明符每 次输入或输出一个字符,重复该过程完成整个字符串的输入和输出。
将字符串整个输入和输出。在scanf()函数或printf()函数中用“%s”格式说明 符一次性输入或输出整个字符串。
(2)使用gets()和puts()函数。使用字符串输入函数gets()或字符串输出函数 puts()将字符串整个输入或输出。
3、二维字符数组的输入和输出
(1)二维字符数组的输入。
对于二维字符数组,除了可以使用初始化的方法赋值外,还可以从键盘赋值。 二维字符数组的每一行可以看作一个一维字符数组,可以将二维字符数组的每 一行作为一个一维字符数组进行输入和输出。
二、字符串
字符串的定义和初始化:
字符串是指若干有效字符的序列,可以包括字母、数字、专用字符和转义字符等。
赋值方法有:
# 第一种方式是按单个字符的方式赋初值,其必须有一个是字符串的结束标志 符‘\0’;
# 第二种方式是直接在初值表中给出一个字符串常量。
需要注意的是,由于系统在存储字符串常量时,会在字符串末尾自动加 上一个结束标志符‘\0’,所以无需认为添加。另外,由于字符串结束标志符 ‘\0’也需要在字符数组中占用一个元素的存储空间,即1字节,因此在说明 字符数组长度时,至少为字符串所需长度加1。
字符串的输入和输出:
1、使用函数scanf( )和printf( )
(1)逐个字符的输入和输出。在scanf()或printf()函数中使用“%c”格式说 明符每次输入或输出一个字符,重复执行多次完成整个字符串的输入或输出。
(2)字符串的整体输入和输出。在scanf()或printf()函数中使用“%s”格式 说明符一次性输入或输出整个字符串。
(3)使用“%s”格式说明符输入字符串时,遇到空格或回车则认为字符串输 入结束。
(4)使用“%s”格式说明符输出字符串时,一旦遇到‘\0’则结束输出 (‘\0’不输出),其后字符不在输出。
2、使用函数gets( )和puts( )
使用字符串输出函数gets()或字符串输入函数puts()将字符串整体输入或输出。
1、字符串输入函数gets( )
【调用格式】gets(字符数组名)
【参数】字符数组名是已经定义的字符数组名。
【功能】从标准输入设备即键盘上输入一个字符串(可以包含空格,仅以回车 作为结束标志),并将其存储到指定的字符数组中。
【返回值】字符数组的首地址。
【说明】
1、gets( )函数输入的字符串的长度没有限制,编程者应保证字符数组有足够 大的空间,存放输入的字符串。
2、gets( )函数和使用“%s”格式说明符的scanf()函数都可以从键盘输入字 符串,但两者是有区别的。对于scanf()函数,回车和空格符都看成是输入字 符串的结束标志;对于gets()函数输入字符串中允许包含空格,只有回车才看 作是输入字符串的结束标志。
2、字符串输出函数puts( )
【调用格式】puts( )
【参数】字符数组名是已经存放字符串的字符数组名。
【功能】把字符数组名中所存放的字符串,输出到标准输出设备即显示器,并 以‘\n’取代字符串的结束标志‘\0’。所以用puts()函数输出字符串时,不 要求另外加换行符。
【返回值】无。
【说明】
1、字符串中允许包含转义字符,输出时产生一个控制操作。
2、puts()函数和使用“%s”格式说明符的printf()函数都可以输出字符串,但 两者是有区别的。对于printf()函数,不输出字符串结束标志符;对于puts()函 数,字符串结束标志符‘\0’转换为‘\n’输出。此外,puts()函数一次只能 输出一个字符串,而printf()函数用来输出字符串时一次可以输出多个。
3、字符串比较函数strcmp( )
【调用格式】strcmp(字符串1,字符串2)
【参数】“字符串1”和“字符串2”可以是字符串常量,也可以是已经存放 字符串的字符数组名。
【功能】比较两个字符串的大小,即两个字符串从左到右逐个字符进行比较 (按照ASCⅡ码值的大小进行比较),直到出现不同字符或遇到‘\0’为止。
如果“字符串1”等于“字符串2”,则函数返回值为0。
如果“字符串1”大于“字符串2”,则函数返回值是正整数(大于0的整数)。
如果“字符串1”小于“字符串2”,则函数返回值是负整数(小于0的整数)。
【说明】
1、如果一个字符串是另一个字符串从头开始的子串,则母串为大。
2、不能使用关系运算符“==”比较两个字符串,只能调用strcmp()函数进行 处理。
例:字符比较
//str这些开头的函数要有#include<string.h> 头文件支持 strcpy strpmp什么的
#include<stdio.h>
#include<string.h>
void main( )
{
int i,j,k;
char a1[ ]="wuhan", a2[ ]="beijing" ;
i=strcmp(a1,a2);
j=strcmp("china", "korea");
k=strcmp(a2, "beijing" );
printf("i=%d\nj=%d\nk=%d\n",i,j,k);
}
3、字符串复制函数strcpy( )
【调用格式】strcpy(字符数组名,字符串[,整型表达式])
【参数】
“字符数组名”是已经定义的字符数组名。
“字符串”可以是字符串常量,也可以是已经存放字符串的字符数组 名
“整型表达式”可以是任何整型表达式,这一参数可以省略。
【功能】将“字符串”的前“整型表达式”个字符组成新的字符串复制到“字 符数组”中,若省略“整型表达式”,则将“字符串”完整地复制到“字符数 组中”,字符数组的原有内容被覆盖。
【返回值】字符数组的首地址
【说明】
1、字符数组长度必须足够大,以便容纳复制过来的字符串。复制时,连同字 符串结束标志‘\0’一起复制。
2、不能用赋值运算符“=”将一个字符串直接赋值给一个字符数组,只能调 用strcpy( )函数处理。
【例 】有3个字符串,要求找出其中最大者。
#include <stdio.h>
#include <string.h>
void main()
{
char string[20],str[3][20];
int i;
for(i=0;i<3;i++)
gets(str[i]); //for循环依次输入3组字符串
if(strcmp(str[0],str[1])>0) //比较前两个字符串大小
strcpy(string,str[0]);
else
strcpy(string,str[1]); //把大的字符串赋值给srting
if(strcmp(str[2],string)>0) //再拿大的字符串和第三个比较。,如果第三个大则把第三个的值赋值给string
strcpy(string,str[2]);
printf("\nThe largest string is:\n%s\n",string); }
4、字符串连接函数strcat( )
【调用格式】
strcat(字符数组名,字符串)
【参数】
“字符数组名”是已经定义的存放字符串的字符数组名。 “字符串”可以是字符串常量,也可以是已经存放字符串的字符数组 名。
【功能】把“字符串”连接到“字符数组”中字符串的尾端(最后一个有效字 符的后面),组成新的字符串并存储到“字符数组”。“字符数组”中原来的 结束标志,被“字符串”的第一个字符覆盖,而“字符串”在操作中未被修改。
【返回值】字符数组的首地址。
【说明】
1、由于没有边界检查,编程者应注意保证字符数组长度足够大,以便容纳连 接后的新字符串;否则,会因长度不够出现问题。
2、连接前两个字符串都有结束标志‘\0’,连接后字符数组中存储的字符串 结束标志‘\0’被舍弃,只在新字符串的最后保留一个‘\0’。
【例】
#include<stdio.h>
#include<string.h>
void main()
{
char str1[10]={"Hello!"};
char str2[10]={"word!"};
printf("%s\n",strcat(str1,str2));
}
输出:
5、测字符串长度函数strlen( )(其中len是length的缩写)
【调用格式】strlen(字符串)
【参数】“字符串”可以是字符串常量,也可以是已经存放字符串的字符数组 名。
【功能】测字符串(字符串常量或字符数组)的实际长度(不包含字符串结束 标志符‘\0’)。
【返回值】字符串的实际长度。
【例】:测试字符串长度
#include<stdio.h>
#include<string.h>
void main()
{
char a1[10]=" china" ;
printf ("%d\n",strlen(a1));
printf ("%d\n", strlen("beijing\0wuhan"));
}
运行结果:
PS:再次注意,使用“%s”格式说明符输出字符串时,一旦遇到‘\0’则结束输出 (‘\0’不输出),其后字符不在输出。
【例】 把输入的字符串逆序排列,并显示。
#include<stdio.h>
#include<string.h>
void main()
{
char str[80];
int temp,i,j;
printf("Enter a string:\n");
scanf("%s",str);
for(i=0,j=strlen(str)-1;i<j;i++,j--)
{
temp=str[i];
str[i]=str[j]; /*交换i,j两个元素*/
str[j]=temp;
}
printf("\nReversed string:\n%s\n",str);
}
6、字符串大写字母转换成小写函数strlwr( )
【调用格式】strlwr(字符串)
【参数】“字符串”可以是字符串常量,也可以是已经存放字符串的字符数组 名。
【功能】将字符串中的大写字母转换成小写字母,其他字符(包括小写字母和 非字母字符)不转换。
#include<stdio.h>
#include<string.h>
void main()
{
char a1[6]="CHinA", a2[ ]="wuHAn" ;
printf ("%s\n",strlwr(a1));
printf ("%s\n",strupr(a2));
}
-------------------------------------------
个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!知识源于分享!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!