C Primer Plus_第10章_数组和指针_编程练习

时间:2024-07-10 18:03:44

1.

/*rain.c 针对若干年的降水量数据,计算年降水总量、年降水平均量,以及月降水平均量*/
#include <stdio.h>
#define MONTHS 12
#define YEARS 5 int main (void)
{
//把数组初始化为2000到2004年的降水量数据
const float rain[YEARS][MONTHS] = //const声明和初始化数组可保护数据
{
{4.3, 4.3, 4.3, 3.0, 2.0, 1.2, 0.2, 0.2, 0.4, 2.4, 3.5, 6.6},
{8.5, 8.2, 1.2, 1.6, 2.4, 0.0, 5.2, 0.9, 0.3, 0.9, 1.4, 7.3},
{9.1, 8.5, 6.7, 4.3, 2.1, 0.8, 0.2, 0.2, 1.1, 2.3, 6.1, 8.4},
{7.2, 9.9, 8.4, 3.3, 1.2, 0.8, 0.4, 0.0, 0.6, 1.7, 4.3, 6.2},
{7.6, 5.6, 3.8, 2.8, 3.8, 0.2, 0.0, 0.0, 0.0, 1.3, 2.6, 5.2}
};
int years,months;
float totyear, totmonth; printf("YEAR RAIN:\n");
for(years=; years<YEARS; years++)
{
for(months=,totyear=; months<MONTHS; months++)
totyear += *(*(rain+years)+months);  //此处应题目要求使用指针形式,同样可以用数组形式
printf("%4d %4.2f\n",+years,totyear);
} printf("\nmonth average:\n");
printf("JUN FEB MAT APR MAY JUN JLY AUG SPT OCT NOV DEC:\n");
for(months=; months<MONTHS; months++)
{
for(years=,totmonth=; years<YEARS; years++)
totmonth += *(*(rain+years)+months);  //可用数组形式
printf("%-4.1f ",totmonth/);
}
printf("\nDone!\n"); return ;
}

2.

/*一维数组函数调用*/
#include <stdio.h>
void copy_arr (double [], double [], int);
void copy_ptr (double *, double *, int); int main (void)
{
double source[] = {1.1, 2.2, 3.3, 4.4, 5.5};
double target1[] = {}; //初始化一个元素全为0的数组可以这样赋值
double target2[] = {}; printf ("Before operation:\n");
printf ("source: \t%g\t%g\t%g\t%g\t%g\n",
source[], source[], source[], source[], source[]);
printf ("target1: \t%g\t%g\t%g\t%g\t%g\n",
target1[], target1[], target1[], target1[], target1[]);
printf ("target2: \t%g\t%g\t%g\t%g\t%g\n",
target2[], target2[], target2[], target2[], target2[]); copy_arr (source, target1, );
copy_ptr (source, target2, ); printf ("\n\nAfter operation:\n");
printf ("source: \t%g\t%g\t%g\t%g\t%g\n",
source[], source[], source[], source[], source[]);
printf ("target1: \t%g\t%g\t%g\t%g\t%g\n",
target1[], target1[], target1[], target1[], target1[]);
printf ("target2: \t%g\t%g\t%g\t%g\t%g\n",
target2[], target2[], target2[], target2[], target2[]); return ;
} void copy_arr (double a1[], double a2[], int n)
{
int i;
for (i = ; i < n; i++)
a2[i] = a1[i];  //简单的赋值就可以实现复制数组
} void copy_ptr (double *p1, double *p2, int n)
{
int i;
for (i = ; i < n; i++)
*(p2 + i) = *(p1 + i);  //同样,赋值即可实现复制数组
} /*******************************************PS: 有关%g输出的补充说明************************************************/
//1.%g用于打印浮点型数据时,会去掉多余的零,至多保留六位有效数字(不同于%e的默认保留小数点后6位)
//2.当%g用于打印超过6位的浮点型数据时,因为精度问题,%f不得不输出一个不精确的超过六位的数字,
// %e也是同样,而%g此时会选择%e格式进行输出,并且按第一条要求,去掉多余的零,并且四舍五入到6位数字。
//3.当一个数字的绝对值很小的时候,要表示这个数字所需要的字符数目就会多到让人难以接受。
// 例如,把π*10^-10写作0.00000000000314159就会显得非常丑陋不雅,反之,如果我们写作3.14159e-10,就不但简洁而且易读好懂。
// 当指数是-4时,这两种表现形式大小相同。对于比较小的数值,除非该数的指数小于或者等于-5,%g才会采用科学计数(%e的格式)进行输出。

