500 likes | 669 Vues
本章主要内容. 第五章 数 组. 一维数组的定义及引用 二维数组的定义及引用 字符数组的定义及引用 字符串处理函数. 数组的引进. 数组是相同类型变量的有序集合。 一个数组里集合了多个数据对象,这些数据对象被称为数组中的元素。 数组中的每一个元素都属于同一种数据类型,它们用一个统一的数组名称和下标(元素在数组中的位置)来唯一确定。 数组也是变量。需要先定义后引用。. 数组举例 :. int a[6]; 上面定义了一个整型数组。 数组名称为 a 数组中有 6 个整型变量 数组中的 6 个基本元素为:
E N D
本章主要内容 第五章 数 组 • 一维数组的定义及引用 • 二维数组的定义及引用 • 字符数组的定义及引用 • 字符串处理函数
数组的引进 • 数组是相同类型变量的有序集合。 • 一个数组里集合了多个数据对象,这些数据对象被称为数组中的元素。 • 数组中的每一个元素都属于同一种数据类型,它们用一个统一的数组名称和下标(元素在数组中的位置)来唯一确定。 • 数组也是变量。需要先定义后引用。
数组举例: • int a[6]; • 上面定义了一个整型数组。 • 数组名称为a • 数组中有6个整型变量 • 数组中的6个基本元素为: a[0],a[1],a[2],a[3],a[4],a[5]。 • 上面方括号中的0~5是数组下标,表明各个元素在数组中的位置。
1. 一维数组的定义 5.1一维数组的定义及引用 • 一维数组的定义: 当数组中每个元素都只带有一个下标时,这个数组就被称为一维数组。 • 定义一维数组的一般形式: 数据类型名 数组名[常量表达式]; • 例如: int num[5]; float score[10];
定义一维数组时,说明几点: 1.“数据类型名”可以是任意的数据类型。 2.“数组名”必须是合法的标识符。 3.“常量表达式”表示数组长度(即数组中的元素个数),一定要用方括号括起来,且里面不允许包含变量。 4. 一维数组中每个元素只有一个下标,并且第一个元素的下标为“0”,最后一个元素的下标为“数组长度减1”。
注意: • 若在程序编译或运行时再给数组长度赋值,程序将在编译时出错。 • 例如: main() { int n; scanf("%d",&n); char ch[n]; …… } 变量说明部分 一定放在main() 函数的开头!
2.一维数组的引用 • 引用格式:数组名[下标表达式] • 说明: • “下标表达式”的值必须是一个整型的量。 • 对于所引用的数组元素,使用方法和前面学过的简单数据类型变量使用方法相同,包括取地址等运算。 • C语言没有语法结构能同时引用数组的所有元素,只能一个一个的引用每一个数组元素。
【例5.1】从键盘输入5个整数,将它们反序输出。【例5.1】从键盘输入5个整数,将它们反序输出。 main() { int i; int nums[5]; for(i=0;i<5;i++) scanf("%d",&nums[i]); for(i=4;i>=0;i--) printf("%5d",nums[i]); } 运行情况: 12 34 5 7 89 89 7 5 34 12
3.一维数组的初始化 • 初始化,即赋初值。C语言允许定义数组时直接对数组进行初始化。 • 一般形式: • 类型说明符 数组名[常量表达式]={数值表}; • 举例: float var[8]={0.1,1.2,2.6,3.5, 4.3,5.5,3.5,5.5}; int a[5]={2,3,4,5,6}; 初始化时,各元素的值要顺序放在一对花括号里面,各元素值之间用逗号间隔。
说明: • 当花括号中的数值表中的数据个数少于数组定义中的元素个数时,C语言将这些数据方别赋给数组的前几个元素,其余数组元素自动被初始化为0。 • 当对数组元素赋初值时,可省略数组长度。 例如: float var[]={0.1,1.2,2.6,3.5,s 4.3,5.5,3.5,5.5}; int a[]={2,3,4,5,6}; 系统将认为数组的元素个数就是后面初始化时所提供的数据的个数。
C语言规定,只有静态存储(static)数组、外部存储(extern)数组才能初始化。C语言规定,只有静态存储(static)数组、外部存储(extern)数组才能初始化。 • 新的C标准(如Turbo C中)更允许对局部自动(auto)数组初始化。 • 如果定义数组时没有对数组元素初始化,外部数组和函数的局部静态数组中的所有元素都将被自动初始化为0。 • Turbo C编译系统对在main函数下的静态存储数组初始化时,可省略static关键字。
为数组中若干元素赋相同初值时,要注意不能随意简化。为数组中若干元素赋相同初值时,要注意不能随意简化。 例如: float var[8]={ 0.1,0.1,0.1,0.1,0.1, 5.5,3.5,5.5}; 不能简化为: float var[8]={ 0.1*5,5.5,3.5,5.5}; 否则,系统将认为数组中的各元素的值分别为: var[0]=0.1*5,var[1]=5.5,var[2]=3.5,var[3]=5.5,var[4]=0,……,var[7]=0。
允许以赋值方式为数组各元素赋初值。 例如: float var[4]; var[0]=0.1*5;var[1]=5.5;var[2]=3.5;var[3]=5.5; • 也可以使用控制语句为数组元素赋初值。static float var[4]; int i; for(i=0;i<4;i++) scanf(“%f”,&var[i]); ……
【例5.2】计算从键盘上任意键入的10个数的和。【例5.2】计算从键盘上任意键入的10个数的和。 不使用数组, 程序怎么写? main() { int i; float num[10],sum=0.0; printf(“Input 10 numbers:\n”); for(i=0;i<10;i++) scanf("%f",&num[i]); for(i=0;i<10;i++) sum=sum+num[i]; printf("The sum is %8.3f\n",sum); }
【例5.5】用冒泡法对10个整数排序(从小到大)。【例5.5】用冒泡法对10个整数排序(从小到大)。 思 路 对相邻两个数进行比较,将较小的调到前面,两两比较一轮之后,最大的一个数被放置在最后面;接着从头开始重复执行以上操作,次大的数被放置在倒数第二位,依次类推,数列由后往前逐渐成型。
冒泡法的核心:小数上浮,大数下沉。 • 冒泡法第一轮:使最大的数放在最后一个位置上
冒泡法第二轮:使次大的数放在倒数第二个位置上!冒泡法第二轮:使次大的数放在倒数第二个位置上!
源程序清单如下: main() { int num[10];int i,j,temp; printf("Please input 10 numbers:\n"); for(i=0;i<10;i++) scanf("%d",&num[i]); for(i=0;i<10;i++) for(j=0;j<10-i;j++) if(num[j]>num[j+1]) {temp=num[j]; num[j]=num[j+1]; num[j+1]=temp; } printf("The sorted numbers:\n"); for(i=0;i<10;i++) printf("%4d",num[i]); }
冒泡法排序中的核心程序段: for(i=0;i<10;i++) for(j=0;j<10-i;j++) if(num[j]>num[j+1]) { temp=num[j]; num[j]=num[j+1]; num[j+1]=temp; }
1.二维数组的定义 5.2 二维数组的定义及引用 • 二维数组定义的一般形式: 数据类型名 数组名[常量表达式1][常量表达式2]; • 例如: double a[3][3],b[2][2]; int f[2][3];
几点说明: • 定义一个二维数组a[3][3],一定不要写成a[3,3]。 • 同一维数组一样,二维数组(或多维数组)中行、列下标的值也都是从0开始的。 • 二维数组中各元素的顺序遵照按行存放的原则。例如,定义一个二维数组a[3][3]后,其中的元素a[0][2]在内存中被存放在元素a[1][0]之前。 • 二维数组可以看成是一个特殊的一维数组,只是这个一维数组的每一个元素又是一个一维数组。
2. 二维数组的引用 • 引用的一般形式: 数组名[下标表达式1][下标表达式2] • 例如: f[2][2],f[2*4][3],f[2+1][4%2] 下标表达式的值必须是一个整型的量,可以是整型常量、整型变量或者结果为整型的表达式。
说明: • 二维数组中的元素地址可表示为: &数组名[下标表达式1][下标表达式2] • 可以把二维数组或多维数组中的元素看成是普通的变量。基本数据类型的变量所能进行的各种操作,同样适用于二维数组或多维数组中的元素。 • 例如: f[2][3]=f[2][2]/2+1; f[2][2]=f[1][2]*f[2][1];
3. 二维数组的初始化 方法1:直接赋初值。适用于数据较少时。 • 将数组元素的所有初始值都写在一个花括号内,由编译系统按照数组元素在内存中存放的顺序对各元素赋初值。 • 例如: int num[3][4]={11,2,23,4,51,6, 7,8,92,10,0,12};
方法2:分行为二维数组赋值。适用于每一行的初始值个数少于每一行中的数组元素个数时。方法2:分行为二维数组赋值。适用于每一行的初始值个数少于每一行中的数组元素个数时。 • 例如: int num[3][4]={{11,2}, {51,6,7}, {92,10,0,12}}; 每一行中后面的剩余元素被自动赋值为0 !
二维数组的长度不能随意省略,必须遵守如下规则:二维数组的长度不能随意省略,必须遵守如下规则: • 使用第一种方式,只有当为二维数组的所有元素赋初值时,所定义数组的第一维的长度才可以省略。 • 例如: int num[ ][4]={11,2,0,0,51, 6,7,0,92,10,0,12};
使用第二种方式,无论是为二维数组的所有元素赋初值,还是为二维数组的部分元素赋初值,定义数组时都可以省略第一维的长度。使用第二种方式,无论是为二维数组的所有元素赋初值,还是为二维数组的部分元素赋初值,定义数组时都可以省略第一维的长度。 • 无论采用上述哪一种方式为二维数组元素赋初值,在定义数组时第二维的长度都绝对不可以省略。
【例5.6】 有一个3×4的矩阵,编写一个程序,找出其中的最大值和最小值,并输出其所在的行号和列号。 main() { int i,j,row1,col1,row2,col2,max,min; static int a[3][4]={{12,3,45,5}, {23,34,56,1},{11,22,33,74}}; max=a[0][0];min=a[0][0]; for(i=0;i<3;i++) for(j=0;j<4;j++) { if(a[i][j]>max) { max=a[i][j];row1=i;col1=j;} if(a[i][j]<min) { min=a[i][j];row2=i;col2=j;} } printf("max=%5d,row=%d,col=%d\n",max,row1,col1); printf("min=%5d,row=%d,col=%d\n",min,row2,col2); }
【例5.7】 从键盘上任意键入一个3行4列的矩阵,要求输出其转置矩阵(注意换行输出)。 main() { int i, j;int a[3][4],b[4][3]; for (i=0; i<3; i++) /*输入原始矩阵a*/ for (j=0; j<4; j++) scanf("%d", &(a[i][j])); for (i=0; i<3; i++) /*计算矩阵a的转置矩阵b*/ for (j=0; j<4; j++) b[j][i] = a[i][j]; printf("\n"); /*输出转置矩阵b*/ for (i=0; i<4; i++) { for (j=0; j<3; j++) printf("%7d ", b[i][j]); printf("\n"); } }
5.3 字符数组 • 字符数组,即存放字符数据的数组。 • 字符数组操作: • 字符数组的定义及引用 • 字符数组的初始化 • 字符数据的输入输出 • 字符串处理函数
1.字符数组的定义及引用 • 定义及引用方法:同一般数组。 • 举例: char c1[8]; char c2[3][10]; • 每一个字符数组元素对应一个字符数据。 • 字符数组名可表示该字符数组的首地址!
字符数组的初始化(方法一) 方法一:逐个字符赋给字符数组中各元素. 例如: char c[5]={‘H’,‘e’,‘l’,‘l’,‘o’}; 则上述字符赋给字符数组c中的5个元素: c[0] ~ c[4]。
说明: • 若数组的初值个数少于数组长度,剩余元素为空字符‘\0’。 • 若初始化时省略第一维数组长度,系统根据初值个数自动确定。
字符数组的初始化(方法二) • 方法:用字符串常量为字符数组中各元素赋初值。 • 说明:每个字符串尾都有一个‘\0’,作为字符串结束标志。
举例: 用字符串常量为字符数组初始化: char ch2[10]={“Hello”}; char ch3[2][10]={{“Hello”},{”World”}}; 可化简为: char ch2[5]=“Hello”; char ch3[2][10]={“Hello”,”World”}; 二维数组不能再化简了!下面是错误的: char ch3[2][10]=“Hello”,”World”;
2. 字符数组的输入输出 方法一: 使用 scanf( )和printf( )函数。 • 采用“%c”格式符逐个字符输入、输出。 • 采用“%s”格式符将字符串常量整个输入或输出。
【例5.9】逐个字符输出“Hello,World!”。 • main() • { • char c1[12]={ • 'H','e','l','l','o',',', • 'W','o','r','l','d','!'}; • int i; • for(i=0;i<12;i++) • printf("%c",c1[i]); • printf("\n"); • } • 运行后,屏幕上显示:Hello,World!
【例5.11】用“%s”格式符输入、输出字符串。 main() {char c3[10]; static char c4[ ]={" are good."}; scanf("%s",c3); printf("%s%s\n\n",c3,c4); } 运行后,键入: You are 屏幕上显示输出: You are good. 使用scanf函数时, 输入的字符串中如果含有空格 或制表符,系统遇到时会认为输 入结束,接着自动在字符串的 末尾加上结束标志‘\0’。
字符数组的输入输出 方法二: gets( )函数:输入字符数组 puts( )函数:输出字符数组
gets( )函数: • 格式:gets(字符数组名); • 功能: 直接输入字符串,直到到遇回车为止。
puts( )函数: • 格式: puts(字符数组名); • 功能: 直接输出字符串,直到遇到结束标志‘\0’为止,输出后自动换行。
【例5.13】使用gets函数和puts函数实现二维字符数组的输入、输出。【例5.13】使用gets函数和puts函数实现二维字符数组的输入、输出。 #include <stdio.h> main() { char string[3][15]; int i; for(i=0;i<3;i++) /*输入多个字符串*/ gets(string[i]); printf("The output is:\n"); for(i=0;i<3;i++) /*输出多个字符串*/ puts(string[i]); }
3.字符串处理函数 C语言的函数库提供了很多处理字符串的函数。 程序中使用这类函数,必须在文件开头进行预定义: #include <string.h> 常用字符串函数
(1) 字符串连接函数 • 格式:strcat(串1,串2) • 功能:连接两个字符串,将“字符串2”接在“字符串1”的后面,“字符串2”不变。
(2) 字符串比较函数 • 格式:strcmp(串1,串2) • 功能:若“字符串1”>“字符串2”,则函数返回值为一正整数,其值为两字符ASCII代码的差;若“字符串1”<“字符串2”,则函数返回值为一负整数,其值仍然为两字符ASCII代码的差。
(3) 求串长函数 • 格式:strlen(串) • 功能:测试“字符串”的实际长度。 • 说明:长度为“字符串”中有效字符的个数(不包含字符串尾部的‘\0’)
(4)字符串拷贝函数 • 格式:strcpy(串1,串2) • 功能:将“字符串2”拷到“字符串1”中去。 • 注意:不能使用赋值语句将一个字符串常量或字符数组直接赋给一个字符数组。 如下面都是不合法的: str1={“abcd”}; str1=str2;
【例5.15】字符串拷贝示例。 字符串函数 定义在头文件 string.h中 #include <string.h> main() { static char str1[40]={"white"}, str2[ ]={"snow"}; puts(strcpy(str1,str2)); printf("%s\n",strcpy(str1,"Red rose")); } 运行该程序,结果显示: snow Red rose
(5) 其他字符串处理函数 • 转换小写字母函数 strlwr(串) 功能:将“字符串”中的大写字母转换成小写字母。 • 转换大写字母函数 strupr(串) 功能:将“字符串”中的小写字母转换成为大写字母。
【例5.16】任意键入3个字符串,编程找出最小的一个。【例5.16】任意键入3个字符串,编程找出最小的一个。 #include <string.h> main() { char string[30]; char ch[3][30]; int i; for(i=0;i<3;i++) gets(ch[i]); strcpy(string,ch[0]); for(i=1;i<3;i++) if(strcmp(ch[i],string)<0) strcpy(string,ch[i]); printf("The result is :\n%s\n",string); }