第八章-数组

 若有一定义语句int a[4][8];按照在内存中的存储顺序,a 数组的第 12个元素的下标是什么?

答案:a[1][3]。一般来说,数组a[x][y]中的第 i个元素所在行下标为: i/x,列下标为: i%y-1 。

如何提高程序的效率?

程序的时间效率是指运行速度,空间效率是指程序占用内存或者外存的状况。
全局效率是指站在整个系统的角度上考虑的效率,局部效率是指站在模块或函数角度上考虑的效率。
【规则1】不要一味地追求程序的效率,应当在满足正确性、可靠性、健壮性、可读性等质量因素的前提下,设法提高程序的效率。
【规则2】以提高程序的全局效率为主,提高局部效率为辅。
【规则3】在优化程序的效率时,应当先找出限制效率的“瓶颈”,不要在无关紧要之处优化。
【规则4】先优化数据结构和算法,再优化执行代码。
【规则5】有时候时间效率和空间效率可能对立,此时应当分析那个更重要,作出适当的折衷。例如多花费一些内存来提高性能。
【规则6】不要追求紧凑的代码,因为紧凑的代码并不能产生高效的机器码。

如何提高循环语句的效率?

提高循环体效率的基本办法是降低循环体的复杂性。
【建议1】在多重循环中,如果有可能,应当将最长的循环放在最内层最短的循环放在最外层,以减少CPU 跨切循环层的次数。
【建议2】如果循环体内存在逻辑判断,并且循环次数很大,宜将逻辑判断移到循环体的外面

未初始化的数组元素值是什么?

静态数组和全局数组的数组元素值会自动初始化为 0 值,而对于在函数内部声明的数组,如果数组元素未初始化,那么其元素值是随机数。

为什么数组不能复制?

虽然表达式a = b; /* a and b are arrays */看上去似乎合理,但它确实是非法的。非法的理由不是显而易见的;这需要用到 C 语言中数组和指针之间的特殊关系。把一个数组复制给另一个数组,最简单的实现方法是利用循环对数组元素逐个进行复制:for (i = 0; i < N; i++)a[i] = b[i];另一种可行的方法是使用来自<string.h>的函数 memcpy(意思是“内存复制”)。Memcpy函数是低级函数,它把字节从一个地方简单复制到另一个地方。为了把数组 b 复制给数组a,使用函数 memcpy 的格式如下:memcpy(a, b, sizeof(a));一些程序员喜欢 memcpy 函数,特别是对大型数组,因为它潜在的速度比普通循环更快。

编程实现显示用户输入的月份(不包括闰年的月份)拥有的天数。

#include <stdio.h>
#define MONTHS 12 

int main(){
	int month[MONTHS]={31,28,31,30,31,30,31,31,30,31,30,31};
	int m;//月份变量 
	scanf("%d",&m);
	
	printf("%d月有%d天",m,month[m-1]);
} 

从键盘输入某年某月(包括闰年),编程输出该年的该月拥有的天数。

/*从键盘输入某年某月(包括闰年),编程输出该年的该月拥有的天数。*/
#include <stdio.h>
#define MONTHS 12 

int main(){
	int days[2][MONTHS]={{31,28,31,30,31,30,31,31,30,31,30,31},
						{31,29,31,30,31,30,31,31,30,31,30,31}};
	int y,m;//月份变量 
	do{
		scanf("%d %d",&y,&m);
	}while(m<1||m>12);//处理非法输入 
	
	if((y%4==0&&y%100!=0)||(y%400==0))
			printf("The number of day is:%d\n",days[1][m-1]);
	else
			printf("The number of day is:%d\n",days[0][m-1]);
} 

从键盘输入某班学生某门课的成绩(已知每班人数最多不超过40人,具体人数由键盘输入),试编程计算其平均分。

/*从键盘输入某班学生某门课的成绩
(已知每班人数最多不超过40人,具体人数由键盘输入),试编程计算其平均分*/
#include <stdio.h>
#define MAXSIZE 40

int Average(int grade[],int n); 
void readGrade(int grade[],int n);

