目录
1.1一维数组
1.1.1一维数组的定义
一维数组可以看作是用于存储一维数列中数据的集合。在使用数组前,需要对数组进行定义。
1.一维数组的定义
一维数组的定义格式如下:
类型说明符 数组名[数组长度]
类型说明符定义了数组中所有成员的数据类型。数组名代表这个数组的起始地址,是地址常量。
命名规则与变量名一致。数组长度定义了数组中存放的成员的个数。在数组定义时,数组长度是一个常量表达式。
例如,定义一个一维数组:
int array[6];
需要注意的是数组下标是从0开始的。
2.一维数组在内存中的存放。
其中一维数组array存放在从首地址为5000H开始的连续存储单元中,而数组名array的值就是5000H。由于array中每个成员都是int型,所以每个成员在内存中占4个字节。因为内存是按字节编址的,所以array[0]从5000H到5003H存放,array[1]从5004H到5007H存放,后续的成员以此类推。
6.1.2一维数组的初始化
如同变量的初始化一样,一维数组的初始化也是在定义一维数组时直接给其成员赋初值。否则数组中各成员的值将是随机的,不可预料。
1.一维数组初始化格式:
类型说明符 数组名[数组长度]=[处置列表];
例如,对一个一维数组初始化:
int array[6]={1,2,3,4,5,6};
2.一维数组初始化的几种情况
1)对一维数组全部成员都赋初值,数组长度可以缺省,系统将按照处置列表中的数值个数自动确定数组长度。例如:
int array[ ]={1,2,3,4,5,6};
2)当给出一维数组的数组长度时,可以在初值列表里列出部分成员的值。例如:
int array[6]={1,2,3};
在初值列表中只列出了3个值,与其对应的是:array[0]=1,array[1]=2,array[2]=3。对于剩余的成员array[3]~array[5],系统将自动为其填充初值为0。因此在定义数值类型的一维数组时只要在初值列表中给出一个初值,其后的成员就全部赋0值。例如:
int array[6]={0};
1.1.3一维数组成员的引用
一维数组定义后就可以使用了。由于c语言规定不能整体引用数组,所以只能逐个引用数组的成员。数组成员的表现形式如下:
数组名[下标]
与数组定义中的数组长度不同,在对数组成员引用时,下标可以是整型常量、整型变量或整型表达式。例如:
array[0],array[1],array[2*i+1]
1.1.4一维数组的使用
对于给定的数列{1,2,3,4,5}用冒泡法按升序排序并在屏幕上输出结果。
分析:冒泡法的思路是,将相邻数据两两一次比较,按从小到大或从大到小顺序交换,一趟过去之后,最大或最小的数字被交换到了最后一位。再从头开始比较,直到倒数第二位。例如,把最大的数字往后交换:
#include<stdio.h>
#define N 5
int main()
{
int i,j,temp;
int array[N]={5,2,3,4,1};
printf("The sequence before sorted:\n");
for(i=0;i<N;i++)
printf("%3d",array[i]);
printf("\n");
for(i=0;i<N-1;i++)
for(j=0;j<N-1-i;j++)
if(array[j]>array[j+1])
{
temp=array[i];
array[j]=array[j+1];
array[j+i]=temp;
}
printf("The sequence after sorted:\n");
for(i=0;i<N;i++)
printf("%3d",array[i]);
printf("\n");
return 0;
}
1.2多维数组
1.2.1多维数组的定义
一维数组只有一个下标变化,而有些情况下,如描述一个矩阵中成员的位置就不够用了。因此,
c语言允许构造多维数组。多维数组成员有多个下标,以标识它在矩阵中的位置,所以也称为多下标变量。
1.多维数组的定义
多维数组的定义格式如下:
类型说明符 数组名[第1维长度] [第2维长度]...[第n维长度];
尽管多维数组可以表达复杂的逻辑关系,但在计算机中的组织形式与一维数组类似,也是按照一定的顺序将数组的成员存储在内存中的。因此,也可以像对待一维数组那样来处理多维数组。
定义一个3×4的二维数组如下:
int arr2[3][4];
这数组第一个下标表示行号,第二个下标表示列号。
2.多维数组在内存中的存放
在c语言里数组在内存中是按“行优先”的顺序连续存放的。如下图所示:
第一行 | arr2[0][0] | arr2[0][1] | arr2[0][2] | arr2[0][3] |
第二行 | arr2[1][0] | arr2[1][1] | arr2[1][2] | arr2[1][3] |
第三行 | arr2[2][0] | arr2[2][1] | arr2[2][2] | arr2[2][3] |
数组名arr2是该数组的首地址。&arr2[1][0]表示arr2[1][0]的地址。因此arr2与&arr2[0][0]相同。但需注意的是,arr2+1的地址不是&arr2[0][1]的地址。
1.2.2多维数组的初始化
与一维数组类似,可以在定义的同时对多维数组成员赋初值。赋值时按“行优先”的顺序对数组成员一次赋值。其初始化形式为:
类型说明符 数组名[第1维长度] [第2维长度]...[第n维长度]={初值列表};
在初始化时有如下两种情况,以二维数组arr2[3][4]为例。
1.将初值写在一个大括号内
1)对全部成员显式赋初值
int arr2[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
此时,可以省略行下标,而不能省略列下标。例如:
int arr2[][4]={1,2,3,4,5,6,7,8,9,10,11,12};
根据初值列表中所有数据为12个,而arr2每行为4列,系统自动会确定数组为3行。
2)对部分成员显示赋初值
int arr2[3][4]={1,2,3};
此初始化后面未被显式赋初值的9个成员会被系统自动赋予0。
2.把初值按行分组
1)对全部成员显示赋初值
int arr2[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
2)对部分成员显式赋初值
int arr2[3][4]={{1,2},{5,6},{9,10,11,12}};
由于按行分组已经明确了行数,因此在此情况下可以缺省行下标。
3.二维以上数组的初始化
...
1.2.3多维数组成员的引用
1.多维数组成员的引用格式
多维数组成员的引用在原则上与一维数组是相同的,主要区别在下标的个数。如果定义的是一个n维数组,则此n维数组中成员的引用格式如下:
数组名[下标1][下标2]...[下标n];
需要注意的是在数组定义时,方括号中给出的是某一维的长度。而数组引用时,成员中的下标是该成员在数组中的位置标识。
2.二维数组成员的引用
在引用时需要注意以下几点:
1)数组成员在引用前必须先定义。
2)在引用数组成员时注意不要越界。
c语言在编译时不检查越界错误,但在运行时会引起程序出错或导致错误结果。
3)成员的下标可以是整型变量或表达式。
数组定义时的数组长度,只能是整型常量或整型变量表达式。
3.二维以上数组成员的引用
二维以上数组成员的引用与二维数组类似,例如,定义了一个三维数组:
int arr3[3][4][5];
则引用其成员arr3[1][0][2]并赋值的语句为:
arr3[1][0][2]=89;
1.3字符数组
当数组的类型说明符也就是数组成员的类型为字符型时称为字符数组。字符数组中的一个成员存放1个字符。字符数组的定义与其他数组类似。
1.3.1字符数组的定义
1.一维字符数组的定义
char 数组名[数组长度];
例如,char lastname[10];
2.二维字符数组的定义
char 数组名[数组长度1][数组长度2];
字符型数据也可以使用整形数组来存储。但是,字符型数据只占1个字节,显然使用整型数组存储字符数据会浪费空间,因此很少这样使用。
1.3.2字符数组的初始化
1.对一维字符数组的初始化格式
char lastname[5]={'L','i','a','n','g'};
字符数组定义的规则如下
1)如果在定义字符数组时不进行初始化,则数组中各成员的值将是随机的,不可预料的。
2)如果花括号中提供的初值个数大于数组长度,则按语法错误处理
3)如果初值个数小于数组长度,则只将这些字符赋给数组中前面那些成员,其余的成员自动确定为空字符(即'\0')。
4)如果提供的初值个数与预定的数组长度相同,在定义时可以省略数组长度,系统会自动根据初值个数确定数组长度。
2.对二维字符数组的初始化格式
1)
char name2[3][5]={{'Z','h','o','u'},{'W','u'},{'Z','h','e','n','g'}};
2)
char name2[][5]={{'Z','h','o','u'},{'W','u'},{'Z','h','e','n','g'}};
3)
char name2[3][5]={'Z','h','o','u','\0','W','U','\0','\0','\0','Z','h','e','n','g'};
4)
char name2[][5]={'Z','h','o','u','\0','W','U','\0','\0','\0','Z','h','e','n','g'};
显然3)、4)两种格式不推荐。
1.3.3字符数组成员的引用
与整型数组成员的引用一样
1.3.4使用字符数组处理字符串
1.字符串在字符数组中的形式
字符串是指用双引号引起来的若干有效字符的序列。字符串是编程语言中表示文本的数据形式。然而,c语言并没有专门的字符串变量用于存放字符串,而是放在要给字符型的数组中。字符串中的每一个字符对应字符数组中的每一个成员。这样在c语言程序中可以通过对字符数组的操作来处理字符串。
在c语言中可以在初始化字符型数组时直接将字符串整体赋值给该字符数组,这比利用循环结构将单个字符一一存入要方便很多。例如:
char lastname[6]="Zheng";
则数组成员的指为:
lastname[0]='Z'、lastname[1]='h'、lastname[2]='e'、lastname[3]='n'、
lastname[4]='g'、lastname[5]='\0'
2.字符串结束符
由于字符串后面隐含了字符'\0'。因此用字符串初始化字符数组时,要特别注意数组长度的定义。如果char lastname[5]="Zheng";,则会出现错误。
字符'\0'在字符串中叫串结束符是“字符串结束标志”。有了这个标志系统就可以自动计算字符串的长度。当然,在定义字符数组时还是需要估计所要存放字符串的长度,保证数组长度始终大于等于字符串实际长度。如果在一个字符数组中存放的字符个数是变化的,应考虑最多字符的情况,数组长度在定义时选择一个成员长度的最大值。
特别需要注意的是,除了对字符数组初始化,不能将一个字符串字符串常量或字符数组直接赋值给一个字符数组。以下情况是不合法的:
s1="Zhang";
s2=s1;
3.字符串的输入/输出
对字符串的输入/输出,除了用字符输入/输出格式控制符“%c”配合格式输出函数printf和格式输入函数scanf输入/输出字符串的单个有效成员外,还可以用字符串输入/输出的格式控制符“%s”,即字符串格式控制符,配合格式输出函数printf和格式输入函数scanf对字符串有效字符整体输入/输出。
1)用printf函数和“%s”格式输出字符串
例如,将整个字符串一次输出:
char lastname[]={"Zheng"};
printf("%s",lastname);
注意:输出的字符中不包括结束符'\0';用“%s“输出字符串时,printf函数中的输出项是字符数组名,不是数组成员名。如果一个字符数组包含一个以上'\0',则遇第一个'\0'时输出就结束。
2)用scanf函数和”%s“格式输入一个字符串
例如,从键盘输入字符串并赋给字符数组:
char lastname[6];
scanf("%s",lastname);
scanf函数中的输入项lastname是已定义的字符数组名,输入的字符串应短于已定义的字符数组的长度。
如果要用一个scanf函数输入多个字符串,则在输入时以空格或Enter键分隔。例如:
char lastname1[6],lastname2[6],lastname3[6];
scanf("%s%s%s",lastname1,lastname2,lastname3);
由于系统把空格字符作为输入字符串之间的分隔符,因此只将空格前的字符串“Zhou”送到lastnaem中,并在“Zhou”后加'\0'。为了克服这些不便,c语言提供了专门对字符串进行输入/输出的函数,这些函数也包含在stdio.h中。
3)字符串输出函数puts
puts函数的作用是将一个字符串输出到屏幕上。与printf不同,puts在输出字符串时,遇到'\0'后会自动加上换行。
例如,用puts函数输出的字符串中可以包含转义字符:
#include <stdio.h>
int main()
{
char name2[]={"Jack Ma\nBill Gates"};
puts(name2);
return 0;
}
/*其输出结果为:Jack Ma
Bill Gates */
4)字符串输入函数gets
不同于读取一个字符的函数getchar(),gets()函数用于从键盘缓冲区读取字符串,直到出现换行符,最后加上'\0'作为字符串结束。
由于gets函数可以输入含有空格的字符串,所以这一点比scanf函数要方便一些。例如,从键盘中输入的字符串“LP,Qing”,并赋给字符数组name2。Enter键是gets函数的输入结束标志。
需要注意的是:用puts和gets函数只能输出或输入一个字符串。
1.3.5字符串处理函数
除了puts和gets函数外,c语言的函数库还提供了一些专门用来处理字符串的函数。这些函数在string.h头文件中进行了声明,只要将string.h头文件包含在程序中,就可以调用这些字符串处理函数了。
下面介绍几种常用的字符串处理函数
1.字符串复制函数strcpy
strcpy函数用于复制字符串,其调用形式为:
strcpy(字符数组1,字符串/字符数组2);
该函数的作用是将字符串复制到字符数组1中去。需要注意的是strcpy中字符数组1的长度不应小于被复制的字符串的长度。此外,字符数组1必须写成数组名形式。例如:
char s1[10],s2[]="Zheng";
strcpy(s1,s2);
如果在复制前未对s1数组赋初值,则s1中存放的是随机值。当把s2中的字符串用strcpy函数复制到字符数组s1中后,s1前面的字符就被s2中存放的字符取代,而后面的字符依然是原有的随机值。
2.两个字符串的连接函数strcat
strcat是用于连接两个字符串的函数,其调用形式为:
strcat(字符数组1,字符串/字符数组2);
该函数的作用是把字符数组2中存放的字符串连接到字符数组1中存放的字符串的后面,连接的结果依然放在字符数组1中,连接前两个字符串的后面都有'\0',连接时将字符数组1中的字符串后面的'\0'取消,然后进行连接。最后在连接组成的新串末尾保留'\0'。函数调用后返回的是字符数组1的地址,也就是新字符串保存在数组1中。
需要注意的是:字符数组1必须足够大,以便容纳连接后的新字符串。
3.字符串比较函数strcmp
strcmp作用是比较字符串1和字符串2。
其调用形式为:
strcmp(字符串1/字符数组1,字符串2/字符数组2);
字符串可以是存放字符串的字符数组名,也可以是字符串常量。因此,如下形式都是合法的:
strcmp(s1,s2);
strcmp("United States","P.R China");
//其运行结果为1
字符串比较的规则是按自左至右的顺序对两个字符串的字符逐对比较字符的ASCII的值,直到出现不同的字符或遇到'\0'为止。如果全部字符相同,则认为相等;若出现不同的字符,则以第一个相同的字符的比较结果为准。当字符串1等于字符串2时,strcmp函数的返回值为0;当字符串1大于字符串2时,strcmp函数的返回值为正整数;当字符串1小于字符串2时,strcmp函数的返回值为负整数。
注意:对两个字符串比较,不能直接使用关系运算符连接字符串,如s1>s2,要用strcmp(s1,s2)来判断两字符串的大小。例如:
if(strcmp(s1,s2)<0)
printf("Right");
4.测试字符串长度函数strlen
strlen函数用于测试字符串的长度。函数值为字符串中的有效字符的个数(不包括'\0'在内)。
其调用形式为:
strlen(字符串/字符数组);
strlen函数中的参数也可以是字符串常量。这样测量的就是该字符串的长度。
5.字符串字母大小写转换函数
1)将字符串中的大写字母转换成小写字母的函数strlwr
其调用形式为:
strlwr(字符数组)
2)将字符串中的小写字母转换成大写字母的函数strupr
其调用形式如上。