若有一定义语句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");
}