int main(){
	int grade[MAXSIZE],avg,n;
	printf("please input n:");
	scanf("%d",&n);
	
	readGrade(grade,n);//实参可以只写首地址 
	avg=Average(grade,n);
	
	printf("avg=%d",avg);
	return 0;
} 
void readGrade(int grade[],int n){//形参必须把括弧带好 
	for(int i=0;i<n;i++){
		scanf("%d",&grade[i]);
	}
}
int Average(int grade[],int n){
	int sum=0;
	for(int i=0;i<n;i++){
		sum+=grade[i];
	}
	return sum/n;
}

/*从键盘输入某班学生某门课的成绩(每班人数最多不超过40人),当输入成绩为负值时,表示输入结束,试编程计算并输出其平均分,并输出实际输入的学生人数。*/ 

/*从键盘输入某班学生某门课的成绩(每班人数最多不超过40人),当输入成
绩为负值时,表示输入结束,试编程计算并输出其平均分,并输出实际输入的学生人数。*/ 
#include <stdio.h>
#define MAXSIZE 40

int main() {
	int grade[MAXSIZE];
	int Sgrade;
	int sum=0;//对学生成绩求和 
	int count=0;//记数总人数,必须初始化 

	for(int i=0;i<MAXSIZE-1;i++){
		scanf("%d",&Sgrade);
		if(Sgrade==-1) break;//如果输入-1代表输入结束 
		grade[i]=Sgrade;
		count++;
		sum+=Sgrade; 
	}	
	printf("average=%d,count=%d\n",(sum/count),count);
}

/*从键盘输入某班学生某门课的成绩(每班人数最多不超过40人),当输入为负值时,表示输入结束,试编程计算并打印最高分*/ 

/*从键盘输入某班学生某门课的成绩(每班人数最多不超过40人),当输入为
负值时,表示输入结束,试编程计算并打印最高分*/ 
#include <stdio.h>
#define MAXSIZE 40

int Max(int grade[],int count);

int main() {
	int grade[MAXSIZE];
	int Sgrade;
	int sum=0;//对学生成绩求和 
	int count=0;//记数总人数,必须初始化 

	for(int i=0;i<MAXSIZE-1;i++){
		scanf("%d",&Sgrade);
		if(Sgrade==-1) break;//如果输入-1代表输入结束 
		grade[i]=Sgrade;
		count++;
		sum+=Sgrade; 
	}	
	int max=Max(grade,count);
	printf("average=%d,count=%d,max=%d\n",(sum/count),count,max);
}
int Max(int grade[],int count){
	int max=grade[0];
	for(int i=1;i<count;i++){
		if(grade[i]>max){
			max=grade[i];
		}
	}
	return max;
}

例8.8 从键盘输入某班学生某门课的成绩(每班人数最多不超过40人),当输入为负值时,表示输入结束,试编程将分数按从高到低顺序进行排序输出。用函数编程实现排序功能。

交换法

 (Exchange Sort )借鉴了求最大、最小值的思想。以降序排列为例,其排序的基本过程为:首先进行第一轮比较,参与比较的数有 n 个,将第一个数分别与后面所有的数进行比较,若后面的数较大,则交换后面这个数和第一个数的位置;这一轮比较结束以后就求出了一个最大的数放在了第一个数的位置。然后进入第二轮比较,参与比较的数变为n-1个,在这 n-1个数中再按上述方法求出一个最大的数放在第二个数的位置。然后进入第三轮比较,……,依此类推,直到第 n-1 轮比较,参与比较的数变为 2 个,求出一个最大的数放在第n-1个数的位置,剩下的最后一个数自然就为最小的数,放在数列的最后。

/*从键盘输入某班学生某门课的成绩(每班人数最多不超过40人),当输入为
负值时,表示输入结束,试编程将分数按从高到低顺序进行排序输出。用函数编程实现排序功能。*/ 
#include <stdio.h>
#define MAXSIZE 40

int Sort(int grade[],int count);

