请编写如下程序: 输入100名学生的成绩,要求输出高于平均分的成绩。 算法:为了保存100名学生的成绩,需要定义100个变量(假定为a1,a2,…a100)来存放,且用变量与平均分(假定为avg)一一比较如下: if(a1>avg)printf(“%f\n”,a1); if(a2>avg)printf(“%f\n”,a2); …… if(a100>avg)printf(“%f\n”,a100);
项目四 学生成绩的排序 一个班有40位学生参加了期终考试(考了三门课),现要按成绩的高低输出成绩单。 项目四 学生成绩的排序 项目要求 一个班有40位学生参加了期终考试(考了三门课),现要按成绩的高低输出成绩单。 程序的运行要求:(成绩任意输入,为了方便,假设只有五个同学)
任务1 多个学生一门课成绩的输入、输出 分析:全班一共有四十个同学,显然定义四十个简单变量x1,x2,……x40, 任务1 多个学生一门课成绩的输入、输出 一、问题情景 一个班40位同学参加了一次数学考试,现要输入全班同学的成绩,并按逆序输出。 分析:全班一共有四十个同学,显然定义四十个简单变量x1,x2,……x40, 然后输出是不科学的。因为是逆序输出,因而要求输入的每个同学的成绩都 必须保存。那么如何解决这个问题呢?其实,仔细分析一些,不难发现每个 同学的成绩都具有相同类型。这样,就须引入了一个新的概念,即数组。
三、相关知识 1、数组: 一组具有相同数据类型的数据的有序的集合 2、数组元素: 数组中的每一个数组元素具有相同的名称,不同的下标,可以作为单个变量使用,所以也称为下标变量。在定义一个数组后,在内存中使用一片连续的空间依次存放数组的各个元素。
三、相关知识 一维数组的定义(先定义后使用) 1.定义方式: 类型说明符 数组名[常量表达式] 2.例: int a[10] 一维数组的定义(先定义后使用) 1.定义方式: 类型说明符 数组名[常量表达式] 2.例: int a[10] 定义一个数组,数组名a,有10个元素,每个元素的类型均为int。 这10个元素分别是:a[0]、a[1]、a[2]、a[3]、a[4]、....、a[8]、a[9]。
三、相关知识 × 3.说明: 例如: int n; scanf("%d",&n); int a[n]; (2)数组名后是[ ],不能是( )。 (3)常量表达式表示元素的个数,即数组的长度。下标从0开始! (4)C语言不允许对数组的大小做动态定义 例如: int n; scanf("%d",&n); int a[n]; × 因为在编译时,C编译器根据已知数组大小分配内存。
【例4-1】数组元素的使用。输入十个学生的成绩,并将其输出。 #include "stdio.h" main() { int i,a[10]; printf("输入数组元素:"); for(i=0;i<10;i++) scanf("%d",&a[i]); printf("输出数组元素:"); printf("%5d",a[i]); }
三、相关知识 补充 (1)C语言不检查数组下标越界,但是使用时, 一般不能越界使用,否则结果难以预料 (2)C语言还规定,数组名是数组的首地址。即a=&a[0]
三、相关知识 一维数组元素的引用 1.先定义,后使用。不能一次引用整个数组 2.表示形式: 数组名[下标] 3.下标可以是整型常量或表达式。 2.表示形式: 数组名[下标] 3.下标可以是整型常量或表达式。 例如: a[0]=a[5]+a[7]-a[2*3]
任务1的具体实现 #include "stdio.h“ #define N 10 main() { int i,score[N]; printf(" 请输入本班同学的成绩:"); for(i=0;i<N;i++) scanf("%d",&score[i]); printf(" 按逆序输出本班同学的成绩:"); for(i=N-1;i>=0;i--) printf("%3d",score[i]); } 注:为了程序运行方便,假设只有10人
【例4-2】求学生的总评成绩。现有十个学生,从键盘上输入他们的 平时成绩、期终成绩,输出总评成绩。 总评成绩=平时成绩*40%+期终成绩*60%. #include "stdio.h" main() { int i; float a[11],b[11],c[11]; printf("输入平时成绩:"); for(i=1;i<=10;i++) scanf("%f",&a[i]); printf("输入期终成绩:"); scanf("%f",&b[i]); c[i]=0.4*a[i]+0.6*b[i]; printf("输出总评成绩:"); printf("%5.1f",c[i]); printf("\n"); } 输入10个平时成绩给a[1]到a[10] 输入10个期终成绩给b[1]到b[10] for(i=0;i<10;i++) c[i]=0.4*a[i]+0.6*b[i]; 输出总评成绩c[1]直到c[10]
三、相关知识 一维数组的初始化 (1)定义数组时对数组元素赋以初值。 int x[5]={1,2,3,4,5}; (2) 可以只给一部分元素赋初值。 int x[5]={1,2}; 系统自动给指定值的数组元素赋值:x[0]=1,x[1]=2,其他元素值均为0。 (3) 如果一个数组的全部元素值都为0,可以写成: int x[5]={0,0,0,0,0}; 或int x[5]={0}; (4) 对全部元素赋初值时,可以不指定长度。 int x[5]={1,2,3,4,5};等价于int x[ ]={1,2,3,4,5};
三、相关知识 判断下面数组初始化的正确性 int arr[10] = {10,9,8,7,6,5,4,3,2,1,0}; //错误!越界了 //正确,后面的6个元素未初始化 //正确:元素个数为 3 //错误,到底是几个元素?
任务2 多个学生一门课成绩的排序 并按学生成绩高低进行排序。 分析 输入40位同学的数学成绩,我们在任务1中已学会,只要定义一个 任务2 多个学生一门课成绩的排序 一、问题情景 一个班40位同学参加了一次数学考试,现要输入全班同学的成绩, 并按学生成绩高低进行排序。 分析 输入40位同学的数学成绩,我们在任务1中已学会,只要定义一个 数组int math[40],然后用一个循环输入就行 ; 而对学生成绩进行排序,可以看成是: 先求最高分,然后和第一个数交换位置,即让第一个位置放最高分; 再求剩下的39个同学的最高分,然后和第二个数交换位置, ……不断重复,直到剩下的最后一个数是最小数为止。
任务2的具体实现 比较法 for(j=0;j< 9;j++) for(i=j+1;i< 10;i++) #include "stdio.h" main( ) {int i,math[10],t,j; printf(" 请输入10个同学的成绩:"); for(i=0;i<10;i++) scanf("%d",&math[i]); for(j=0;j< 9;j++) for(i=j+1;i< 10;i++) /*分离第j个数,则一定与第j+1至最后一个数比较*/ if(math[j]<math[i]) { t=math[j]; math[j]=math[i]; math[i]=t; } printf("10个同学的成绩排序为:"); printf("%3d", math[i]); printf("\n"); 比较法
输入6个数,用“冒泡法”对6个数排序(由小到大)。 冒泡法的基本思想: 通过相邻两个数之间的比较和交换, 使排序码(数值)较小的数逐渐从底部移向顶部, 排序码较大的数逐渐从顶部移向底部。 就像水底的气泡一样逐渐向上冒,故而得名。
第1趟比较(下图1 ) 第2趟比较(下图2)
第1趟,两两比较5次,剩5个数未排好序; 第2趟,两两比较4次,剩4个数未排好序; 第3趟,两两比较3次,剩3个数未排好序; 第4趟,两两比较2次,剩2个数未排好序; 第5趟,两两比较1次,全部排好序; 算法结论:对于n个数的排序,需进行n-1趟比较, 第j趟比较需进行n-j次两两比较。
任务2的具体实现 冒泡法 #include "stdio.h" main( ) {int i,math[10],t,j; printf(" 请输入10个同学的成绩:"); for(i=0;i< 10;i++) scanf("%d",&math[i]); for(j=0;j<9;j++) for(i=0;i<9-j;i++) if(math[i]<math[i+1]) { t=math[i]; math[i]=math[i+1]; math[i+1]=t; } printf("10个同学的成绩排序为:"); for(i=0;i<10;i++) printf("%3d", math[i]); printf("\n"); 冒泡法
【例4-16】输入10 个数存入一维数组,然后再按逆序重新存放后输出。 分析:定义一个一维数组int a[10],用一个循环将10个数输入。然后a[0]与a[9]交换,a[1]与a[8],a[2]与a[7],a[3]与a[6],a[4]与a[5],即a[i]与a[9-i]交换(i=0到(10-1)/2),最后输出a[0]至a[9]即可。 #include "stdio.h" #define N 10 main() {int a[N],i,t; printf("输入%d个数\n",N); for(i=0;i<N;i++) scanf("%d",&a[i]); for(i=0;i<=(N-1)/2;i++) { t=a[i]; a[i]=a[N-1-i]; a[N-1-i]=t; } //交换 printf("输出逆序数\n"); printf("%3d",a[i]); printf("\n"); }
任务 3 学生姓名的输入输出 一、问题情景 本任务所要掌握的知识点是: 字符数组的输入输出 任务 3 学生姓名的输入输出 一、问题情景 一个班里有40个学生,在选举班干部时有10个候选人,现要求输出候选人名单。请用C编程解决此问题。 分析:此题的主要内容是学会姓名的输入/输出。 本任务所要掌握的知识点是: 字符数组的输入输出
三、相关知识 (一) 一维字符数组 1. 一维字符数组的定义 例如:char c[10]; 意思是定义一个字符数组c,它有10个元素。 c[0]=’I’;c[1]=’□’;c[2]=’a’;c[3]=’m’;c[4]=’□ ’; c[5]=’h’;c[6]=’a’;c[7]=’p’;c[8]=’p’;c[9]=’y。 该数组的下标从0到9 ,数组元素值如右图所示。 I □ a m h p y 2. 一维字符数组的初始化 (1)定义时逐个字符给数组中各元素。 char c[5]={‘c’,’h’,’i’,’n’,’a’}; (2)可省略数组长度。 char c[ ]={‘c’,’h’,’i’,’n’,’a’}; 系统根据初值个数确定数组的长度,数组c的长度自动为5。 (3)字符数组可以用字符串来初始化。 char c[6]=”china” char c[10]={“china”} /*加不加花括号都没关系*/ c h i n a \0 c h i n a \0
3.一维字符数组的引用 方法一:用%c格式符逐个输入输出。 例如: 方法二:用%s格式符进行字符串输 char c[6]; 入输出。例如: for(i=0;i<6;i++) {scanf(“%c”,&c[i]); printf(“%c”,c[i]);} 方法二:用%s格式符进行字符串输 入输出。例如: char c[6]; scanf(“%s”,c); printf(“%s”,c); (1)“%s”格式输入时,遇空格或回车结束,但获得的字符中不包含回车及空 格本身,而是在字符串末尾添’\0’。
【例4-7】三个同学姓名的输入输出。 程序如下: #include "stdio.h" main() {char name1[10],name2[10],name3[10]; printf("请输入姓名:\n"); scanf("%s%s%s",name1,name2,name3); printf("输出的姓名为:\n"); printf("%s,%s,%s\n",name1,name2,name3);} 程序的运行结果表明:%s输入时,空格或回车表示输入的分隔符
4.常用的字符串处理函数 (1) 输入字符串函数——gets() 格式:gets(字符数组) 例如:char s[12]; gets(s); 功能:从键盘输入1个字符串。允许输入空格。 【例4-8】将例4-7改为gets()输入: #include "stdio.h" main() {char name1[10],name2[10],name3[10]; printf("请输入姓名:\n"); gets(name1); gets(name2); gets(name3); printf("输出的姓名为:\n"); printf("%s,%s,%s\n",name1,name2,name3);} 注意: gets( )允许输入空格
(2) 输出字符串函数 格式:puts(字符数组) 如:char s[6]=”china”; puts(s); 替’\0’ 【例4-9】将例4-7改为gets()、puts()函数。 #include "stdio.h" main() {char name1[10],name2[10],name3[10]; printf("请输入姓名:\n"); gets(name1);gets(name2);gets(name3); printf("输出的姓名为:\n"); puts(name1);puts(name2);puts(name3); }
【例4-17】从键盘输入一串字符(以回车键结束),统计字符数。 分析:因为不知道会输入一串多长的字符,所以刚开始定义一个足够大的字符数组char str[80],然后从键盘输入的字符将会放在str[0]至str[k]中,而str[k+1]将存放回车。如表: 所以,从str[0]开始找,只要没找到’\0’,则继续找下一个。 \0 Str(k) …… Str(0) 程序如下: #include "stdio.h" #define N 80 main() { char str[N],i,t; printf("输入字符串\n"); gets(str); i=0; while(str[i]!='\0') i++; printf("字符数为%d",i); printf("\n"); }
任务 4 多个学生多门课成绩的排序 一、问题情景 任务 4 多个学生多门课成绩的排序 一、问题情景 一个班40个同学参加了三门课的考试,现要求输出按总成绩的高低排序的成绩单。成绩单的格式如下: 排序 姓名 课1 课2 课3 总分 平均分 1 张三 98 87 88 273 91 2 李四 96 86 88 270 90 …… 分析:本问题要解决姓名的输入/输出,这个在任务3中已解决。同时也需输入/输出40个同学三门课的成绩,并进行相应的总分及平均分的计算。最后按总分的高低进行排序。所以将这一任务分解为二个小任务。 一个是40个同学三门课成绩的输入/输出(其知识点是二维数组); 另一个是计算相应的平均分及总分并进行排序。
三、相关知识 (一) 二维数组的定义 1. 二维数组定义的一般形式 类型说明符 数组名[常量表达式][ 常量表达式] 类型说明符 数组名[常量表达式][ 常量表达式] 例如:int a[3][4] 定义了一个3×4(3行4列)的整型数组a 2. 二维数组的理解 二维数组是一种特殊的一维数组 例如 int a[3][4]; a为数组名,先看第一维,表明它是一个具有3个元素的特殊的一维数组, 三个元素分别为a[0],a[1],a[2]。 再看第二维,表明每个元素又是一个包含4个元素的一维数组, 如a[0]这个元素包含4个元素:a[0][0],a[0][1],a[0][2],a[0][3]
三、相关知识 ( 二) 二维数组的引用 二维数组元素的表示形式: 数组名[下标][下标] 例:int a[3][4], 表示行下标值最小从0开始,最大为3-1=2; 列下标值最小为0,最大为4-1=3, 即: a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a[2][0] a[2][1] a[2][2] a[2][3]
三、相关知识 (三) 二维数组的初始化 二维数组初始化的方法如下。 (1) 分行给二维数组赋初值(推荐使用) int a[3][4]={{1,2,3,4},{4,5,6,7},{6,7,8,9}}; (2) 将所有数据写在一个花括弧内,按数值排列的顺序对各元素赋初值。 int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12} (3) 可以对部分元素赋初值。 int a[3][4]={{1,2},{4},{6,7,8}}; a数组分布如图所示。 (4) 如果对全部数组元素赋值,则第一维的长度可以不指定, 但必须指定第二维的长度,全部数据写在一个大括号内。 如: int a[][3]={1,2,3,4,5,6,7,8,9,10,11,12}; 第一维长度4省略。 1 2 0 0 4 0 0 0 6 7 8 0
(四) 二维数组的应用 【例4-12】输入五个同学三门课的成绩并输出。 #include "stdio.h" #define N 5 main() {int i,j; int score [N][3]; printf("请输入五个同学三门课的成绩:\n"); for (i=0;i<N;i++) for(j=0;j<3;j++) scanf("%d",&score[i][j]); printf("输出五个同学三门课的成绩:\n"); for (i=0;i<N;i++) { printf("第%d位同学:",i+1); for(j=0;j<3;j++) printf("%5d",score[i][j]); printf("\n"); }
【例4-18】输出如下的杨辉三角形,要求一共有10行10列。 /*给每一列及主对角元素赋值*/ for(i=0;i<10;i++) {a[i][0]=1; a[i][i]=1;} /*计算其它列的值*/ for(i=2;i<10;i++) for(j=1;j<I;j++) a[i][j]=a[i-1][j-1]+a[i-1][j]; #include "stdio.h" main() {int a[10][10],i,j; /*给每一列及主对角元素赋值*/ for(i=0;i<10;i++) { a[i][0]=1; a[i][i]=1; } /*计算其它列的值*/ for(i=2;i<10;i++) f or(j=1;j<i;j++) a[i][j]=a[i-1][j-1]+a[i-1][j]; printf("杨辉三角形的图形为:\n"); for(i=0;i<10;i++) {for(j=0;j<=i;j++) printf("%5d",a[i][j]); printf("\n");} }
(二) 二维字符数组 1. 二维字符数组的定义: char str[10][8] 定义一个二维数组str,共有10行8列共80个元素。 2. 二维字符数组的初始化: (1) char s1[3][3]={{‘a’,’b’,’c’},{‘d’,’e’,’f’},{‘1’,’2’,’3’}}; 如右图所示。 (2) char s1[3][3]={“abc123”}; 3. 二维字符数组的引用: (1)输入/输出二维字符数组中第i行(假设i=2) 方法一: char name[10][12]; gets(name[2]); puts(name[2]); 方法二 char name[10][12]; scanf("%s",name[2]); printf("%s",name[2]);
注意:gets(name[2]);与scanf("%s",name[2]);输入时有些不一样 printf("%s\n",name[2]); 程序运行时输入zhang ming,则输出zhang ming scanf("%s",name[2]); printf("%s\n",name[2]);则程序运行时输入zhang ming,输出zhang
任务3的具体实现 #include "stdio.h" #include "string.h" #define N 40 main() {char name[N][12]; int i,j; printf("请输入%d个候选同学的姓名:\n",N); for(i=0;i<N;i++) gets(name[i]); printf("-------------------\n"); printf("输出%d个候选同学的姓名:\n",N); puts(name[i]); }
四、知识扩展 1、字符串比较函数 格式:strcmp(字符串1,字符串2) 其中字符串1、字符串2可以是字符串常量,也可以是一维字符数组。如: strcmp(str1,str2); strcmp(“China”,”English”); strcmp(str1,”beijing”) 功能:比较二个字符串的大小。 如果字符串1>字符串2,则函数大于0;如果字符串1=字符串2,则函数值为0;如果字符串1<字符串2,则函数值小于0。 2、拷贝字符串函数 格式:strcpy(字符数组1,字符串) 其中字符串可以是字符串常量,也可以是字符数组。 如:char c[30]; strcpy(c,”Good moning”); 功能:将“字符串”完整地复制到“字符数组1”中, 字符数组1中原有内容被覆盖。
任务4的具体实现 #include "stdio.h" #include "string.h" #define N 5 main() {int i,j; int score [N][3],t; char name[N][10],nn[10]; float sum[N]={0},avg[N]; printf("请输入五个同学三门课的成绩:\n"); for (i=0;i<N;i++) { printf("第%d个同学的记录:",i+1); scanf("%s",name[i]); for(j=0;j<3;j++) scanf("%d",&score[i][j]); } for(i=0;i<N;i++) sum[i]=sum[i]+score[i][j]; avg[i]=sum[i]/3.0;
任务4的具体实现 /*排序成绩*/ for(i=0;i<N-1;i++) for(j=0;j<N-1-i;j++) if(sum[j]<sum[j+1]) { t=sum[j];sum[j]=sum[j+1]; sum[j+1]=t; t=avg[j];avg[j]=avg[j+1];avg[j+1]=t; t=score[j][0];score[j][0]=score[j+1][0];score[j+1][0]=t; t=score[j][1];score[j][1]=score[j+1][1];score[j+1][1]=t; t=score[j][2];score[j][2]=score[j+1][2];score[j+1][2]=t; strcpy(nn,name[j]); strcpy(name[j],name[j+1]); strcpy(name[j+1],nn); }
任务 4 多个学生多门课成绩的排序 printf("----------------------------------------------------\n"); printf("输出排序后五个同学三门课的成绩:\n"); printf("----------------------------------------------------\n"); printf("排序\t姓名\t课1\t课2\t课3\t总分\t平均分\n"); for (i=0;i<N;i++) { printf("第%d名:\t",i+1); printf("%s\t",name[i]); for(j=0;j<3;j++) printf("%d\t",score[i][j]); printf("%.0f\t%.1f\t",sum[i],avg[i]); printf("\n"); } printf("-----------------------------------------------------\n");