400 likes | 585 Views
第 七 章. 数 组. 主要内容. 一、数组的基本概念 二、一维数组 三、二维数组 四、字符数组. 问题: 有 3 个数,编程计算这 3 个数的总和、平均值、每个数与平均值的差。. #include <stdio.h> void main() { float a1,a2,a3, sum, ave,c1,c2,c3; sacnf("%f%f%f",&a1,&a2,&a3); sum=a1+a2+a3; ave=sum/3; c1=a1-ave; c2=a2-ave;
E N D
第 七 章 数 组
主要内容 一、数组的基本概念 二、一维数组 三、二维数组 四、字符数组
问题: 有3个数,编程计算这3个数的总和、平均值、每个数与平均值的差。 #include <stdio.h> void main() { float a1,a2,a3, sum, ave,c1,c2,c3; sacnf("%f%f%f",&a1,&a2,&a3); sum=a1+a2+a3; ave=sum/3; c1=a1-ave; c2=a2-ave; c3=a3-ave; printf("sum=%f,ave=%f,c1=%f,c2=%f,c3=%f",sum,ave,c1,c2,c3); }
用循环来实现计算20个数的总和、平均值、每个数与平均值的差。用循环来实现计算20个数的总和、平均值、每个数与平均值的差。 假如问题的规模扩大为1000个数, 1。如何编程呢? 2。在运行程序时会有什么苦恼呢? #include <stdio.h> void main() { float a, sum=0, ave,c; for(i=1;i<=20;i++) { sacnf("%f",&a); sum=sum+a; } ave=sum/20; printf("sum=%f,ave=%f",sum,ave); for(i=1;i<=20;i++) { sacnf("%f",&a); c=a-ave; printf("第 %d 个数与平均值的差为 %f ", i,c); } } 可能的解决方法: 将程序中的20改为1000; 但在运行程序时会两次输入1000个数! 能不能在运行程序时1000个数只输入一次呢! 可以,但需要采用一种新方法把输入的1000个数保存起来!
用数组来存储输入的1000个数;再用一个数组来存储求出的1000个差值; 用循环来实现计算1000个数的总和、平均值、每个数与平均值的差。 假如问题的规模扩大为2000个数, 如何修改编程呢? #include <stdio.h> #define SIZE 1000 void main() { float a[SIZE], sum=0, ave,c [SIZE]; for(i=0;i<SIZE;i++) { sacnf("%f ",&a[i]); sum=sum+a[i]; } ave=sum/SIZE; printf("sum=%f,ave=%f ",sum,ave); for(i=0;i<SIZE;i++) { c[i]=a[i]-ave; printf("第 %d 个数与平均值的差为 %f ", i,c[i]); } } 解决方法: 将程序中 #define SIZE 1000 改为: #define SIZE 2000
《知识扩展》 • 计算机程序语言的数据机制 • 把程序里能够处理的数据对象划分为一些类型; • 提供一组基本数据类型,确定其书写方式,为每个基本类型提供一组基本操作,支持基本数据对象的表示和使用; • 提供一组由简单数据类型或数据对象构造更复杂数据类型或数据对象的手段。 • 最常用的数据组合机制——数组、结构及其另一种用于数据组织的重要机制指针 • 复合数据对象 • 复合数据类型 • 复合数据变量
一、数组的基本概念 • 数组是一组有序数据的集合。 • 如10个整数: 1,9,20,15,21,35,40,25,55,10 可以组成的一个数组; 该数组的第一个元素为1,最后一个元素为10,第4个元素为15。 • 如10个实数: 1.1,9.2,20.3,1.5,2.1,3.5,4.0,2.5,5.5,10.5 也可以组成的一个数组; 该数组的第一个元素为1.1,最后一个元素为10.5,第4个元素为1.5。 • c语言提出了数组类型的概念。并规定了对数组处理的方法。 • 对一个数组用一个统一的名字表示,对于数组中的每个元素用数组名及该元素在数组中的位置值(称为下标)联合起来表示。如数组a的第一个元素用a[0]表示, a[0] 中保存了第一个元素的值。
数组中的每一个元素都必须属于同一数据类型。数组中的每一个元素都必须属于同一数据类型。 • 用一个统一的数组名和下标唯一地确定数组中的元素。 • 数组是一种构造数据类型。 • 数组分为一维数组、二维数组、多维数组。 • 通常把线性列表、矢量等定义为一维数组。
二、一维数组 数组的长度. 一维数组的定义 格式 类型说明符 数组名[常量表达式] 数组元素的下标的范围是:从 0 到 9 举例 int a[10]; 说明 1。常量表达式表示数组中元素的个数。数组的每个元素 表示如下: a[0],a[1], a[2], a[3], a[4], a[5], a[6], a[7],a[8], a[9] 2。常量表达式中可以包含常量和符号常量,不能包含变量。 用符号常量指定数组大小的好处是什么? #define SIZE 10 void main( ) { int a[SIZE]; … } 用符号常量指定数组大小更容易调整程序。
一维数组的存储和引用 一维数组的存储结构 若有一数组定义为: int a[10]; 那么,该数组在内存中的存储结构是怎样呢? 编译器为数组分配一段连续的内存空间。 第一个元素a[0]存放在该内存区域的开始位置,最后一个元素存放在该内存区域的最后。如图1所示。 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] 一维数组元素的引用 数组元素的表示形式为: 数组名[下标] 对数组元素的引用与同类型的一般变量使用方式一样。例:执行 a[0]=3; a[0]对应的内存单元的内容为3。 图1 执行 a[3]=a[0]*5+3; 后,a[3]对应的内存单元的内容为18。
对数组的说明 1. 数组必须先定义,后使用。 2. 数组元素只能逐个引用,而不能一次引用整个数组。 数组元素的引用与同类型的一般变量使用方式一样。 …… int a[10]; a[0]=10; a[2]=a[0]*5; scanf("%d",&a[5]); printf("%d",a[5]); …… 下面的写法是错误: printf("%d",a); 或 在 i 未赋值时,写 printf("%d",a[i]); 3.当逐个使用数组中的每一个元素时,通常借助for循环语句。 假如有定义 int i , a[10] ; 数组的输入: for (i=0; i<=9; i++) scanf("%d", &a[i] ); 数组的输出: for (i=9; i>=0; i--) printf("%2d", a[i] ); …… 若运行时输入为: 9 4 6 7 8 5 3 2 4 0 则输出为: 0 4 2 3 5 8 7 6 4 9
一维数组的初始化 说明 1。定义数组时,对数组元素赋初值。 int a[10]={0,1,2,3,4,5,6,7,8,9}; 2。可以只给一部分数组元素赋初值。 int a[10]={0,1,2,3,4}; 3.要想使数组中全部元素数据为0,则采用如下形式。 int a[10]={0,0,0,0,0,0,0,0,0,0}; 4。在对全部数组元素赋初值时,可以不指定数组长度。 int a[ ]={0,1,2,3,4};
输入a[0]~a[9]的值 for j=0 to 8 for i=0 to 8-j a[i]>a[i+1] ? Y N a[i]和a[i+1] 交换 输出排序后的a[0]~a[9] 一维数组程序举例 通过对一维数组编程实例的研究,掌握一维数组的输入、处理、输出等操作,掌握对数组的编程规律(通常使用for语句)。 例 1. 用冒泡法对10个整数排序(由小到大)。 冒泡排序的思想: (假设为从小到大排序) 从数组的第一个元素起,相邻的两个元素进行比较,若a[i]>a[i+1],则互换此两个元素的值,直到所有元素比较完; 至此,数组中值最大的元素移到了数组的最后位置。 这样,数组元素就完成了一趟比较。 下一趟比较仍从数组的第一个元素起,但下界比第一趟少1; 若数组长度为n,则比较n-1趟就完成了数组的冒泡排序过程。
常用排序算法 • 冒泡排序 思想:第一轮,比较第0个元素和第1个元素,如果第0个元素大于第1个元素, 则两者交换,然后比较第1个元素和第2个元素,并作相同处 理,直到第N-2和N-1个元素比较完。此时最大数位于第N-1位置. 第二轮,与第一轮类似,但只比较到第N-2个元素。 依此类推,直到只需比较第0个和第1个元素,最终完成排序。 例: 原始数据 2 5 7 1 6 第一轮第一次比较后2 5 7 1 6 /* 2与5比较,2<5, 不交换*/ 第一轮第二次比较后2 57 1 6 /* 5与7比较,5<7, 不交换*/ 第一轮第三次比较后2 5 1 7 6 /* 7与1比较,7>1, 交换*/ 第一轮第四次比较后2 5 1 67 /* 7与6比较,7>6, 交换*/ a[0] a[1] a[2] a[3] a[4]
#include <stdio.h> #define N 10 void main() { int a[N], i,j,t; printf("input N numbers:\n"); for (i=0;i<=N-1;i++) scanf("%d",&a[i]); for (j=0;j<=N-2;j++) for (i=0;i<=n-2-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=0;i<=N-1;i++) printf("%d",a[i]); } 输入10个数组元素. 对10个数组元素排序. 输出排序后的10个数组元素.
例 用冒泡法对8个数排序(图解) 13 27 49 38 65 97 76 13 27 30 38 49 65 76 13 27 30 97 38 49 65 13 27 30 76 38 49 13 27 30 65 38 13 27 30 49 13 27 30 38 13 27 30 初始关键字 第三趟 第四趟 第五趟 第六趟 第一趟 第二趟 第七趟 n=8 13 38 例 13 49 38 27 27 49 13 38 30 76 13 38 30 27 65 49 97 13 27 76 30 49 65 27 97 76 30 65 30 97 76 97
常用排序算法 • 选择排序 思想:第一趟选出最小的数和第0个数交换, 第二趟选出除第0个数以外剩下数中最小的数和第1个数交换, 直到最后比较完第N-2和N-1,而完成排序。 例:原始数据 2 5 7 1 6 第一趟 1 5 7 2 6 /*第一次选出最小的数和第0个数交换*/ 第二趟 1 2 7 5 6 /*第二次选出次小的数和第1个数交换*/ 第三趟 1257 6 /*第三次选出剩下的数中最小数和第2个数交换*/ 第四趟 12 56 7/*第四次选出剩下的数中最小数和第3个数交换*/ a[0] a[1] a[2] a[3] a[4]
输入a[0]~a[9] for i=0 to 8 p=i for j=i+1 to 9 a[p]>a[j]? Y N p=j a[p]与a[i]交换 输出排序后的a[0]~a[9] 一维数组程序举例 举例 2. 用选择法对10个整数进行排序(由小到大)。 void main() { int a[10]; int i, j, t, p; printf("input 10 numbers:\n"); for (i=0;i<=9;i++) scanf("%d",&a[i]); for (i=0;i<=8;i++) {p=i; for (j=i+1;j<=9;j++) if (a[p]>a[j]) p=j; t=a[i];a[i]=a[p];a[p]=t; } printf("the sorted numbers:\n"); for (i=0;i<=9;i++) printf("%d",a[i]); } 输入10个数组元素. 对10个数组元素排序. 输出排序后的10个数组元素.
例 用简单选择法对7个数排序 p p p p p j j j j j j j j j j j 二趟: 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 ] 初始: [ 49 38 65 97 76 13 27 ] 例 i=1 49 13 i=2 一趟: 13 [38 65 97 76 49 27 ] 38 27 六趟: 13 27 38 49 65 76 [97 ]
在对大量数据进行处理时,使用数组,可以方便使用循环,进而简化编程。在对大量数据进行处理时,使用数组,可以方便使用循环,进而简化编程。 例:统计全班学生计算机课的平均成绩. 分析: 设定一个数组用来存储全班同学计算机课的成绩。 思考: 如果要统计多门课的平均成绩如何处理呢? 开始 输入学生人数iNumer i = 1 i <= iNumber N Y 成绩->sc[i],累加总分 i++ 计算平均分,并输出 结束 一维数组程序举例
#include <stdio.h> void main() { int sc[100]; /*存储每个同学一门课的成绩*/ int iStudentNumber = 0, iavag = 0, i = 0; printf("请输入学生数:"); scanf("%d", &iStudentNumber); printf("请按学号输入学生成绩:\n"); for(i = 1; i <= iStudentNumber; i++) { printf("%d :", i); scanf("%d", &sc[i]); iavag += sc[i]; } iavag =iavag / iStudentNumber; for(i = 1; i <= iStudentNumber; i++) printf("学号:%d 成绩:%d\n", i, sc[i]); printf("平均分: %d\n", iavag); } 求一科平均分实例代码
三、二维数组 1 2 3 4 2 3 4 5 3 4 5 6 第 1 列 第 4 列 第 1 行 第 2 行 第 3 行 把表格数据定义为二维数组。表格中的每个元素用行下标、列下标标识。如 a[i][j] 二维数组的元素在行、列两个方向上排列。
三、二维数组 a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] 二维数组的定义形式: 类型说明符 数组名[常量表达式1] [常量表达式2] 举例 float a[2][3] , b[4][5]; 说明 1. 二维数组中元素在内存中的排列顺序是:先行后列。如图3所示。 图3 2. 二维数组元素仍然是从a[0][0]开始。即 a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] 可以把二维数组看成是一个矩阵。 3. 二维数组元素的第一维下标习惯上也称为行下标,第二维下标称为列下标。 4. 二维数组中包含的元素个数为行数 × 列数。例如,数组b[4][5]的元素个数为 4×5=20,第一个元素是b[0][0],最后一个元素是b[3][4]。
二维数组元素的引用 格式 数组名[下标1] [下标2] 说明 1。数组必须先定义,后使用。 a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] 2。数组元素只能逐个引用,而不能一次引用整个数组。 数组元素的引用与同类型的一般变量使用方式一样。 举例 有一个数组定义为: int a[2][3]; 执行 a[0][1]=10;后,a[0][1]对应的内存单元的内容为10。 执行 a[1][2]=a[0][1]*5;后, a[0][2]对应的内存单元的内容为50。此时,数组存储区域的状态如图4所示。 图4
说明 二维数组输入/输出的一般格式。 int i, j; float a[4][5]; for (i=0; i<=3; i++) { for (j=0; j<=4; j++) printf("%4d",a[i][j]); printf"\n"); } …… int i,j; float a[4][5]; for (i=0; i<=3; i++) for (j=0; j<=4; j++) scanf("%d",&a[i][j]); …… 若程序运行时输入为: 4 3 2 6 5 ↙ 8 9 10 12 13 ↙ 17 19 12 14 16 ↙ 20 22 24 26 28↙ 上述双重循环的输出结果为: 4 3 2 6 5 8 9 10 12 13 17 19 12 14 16 20 22 24 26 28
二维数组的初始化 说明 1。分行给二维数组赋初值。 int a[2][3]={{1,2,3},{4,5,6}}; 2。按数组的排列顺序对各数组元素赋初值。 int a[2][3]={1,2,3,4,5,6}; 3.可以对部分元素赋初值。 int a[3][4]={{1},{5},{9}}; int a[3][4]={{1},{5,6},{0,9,7}}; 4。在对全部数组元素赋初值时,数组第一维的长度可以不指定。 int a[ ][3]={1,2,3,4,5,6}; int a[ ][4]={{0,0,3},{0},{0,10}}; a[1][1]=? a[2][3]=?
max=a[0][0] for i=0 to 2 for j=0 to 3 a[i][j]>max? Y N max=a[I][j] row=i colum=j 输出max,row,colum P128 二维数组程序举例 例1 将一个二维数组元素的行和列元素互换,存在另一个二维数组中。 例2 有一个3*4矩阵,输出最大元素的值,及其所在的行号和列号。 #include "stdio.h" main() { int i,j,max,row=0,colum=0; int a[3][4]={{1,2,3,4},{9,8,7,6}, {-10,10,-5,2}}; 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); }
四、字符数组 (一)、字符数组 (二)、字符串
(一) 字符数组 定义 char c[5]; 初始化 char c[5]={'h','a','p','p','y'}; 注意: 如果初值个数大于数组长度,按语法错误处理。 如果初值个数小于数组长度,只将这些字符赋给前面那元 素,其余元素自动赋空字符('\0')。 引用 main() {char c[5]={'h','a','p','p','y'}; int i; for (i=0;i<5;i++) printf("%c",c[i]); printf("\n"); } happy
(二)、字符串 定义 在c语言中,将字符串按字符数组来存放。 可以这样理解:凡以' \0 '结尾的字符数组就是字符串, 否则就是一个普通的字符数组。 与定义数组变量一样定义字符串变量 ,即 char c[5]; 初始化 char c[6]={"happy"}; 或省掉花括弧,即 char c[6]="happy"; • 这两个数组的区别: • 第一个数组长度为5; • 第二个数组长度为4. • 第一个数组是字符串; • 第二 个只是一个普通 • 的字符数组. char c[]="good"; 区别? char c[]={'g','o','o','d'};
字符串的输入及输出 方式一 逐个字符输入/输出。(用格式符%c,输入单位是串的一个元素) 方式二 将整个字符串一次输入或输出。 (在scanf/printf函数中使用格式符%s) char str[10] ; scanf("%s",str); printf("%s",str); happy happy good bye good 方式三 将整个字符串一次输入或输出。 (使用gets/puts函数) char str[10] ; gets(str); puts(str); happy happy good bye good bye
字符串处理函数 1.字符串连接函数 strcat(字符数组1,字符数组2); 功能 将字符串2连接到字符串1之后,结果放在字符数组1中。 举例 char str1[30] = {"Good "}; char str2[ ] = {"china"}; printf("%s",strcat(str1,str2)); 说明 (1) 字符数组1必须足够大,以便容纳连接后的新字符串。 (2) 连接前两个字符串的最后一个都是'\0'元素,连接时将字 符串1后的'\0'去掉,只在新串后保留一个'\0'。
2.字符串复制函数 strcpy(字符数组1,字符串2); 功能 将字符串2复制到字符串1中。 举例 char str1[10],str2[] = {"china"}; strcpy(str1,str2); 说明 (1) 字符数组必须足够大,以便容纳被复制的字符串。 (2) "字符数组1"必须写成数组名的形式。 "字符串2" 可以是数组名,也可以是字符串常量。 如: strcpy(str1,"china"); (3) 可以只复制第二个字符串的一部分。即: strcpy(str1, str2, 2); 将str2的前两个字符复制到str1中。
3.字符串比较函数 strcmp(字符串1,字符串2); 功能 比较两个字符串的大小。规则如下: 逐个比较每个字符(按ASCII码值比较),直到出现不同的 字符或遇到'\0'为止。 比较结果有函数值带回。 (1) 若字符串1=字符串2,函数值为0; (2) 若字符串1>字符串2,函数值为一个正整数; (3) 若字符串1<字符串2,函数值为一个负整数; 举例 if(strcmp(str1,str2)==0) printf("two string is samel!"); 不能用下列形式: if(str1==str2) printf("two string is samel!");
4. 求字符串长度的函数 strlen(字符串); 5.将字符串小写的函数 strlwr(字符串); 6.将字符串大写的函数 strupr(字符串);
字符串应用举例 例1 输入5个字符串,输出其中长度最大者。 #include <stdio.h> main() { char string[20]; char str[5][20]; int i; for (i=0;i<5;i++) gets(str[i]); strcpy(string,str[0]); for (i=1;i<5;i++) if (strlen(str[i])>strlen(string)) strcpy(string,str[i]); printf( " The largest string is :%s\n",string); } 程序运行时输入为: Russa France America Krea China 程序输出结果为: The largest string is:America
字符串应用举例 例2 输入一个字符串,然后将其通过循环语句实现 按逐个元素赋给另一个字符串。即实现串复制. #include <stdio.h> main() { char string1[20], string2[20]; int i=0; gets(str[i]); while(string1[i]!='\0') { string2[i]=string1[i]; i++; } puts(string2); }
例3 输入4名学生的姓名及三门课成绩,打印学生成绩表。(姓名、三门课成绩、平均分) main() { int i,j; char str[5][10]; float score[5][4],ave[5],sum; for (i=1;i<=4;i++) { printf("input the name of number %d:",i); scanf("%s",str[i]); printf("input the scores of number%d:",i); scanf("%f%f%f",&score[i][1],&score[i][2],&score[i][3]); } for (i=1;i<=4;i++) { sum=0; for (j=1;j<=3;j++) sum=sum+score[i][j]; ave[i]=sum/3; } 输入4名学生的姓名 及三门课成绩。 求4名学生的平均分。 (转下页)
(接上页) /* 下面按一定的格式输出4名学生的姓名、成绩、平均分:*/ printf("\n ***the table of score***\n"); printf("-----------------------------------\n"); printf("name math eng com ave\n"); printf("-----------------------------------\n"); for (i=1;i<=4;i++) { printf("%-5s",str[i]); for (j=1;j<=3;j++) printf("%6.1f",score[i][j]); printf("%6.1f\n",ave[i]); } printf("-----------------------------------\n"); }
作 业 实验指导书: 实验六---数组应用(一) 实验七---数组应用(二).