3.

/* 找出一个int数组中的最大数 */
#include <stdio.h>
int max (int[], int); int main (void)
{
int array[] = {, , , , , };
printf("%d\n",sizeof(array)/sizeof(int));
printf ("The max is: %d\n", max (array, sizeof(array)/sizeof(int))); return ;
} int max (int a[], int n)
{
int i, max;
  //for (i = 0, max = a[0]; i < (sizeof(a)/sizeof(int)); i++)//sizeof(a)不能反应sizeof(array)的大小,所以处理数组的函数应该包括一个数组大小的参数
for (i=,max=a[]; i<n; i++) //n反应出sizeof(array)的大小
max = (max>a[i]) ? max : a[i]; return max;
}

4.

#include <stdio.h>
int MaxIndex (double * ptr, int n); int main (void)
{
double array[] = {4.3, 5.3, 2.6, 9.2, 2.8, 3.6};
printf ("The max number's index is: %d\n", MaxIndex(array, sizeof(array)/sizeof(double))); return ;
} int MaxIndex (double a[], int n)
{
int i;
double max;
for (i=,max=a[]; i<n; i++)
max = (max>a[i]) ? max : a[i];
for (i=; max!=a[i]; i++)
continue;
return i;
}

5.

/*求数组中最大值最小值间的差值*/
#include <stdio.h>
double gap (double *, int); int main (void)
{
double array[] = {4.3, 5.3, 2.6, 9.2, 2.8, 3.6};
printf ("The gap between max and min is: %g\n", gap (array, sizeof(array)/sizeof(double))); return ;
} double gap (double a[], int n)
{
int i;
double max, min;
for (i = , max = a[], min = a[]; i < n; i++)
{
if (max < a[i]) max = a[i];
if (min > a[i]) min = a[i];
}
return (max - min);
}

6.

/*复制二维数组*/
#include <stdio.h>
#define ROWS 2
#define COLS 3
void copy_2d (double source[][COLS], double target[][COLS], int); //复制二维数组,注意声明处理二维数组的函数时要给出子数组大小信息
void copy_1d (double a1[], double a2[], int n); //复制一维数组 int main (void)
{
int i, j;
double source[ROWS][COLS] = {{, , }, {, , }};
double target[ROWS][COLS] = {}; copy_2d (source, target, ROWS);
for (i=; i<ROWS; i++)
{
for (j = ; j < COLS; j++)
printf ("%g\t", target[i][j]);
printf ("\n");
}
return ;
} void copy_2d (double (*source)[COLS], double target[][COLS], int n)
{
int i;
for (i = ; i < n; i++)
copy_1d ( *(source + i), target[i], COLS); //*(source + i), target[i]都是double(* )[3]型
} void copy_1d (double a1[], double *a2, int n)
{
int i;
for (i = ; i < n; i++)
a2[i] = a1[i];
}

7.

/*一维数组函数调用,复制数组中某部分的元素们*/
#include <stdio.h>
void copy (double *, double *, int); int main (void)
{
double source[] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7};
double target[] = {}; printf ("Before operation:\n");
printf ("source: \t%g\t%g\t%g\t%g\t%g\t%g\t%g\n",
source[], source[], source[], source[], source[], source[], source[]);
printf ("target: \t%g\t%g\t%g\n",
target[], target[], target[]); copy (source + , target, ); //函数在这里哦,怕你看得心烦不想找 printf ("\nAfter operation:\n");
printf ("source: \t%g\t%g\t%g\t%g\t%g\t%g\t%g\n",
source[], source[], source[], source[], source[], source[], source[]);
printf ("target: \t%g\t%g\t%g\n",
target[], target[], target[]); return ;
} void copy (double *p1, double *p2, int n)
{
int i;
for (i = ; i < n; i++)
*(p2 + i) = *(p1 +i);
}

8.