int main() {
	int grade[MAXSIZE];
	int Sgrade;
	int count=0;//记数总人数,必须初始化 

	for(int i=0;i<MAXSIZE-1;i++){
		scanf("%d",&Sgrade);
		if(Sgrade==-1) break;//如果输入-1代表输入结束 
		grade[i]=Sgrade;//给数组赋值 
		count++;
	}	
	Sort(grade,count);
}
//交换法排序 ,每轮找一个最大的放好 
int Sort(int grade[],int count){

	int i,j;
	for(i=0;i<count;i++){
		for(j=i+1;j<count;j++){
			if(grade[i]<grade[j]){
				int temp;
				temp=grade[i];
				grade[i]=grade[j];
				grade[j]=temp;
			}
		}
	} 
	
	for(int i=0;i<count;i++){//打印排序后的数组 
		printf("%d ",grade[i]);
	}	
}

选择法:交换法是每次找到比他大或小的就交换,选择法是找到最值再交换

(Selection Sort ),是指在每一轮比较中,从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最前面,直到全部待排序的数据元素排完。

/*从键盘输入某班学生某门课的成绩(每班人数最多不超过40人),当输入为
负值时,表示输入结束,试编程将分数按从高到低顺序进行排序输出。用函数编程实现排序功能。*/ 
#include <stdio.h>
#define MAXSIZE 40

int Sort(int grade[],int count);

int main() {
	int grade[MAXSIZE];
	int Sgrade;
	int count=0;//记数总人数,必须初始化 

	for(int i=0;i<MAXSIZE-1;i++){
		scanf("%d",&Sgrade);
		if(Sgrade==-1) break;//如果输入-1代表输入结束 
		grade[i]=Sgrade;//给数组赋值 
		count++;
	}	
	Sort(grade,count);
}
//选择法排序 ,找到大的就交换 
int Sort(int grade[],int count){

	int i,j,k,temp;
	for(i=0;i<count;i++){		
		for(j=i+1;j<count;j++){
			k=i;//每次循环再次开始时使k=i 
			if(grade[j]>grade[k]){
				k=j;//用k保存最大值下标 
			}
		if(k!=i){//只要不相等了就交换,然后还要往后循环看有没有更大的来交换
			temp=grade[k];
			grade[k]=grade[i];
			grade[i]=temp;
			} 
		}
	} 
	
	for(int i=0;i<count;i++){//打印排序后的数组 
		printf("%d ",grade[i]);
	}	
}

 在例 8.8 程序基础上,要求输入学生成绩的同时输入学生的学号,并且将学生的学号随分数排序结果一同输出,即要得到下面的运行结果,则应该如何修改程序?

/*在例 8.8 程序基础上,要求输入学生成绩的同时输入学生的学号,并且将学生
的学号随分数排序结果一同输出,即要得到下面的运行结果,则应该如何修改程序?
Input student’s ID and score:070310122 84  ↙
Input student’s ID and score:070310123 83  ↙
Input student’s ID and score:070310124 88  ↙
Input student’s ID and score:070310125 87  ↙
Input student’s ID and score:070310126 61  ↙
Input student’s ID and score:-1 -1  ↙
Total students are 5
Sorted scores:
070310124 88
070310125 87
070310122 84
070310123 83
070310126 61*/ 
#include <stdio.h>
#define MAXSIZE 40

int Sort(int grade[],int snum[],int count);

int main() {
	int grade[MAXSIZE];
	int snum[MAXSIZE];
	int Sgrade;
	int Snum;
	int count=0;//记数总人数,必须初始化 

	for(int i=0;i<MAXSIZE-1;i++){
		printf("Input student’s ID and score:");
		scanf("%d %d",&Snum,&Sgrade);
		if(Sgrade==-1&&Snum==-1) break;//如果输入-1代表输入结束 
		grade[i]=Sgrade;//给数组赋值 
		snum[i]=Snum;
		count++;
	}	
	Sort(grade,snum,count);
	
}
//选择法排序 ,找到大的就交换 
int Sort(int grade[],int snum[],int count){

	int i,j,k,temp;
	for(i=0;i<count;i++){	
		for(j=i+1;j<count;j++){
			k=i;//每次循环再次开始时使k=i 
			if(grade[j]>grade[k]){
				k=j;//用k保存最大值下标 
			}
			if(k!=i){
			temp=grade[k];
			grade[k]=grade[i];
			grade[i]=temp;
			} 
		}
	} 
	
	printf("Total students are %d\n",count);
	printf("Sorted scores:\n");
	for(int i=0;i<count;i++){//打印排序后的数组 
		printf("%d %d\n",snum[i],grade[i]);
	}	
	
}

从键盘输入某班学生某门课的成绩(每班人数最多不超过40人),当输入为负值时,表示输入结束,试编程从键盘任意输入一个学号,查找该学号学生的成绩。

/*从键盘输入某班学生某门课的成绩(每班人数最多不超过40人),当输入为
负值时,表示输入结束,试编程从键盘任意输入一个学号,查找该学号学生的成绩。*/ 
#include <stdio.h>
#define MAXSIZE 40

int find(int grade[],int snum[],int count,int a);

int main() {
	int grade[MAXSIZE];
	int snum[MAXSIZE];
	int Sgrade;
	int Snum;
	int count=0;//记数总人数,必须初始化 

	for(int i=0;i<MAXSIZE-1;i++){
		printf("Input student’s ID and score:");
		scanf("%d %d",&Snum,&Sgrade);
		if(Sgrade==-1&&Snum==-1) break;//如果输入-1代表输入结束 
		grade[i]=Sgrade;//给数组赋值 
		snum[i]=Snum;
		count++;
	}	
	printf("please input student number:");
	int a;//保存用户输入的学生学号 
	int b;//保存查找函数的返回值 
	scanf("%d",&a);
	b=find(grade,snum,count,a);
	if(b==-1)  printf("Nobody here with that number");//如果没这个学号,则find函数返回-1 
	else printf("%d",grade[b]);
}
//顺序查找
int find(int grade[],int snum[],int count,int a){
	
	int i;
	
	for(i=0;i<count;i++){
		if(snum[i]==a) return i;
	}
	return -1;
}	

在例8.10的基础上,改用折半查找法实现学生成绩的查找,假设按学生的学号从小到大的顺序输入学生的成绩。

/*在例8.10的基础上,改用折半查找法实现学生成绩的查找,假设按学生的学号从小到大的顺序输入学生的成绩。*/ 
#include <stdio.h>
#define MAXSIZE 40

int find(int grade[],int snum[],int count,int a);

int main() {
	int grade[MAXSIZE];
	int snum[MAXSIZE];
	int Sgrade;
	int Snum;
	int count=0;//记数总人数,必须初始化 

	for(int i=0;i<MAXSIZE-1;i++){
		printf("Input student’s ID and score:");
		scanf("%d %d",&Snum,&Sgrade);
		if(Sgrade==-1&&Snum==-1) break;//如果输入-1代表输入结束 
		grade[i]=Sgrade;//给数组赋值 
		snum[i]=Snum;
		count++;
	}	
	printf("please input student number:");
	int a;//保存用户输入的学生学号 
	int b;//保存查找函数的返回值 
	scanf("%d",&a);
	b=find(grade,snum,count,a);
	if(b==-1)  printf("Nobody here with that number");//如果没这个学号,则find函数返回-1 
	else printf("%d",grade[b]);
}
//折半查找 
int find(int grade[],int snum[],int count,int a){
		int mid,left,right;
		left=0;
		right=count-1;
		mid=(left+right+1)/2;
			
	while(left<right){//当坐标交叉了,说明找不到 
		mid=(left+right+1)/2;
		
		if(a==snum[mid]) return mid;
		else if(a<snum[mid]){
			right=mid-1;
		}
		else if(a>snum[mid]){
			left=mid+1;
		}
	}return -1;	
}	

确定终止条件是下标交叉

/*某班期末考试科目为数学(MT)、英语(EN)和物理(PH),有最多不超过40人参加考试。请编程计算:(1)每个学生的总分和平均分;(2)每门课程的总分和平均分。*/  (关键是要想到用二维数组存学生成绩,则按行看是学生总成绩,按列看是每门课程的总成绩)

/*某班期末考试科目为数学(MT)、英语(EN)和物理(PH),有最多不超过40人参加考试。
请编程计算:(1)每个学生的总分和平均分;(2)每门课程的总分和平均分。*/ 