#include <stdio.h>
#define COLS 5
void copy (double (*)[COLS], double (*)[COLS], int);
void display (double (*)[COLS], int); int main (void)
{
double source[][COLS] =
{
{1.1, 2.2, 3.3, 4.4, 5.5},
{6.6, 7.7, 8.8, 9.9, 10.10},
{11.11, 12.12, 13.13, 14.14, 15.15}
};
double target[][COLS] = {}; copy (source, target, ); puts ("source:");
display (source, );
puts ("\ntarget:");
display (target, ); return ;
} void copy (double (*source)[COLS], double target[][COLS], int rows) //double (*source)[COLS]等同于double source[][COLS]
{
int i, j;
for (i = ; i < rows; i++)
{
for (j = ; j < COLS; j++)
target[i][j] = source[i][j];
}
} void display (double (*p)[COLS], int rows)
{
int i,j; for (i = ; i < rows; i++)
{
for (j = ; j < COLS; j++)
printf ("%g\t", p[i][j]);
printf ("\n");
} }

突然发现自己写的程序自己都不愿意去读,因为全是代码没有模块化的注释,仅仅偶尔有个细节注释啥的,所以看起来要找,要想,这一段函数是干什么的,实现某个功能的函数在哪里等等。本来程序就是密密麻麻的东西,而且又不是汉语形式的,本身看起来就很费劲。所以还是要多写注释,尤其是模块化地去注释,最好能让人一眼看清程序的整体思路以及模块。

9.

/*两数组对应元素相加放在第三个数组中*/
#include <stdio.h>
void add (double [], double *, double [], int n); int main (void)
{
/**************声明和初始化两个源数组和一个目标数组*****************/
double source1[] = {1.1, 2.2, 3.3, 4.4, 5.5};
double source2[] = {6.6, 7.7, 8.8, 9.9, 10.10};
double target[] = {}; /**************执行两个源数组相加并且赋值给目标数组*****************/
add (source1, source2, target, sizeof(source1)/sizeof(double)); /**************显示两个源数组和目标数组*****************/
printf ("source1: \t%g\t%g\t%g\t%g\t%g\n",source1[],source1[],source1[],source1[],source1[]);
printf ("source2: \t%g\t%g\t%g\t%g\t%g\n",source2[],source2[],source2[],source2[],source2[]);
printf ("target: \t%g\t%g\t%g\t%g\t%g\n",target[],target[],target[],target[],target[]); return ;
} /**************定义函数:两个源数组相加并且赋值给目标数组*****************/
void add (double source1[], double source2[], double target[], int n)
{
int i;
for (i = ; i < n; i++)
target[i] = source1[i] + source2[i];
}

这样就清楚些了吧。其实写出来牛逼的代码确实牛逼,但是做好注释方便维护则是素养!

10.

打算用指针的形式,不能老用数组,正好可以加强一下对指针的认识。

/*二维数组元素翻一番*/
#include <stdio.h>
#define ROWS 3
#define COLS 5
void twice (double (*)[COLS], int);
void display (double (*)[COLS], int); int main (void)
{
/*******************声明和初始化二维源数组********************/
double array[ROWS][COLS] =
{
{1.1, 2.2, 3.3, 4.4, 5.5},
{6.6, 7.7, 8.8, 9.9, 10.10},
{11.11, 12.12, 13.13, 14.14, 15.15}
}; /*******************显示源数组,对源数组执行翻倍,显示翻倍后的数组********************/
puts ("before: \n");
display (array, );
twice (array, );
puts ("\nafter:\n");
display (array, ); return ;
} /*******************定义函数:翻倍源数组********************/
void twice (double (*p)[COLS], int rows)
{
int i, j;
for (i = ; i < rows; i++)
{
for (j = ; j < COLS; j++)
*(*(p+i)+j) = *(*(*(p+i)+j));
}
} /*******************定义函数:显示二维数组********************/
void display (double (*p)[COLS], int rows)
{
int i, j;
for (i = ; i < rows; i++)
{
for (j = ; j < COLS; j++)
printf ("%g\t", p[i][j]);
printf ("\n");
}
}

11.