#include <stdio.h>
#define STUD_N 40 /* 最多学生人数 */
#define COURSE_N 3 /* 考试科目数 */
int ReadScore(int score[][COURSE_N], long num[]);
void AverforStud(int score[][COURSE_N], int sum[], float aver[], int n);
void AverforCourse(int score[][COURSE_N], int sum[], float aver[], int n);
void Print(int score[][COURSE_N], long num[], int sumS[], float averS[],int sumC[],float averC[], int n);

int main()
{
	int score[STUD_N][COURSE_N], sumS[STUD_N], sumC[STUD_N], n;
	long num[STUD_N];
	float averS[STUD_N], averC[STUD_N];
	n = ReadScore(score, num); /* 读入学生成绩 */
	AverforStud(score, sumS, averS, n); /* 计算每个学生的总分平均分 */
	AverforCourse(score, sumC, averC, n); /* 计算每门课程的总分平均分 */
	Print(score, num, sumS, averS, sumC, averC, n); /* 输出学生成绩 */
	return 0;
}
/* 函数功能:输入学生的学号及其三门课的成绩,当输入负值时,结束输入,返回学生人数 */
int ReadScore(int score[][COURSE_N], long num[])
{
	int i, j, n;
	printf("Input the total number of the students(n<40):");
	scanf("%d", &n); /* 输入参加考试的学生人数 */
	printf("Input student’s ID and score as: MT EN PH:\n");
	for (i=0; i<n; i++) /* 对所有学生进行循环 */
	{
		scanf("%ld", &num[i]); /* 以长整型格式输入每个学生的学号 */
		for (j=0; j<COURSE_N; j++) /* 对所有课程进行循环 */
		{
			scanf("%d", &score[i][j]); /* 输入每个学生的各门课成绩 */
		}
	}
	return i; /* 返回学生人数 */
}
/* 函数功能: 计算每个学生的总分和平均分 */
void AverforStud(int score[][COURSE_N], int sum[], float aver[], int n)
{
	int i, j;
	for (i=0; i<n; i++)
	{
		sum[i] = 0;
		for (j=0; j<COURSE_N; j++) /* 对所有课程进行循环 */
		{
			sum[i] = sum[i] + score[i][j]; /* 计算第i个学生的总分 */
		}
		aver[i] = (float)sum[i] / COURSE_N;/* 计算第i个学生的平均分 */
	}
}
/* 函数功能:计算每门课程的总分和平均分 */
void AverforCourse(int score[][COURSE_N], int sum[], float aver[], int n)
{
	int i, j;
	for (j=0; j<COURSE_N; j++)
	{
		sum[j] = 0;
		for (i=0; i<n; i++) /* 对所有学生进行循环 */
		{
			sum[j] = sum[j] + score[i][j]; /* 计算第 j门课程的总分 */
		}
		aver[j] = (float)sum[j] / n; /* 计算第 j门课程的平均分 */
	}
}
/*函数功能:打印每个学生的学号、各门课成绩、总分和平均分,以及每门课的总分和平均分*/
void Print(int score[][COURSE_N], long num[], int sumS[], float averS[],int sumC[], float averC[], int n)
{
	int i, j;
	
	printf("Counting Result:\n");
	printf("Student’s ID\t MT \t EN \t PH \t SUM \t AVER\n");
	
	for (i=0; i<n; i++)
	{
		printf("%12ld\t",num[i]); /* 以长整型格式打印学生的学号 */
		for (j=0; j<COURSE_N; j++)
		{
		printf("%4d\t", score[i][j]); /* 打印学生的每门课成绩 */
		}
		printf("%4d\t%5.1f\n", sumS[i], averS[i]);/*打印学生的总分平均分*/
	}
	printf("SumofCourse \t");
	for (j=0; j<COURSE_N; j++) /* 打印每门课的总分 */
	{
		printf("%4d\t", sumC[j]);
	}
	printf("\nAverofCourse\t");
	for (j=0; j<COURSE_N; j++) /* 打印每门课的平均分 */
	{
		printf("%4.1f\t", averC[j]);
	}
	printf("\n");
}

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值