/*rain.c 针对若干年的降水量数据,计算年降水总量、年降水平均量,以及月降水平均量*/
#include <stdio.h>
#define MONTHS 12
#define YEARS 5
void RainPerYear(const float (*)[]); //注意使用const定义形参(因为实参都用const定义了,更别说形参了)
void RainAveMon(const float (*)[]); int main (void)
{
/***********把数组初始化为2000到2004年的降水量数据****************/
const float rain[YEARS][MONTHS] = //const声明和初始化数组可保护数据
{
{4.3, 4.3, 4.3, 3.0, 2.0, 1.2, 0.2, 0.2, 0.4, 2.4, 3.5, 6.6},
{8.5, 8.2, 1.2, 1.6, 2.4, 0.0, 5.2, 0.9, 0.3, 0.9, 1.4, 7.3},
{9.1, 8.5, 6.7, 4.3, 2.1, 0.8, 0.2, 0.2, 1.1, 2.3, 6.1, 8.4},
{7.2, 9.9, 8.4, 3.3, 1.2, 0.8, 0.4, 0.0, 0.6, 1.7, 4.3, 6.2},
{7.6, 5.6, 3.8, 2.8, 3.8, 0.2, 0.0, 0.0, 0.0, 1.3, 2.6, 5.2}
}; /************计算和显示年总降水量*****************/
RainPerYear(rain);
/***********计算和显示月平均降水量****************/
RainAveMon(rain); return ;
} /************定义函数:计算和显示年总降水量*****************/
void RainPerYear(const float (*rain)[])
{
int years,months;
float totyear; printf("YEAR RAIN:\n");
for(years=; years<YEARS; years++)
{
for(months=,totyear=; months<MONTHS; months++)
totyear += *(*(rain+years)+months);
printf("%4d %4.2f\n",+years,totyear);
}
} /***********定义函数:计算和显示月平均降水量****************/
void RainAveMon(const float (*rain)[])
{
int years,months;
float totmonth; printf("\nmonth average:\n");
printf("JUN FEB MAT APR MAY JUN JLY AUG SPT OCT NOV DEC:\n");
for(months=; months<MONTHS; months++)
{
for(years=,totmonth=; years<YEARS; years++)
totmonth += *(*(rain+years)+months);
printf("%-4.1f ",totmonth/);
}
printf("\nDone!\n");
}

12.

/*键盘输入储存3*5数组数据,计算平均,找最值,显示*/
#include <stdio.h>
#define COLS 5
void store (double p[][COLS], int row);
double average_row (double p[], int n);
double average_total (double p[][COLS], int row);
double max(double p[][COLS], int row);
//void display (double p[][COLS], int rows, double average0, double average1, double average2, double average_total, double max); int main (void)
{
int i;
double array[][COLS];
double ave_row[];
double ave_tot;
double max_tot; /**********************读入array的3个数集,每个数集5个数据***********************/
store (array, ); /****************************计算每个数集的平均值********************************/
for(i=; i<; i++)
ave_row[i] = average_row (array[],); /****************************计算整个数集的平均值********************************/
ave_tot = average_total(array, ); /****************************找出整个数集的最大值********************************/
max_tot = max (array, ); /**********************************输出结果**************************************/
printf("ave_row[0],ave_row[1],ave_row[2] are: %g %g %g\n",ave_row[],ave_row[],ave_row[]);
printf("ave_total is %g:\n", ave_tot);
printf("max is %g:\n", max_tot);
printf("Done!\n"); return ;
} /**********************定义函数:读入array的3个数集,每个数集5个数据***********************/
void store (double p[][COLS], int row)
{
int i, j;
printf ("Please enter 15 double numbers:\n");
for (i = ; i < row; i++)
{
for (j = ; j < COLS; j++)
scanf ("%lf", *(p+i)+j); // *(p+i)+j等同于&p[i][j]
}
puts ("Now you have finished.\n");
} /****************************定义函数:计算每个数集的平均值********************************/
double average_row (double p[], int n)
{
int i;
double sum;
for (i=,sum=; i<n; i++)
sum += p[i]; return sum/n;
} /****************************定义函数:计算整个数集的平均值********************************/
double average_total(double p[][COLS], int row)
{
int i,j;
double total=;
for(i=; i<row; i++)
{
for(j=; j<COLS; j++)
total += p[i][j];
} return total/row/COLS;
} /****************************定义函数:找出整个数集的最大值********************************/
double max(double p[][COLS], int row)
{
int i,j;
double m=p[][]; for(i=; i<row; i++)
for(j=; j<COLS; j++)
m = (m>p[i][j]) ? m : p[i][j]; return m;
}

终于搞定,不难,就是有点烦,嘿嘿