第十章编程练习
首先,第一个问题要我们去修改程序清单10.7,将数组表示法改为指针表示法。用数组表示时,计算的那一行代码如下:
subtot += rain[year][month];
下面我们分析一下如何使用指针去替换掉它,首先rain即为指针指向数组的位置,也就是首元素的位置,也就是rain【0】的位置,而rain【0】是一个指针指向二维数组的首元素的位置,也就是rain【0】【0】的位置,根据这样来说,我们可以用(rain+year)来表示一维的位置,也就是数组中的数组的位置,解引用取值得到二维的首地址,也就是说*(rain + year)与rain【year】等价,然后在* (rain + year) 的基础上加month,就得到了二维数组的位置,然后解引用去得到这个位置上的值,也就是说\*(*(rain + year)+ month)与rain[year][month]等价,也就是说上面的哪一行代码可以替换成下面的指针表示:
subtot += *(*(rain + year) + month);
所以,完整的代码以及运行结果如下:
#include <stdio.h>
#define MONTHS 12 // 一年的月份数
#define YRS 5 // 年数
int main(void){
// 用2010-2014年的降水量数据初始化数组
const float rain[YRS][MONTHS] = {
{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 year, month;
float subtot, total;
printf(" YEAR RAINFALL (inches)\n");
for (year = 0, total = 0; year < YRS; year++){
//每一年,各月的降水量总和
for (month = 0, subtot = 0; month < MONTHS; month++)
subtot += *(*(rain + year) + month);
printf("%5d %15.1f\n", 2010 + year, subtot);
total += subtot; //五年的总降水量
}
printf("\nThe yearly average is %.1f inches.\n\n", total/YRS);
printf("MONTHLY AVERAGES:\n\n");
printf(" Jan Feb Mar Apr May Jun Jul Aug Sep Oct ");
printf(" Nov Dec\n");
for (month = 0; month < MONTHS; month++){
//每个月,五年的总降水量
for (year = 0, subtot =0; year < YRS; year++)
subtot += *(*(rain + year) + month);
printf("%4.1f ", subtot/YRS);
}
printf("\n");
return 0;
}
接下来,我们来看第二题,要求使用三种形参的函数去复制一个数组,首先,我们先看一下第一个,数组表示法去作为形参的函数
void copy_arr(double target[], const double source[], int x){
int i;
for ( i = 0; i < x; i++){
target[i] = source[i];
}
printf("数组表示法拷贝target1[]如下:\n");
for (int j = 0; j < x; j++){
printf("%.3lf ",target[j]);
}
}
这个看起来还是很明朗的,通过循环将原数组的数值赋值到目标数组上,接着,我们看第二个,指针表示法以及指针递增
void copy_ptr(double * target, const double * source, int x){
int i;
for ( i = 0; i < x; i++){
*(target+i) = *(source+i);
}
printf("指针表示法拷贝target2[]如下:\n");
for (int j = 0; j < x; j++){
printf("%.3lf ",target[j]);
}
}
将数组首元素地址作为形参传递进函数,通过循环,以此将目标数组的地址上的值赋值为指定原数组地址上的值。这里也可以用另一种形式去赋值
*target = *source;
target++;
source++;
如果使用第二种方式赋值的话,最好要将目标数组的首地址先保存一下,方便后续回显,因为自增会改变target指针指向的位置,而第一种方式不会改变这个位置。同样的,我们看一下第三种形参的函数
void copy_ptrs(double * target, const double * source, const double * end){
double * p = target;
while (source != end){
*target = *source;
target++;
source++;
}
printf("指针表示法拷贝target3[]如下:\n");
for (int i = 0; i < SIZE; i++){
printf("%.3lf ",p[i]);
}
}
就是看一下校验条件,是不是到了数组后面的一位,最后,我们将上面的合并起来,就得到了最终的完整代码。第二题的完整代码以及运行结果如下:
#include<stdio.h>
#define SIZE 5
void copy_arr(double target[], const double source[], int x);
void copy_ptr(double * target, const double * source, int x);
void copy_ptrs(double * target, const double * source, const double * end);
int main(void){
double source[5] = {1.1, 2.2, 3.3, 4.4, 5.5};
double target1[5];
double target2[5];
double target3[5];
printf("内容复制开始:\n");
copy_arr(target1,source,SIZE);
printf("\n");
copy_ptr(target2,source,SIZE);
printf("\n");
copy_ptrs(target3,source,source+5);
printf("\n");
printf("复制完成!\n");
printf("原数组source[]如下:\n");
for (int i = 0; i < SIZE; i++){
printf("%.3lf ",source[i]);
}
getchar();
return 0;
}
void copy_arr(double target[], const double source[], int x){
int i;
for ( i = 0; i < x; i++){
target[i] = source[i];
}
printf("数组表示法拷贝target1[]如下:\n");
for (int j = 0; j < x; j++){
printf("%.3lf ",target[j]);
}
}
void copy_ptr(double * target, const double * source, int x){
int i;
for ( i = 0; i < x; i++){
*(target+i) = *(source+i);
}
printf("指针表示法拷贝target2[]如下:\n");
for (int j = 0; j < x; j++){
printf("%.3lf ",target[j]);
}
}
void copy_ptrs(double * target, const double * source, const double * end){
double * p = target;
while (source != end){
*target = *source;
target++;
source++;
}
printf("指针表示法拷贝target3[]如下:\n");
for (int i = 0; i < SIZE; i++){
printf("%.3lf ",p[i]);
}
}
好的,接下来,我们来分析一下第三个题。编写一个比较大小的函数,返回存储在int类型数组中的最大值,首先,比较大小的话,就从数组下标为0开始以此与下一个值作比较,然后搞一个变量存储下标,将两者之间的较大值存到这个变量上面,最后输出这个下标的数组数据即可。他在这没有要求数组元素是初始化定义,还是从键盘输入,所以两者均可。上面说的两种数组数据获取方式,都做一下例子,完整代码以及运行结果如下:
#include<stdio.h>
#define SIZE 6
void bijiao(int * a);
int main(void){
int arr[SIZE] = {1, 2, 3, 4, 5, 1};//初始化定义数据
int ac[SIZE];
printf("请输入六个整数值:\n");
for (int i = 0; i < SIZE; i++){
scanf("%d",&ac[i]);
}
bijiao(arr);
bijiao(ac);
printf("Done!!");
getchar();
return 0;
}
void bijiao(int * a){
int r = 0;
for (int i = 0; i < SIZE; i++){
if (*(a+r)<=*(a+i)){
r = i;
}else{
r = r;
}
}
printf("该数组中最大的值为:%d\n",*(a+r));
}
接着,来看一下第四题,返回double类型数组中最大值的数组下标,把上面第三题的代码修改一下即可实现,下面是完整代码以及运行结果:
#include<stdio.h>
#define SIZE 6
void bijiao(double * a);
int main(void){
double arr[SIZE] = {1, 2, 3, 4, 5, 1};//初始化定义数据
double ac[SIZE];
printf("请输入六个数值:\n");
for (int i = 0; i < SIZE; i++){
scanf("%lf",&ac[i]);
}
bijiao(arr);
bijiao(ac);
printf("Done!!");
getchar();
return 0;
}
void bijiao(double * a){
int r = 0;
for (int i = 0; i < SIZE; i++){
if (*(a+r)<=*(a+i)){
r = i;
}else{
r = r;
}
}
printf("该数组中最大的值的数组下标为:%d\n",r);
}
接着,来看一下第五题,要求返回double类型数组中的最大值与最小值的差值,我们再在前几个问题的基础上对其进行修改即可实现这个功能。完整代码以及运行结果如下:
#include<stdio.h>
#define SIZE 6
void bijiao(double * a);
int main(void){
double arr[SIZE] = {1, 2, 3, 4, 5, 1};//初始化定义数据
double ac[SIZE];
printf("请输入六个数值:\n");
for (int i = 0; i < SIZE; i++){
scanf("%lf",&ac[i]);
}
bijiao(arr);
bijiao(ac);
printf("Done!!");
getchar();
return 0;
}
void bijiao(double * a){
int min = 0;//获取最小值数组下标
int max = 0;//获取最大值数组下标
for (int i = 0; i < SIZE; i++){
if (*(a+max)<=*(a+i)){
max = i;
}else{
max = max;
}
if (*(a+min)>=*(a+i)){
min = i;
}else{
min = min;
}
}
printf("该数组中最大的值为:%lf\n",*(a+max));
printf("该数组中最小的值为:%lf\n",*(a+min));
printf("两者的差值为:%lf\n",*(a+max)-*(a+min));
}
ok,接下来来看第六题,将数组中的数据进行倒序排列,循环依次比较相近的两个值,然后去交换位置即可,理论可行,我们看一下实践
#include<stdio.h>
#define SIZE 6
void bijiao(double * a);
int main(void){
double arr[SIZE] = {1, 2, 3, 4, 5, 1};//初始化定义数据
double ac[SIZE];
printf("请输入六个数值:\n");
for (int i = 0; i < SIZE; i++){
scanf("%lf",&ac[i]);
}
bijiao(ac);
printf("Done!!");
getchar();
return 0;
}
void bijiao(double * a){
double z = 0;
for (int i = 0; i < SIZE; i++){
for (int j = 0; j < SIZE; j++){
if (*(a+j)<*(a+j+1)){
z = *(a+j);
*(a+j) = *(a+j+1);
*(a+j+1) = z;
}
}
}
printf("倒序操作之后的数组元素为:\n");
for (int i = 0; i < SIZE; i++){
printf("%.3lf ",*(a+i));
}
printf("\n");
}
接下来,我们来看第七题,拷贝二维数组的内容,我们直接用指针表示法来拷贝吧,因为使用数组表示法较为简单,然后也可以使用初始化定义数组,也可以通过键盘输入,得到的完整代码以及运行结果如下:(说明,打印拷贝数组的时候,外循环里面的换行符是后来加的,所以截图可能会不太对,因为运行之后,我看着不太舒服,又加了一个换行,不过懒得在执行一遍了)
#include<stdio.h>
#define HANG 3
#define SIZE 6
void copy_ptr(double (* target)[SIZE], const double (* source)[SIZE]);
int main(void){
//初始化定义数组
double arr[HANG][SIZE] = {{1.1, 2.2, 3.3, 4.4, 5.5, 6.6},
{1.2, 2.2, 3.2, 4.2, 5.2, 6.2},
{3.1, 3.2, 3.3, 3.4, 3.5, 3.6}
};
double ac[HANG][SIZE];
double sou[HANG][SIZE];
printf("请输入十八个数值:\n");
for (int i = 0; i < HANG; i++){
for (int j = 0; j < SIZE; j++){
scanf("%lf",&ac[i][j]);
}
}
copy_ptr(sou,ac);
printf("Done!!");
getchar();
return 0;
}
void copy_ptr(double (* target)[SIZE], const double (* source)[SIZE]){
for ( int i = 0; i < HANG; i++){
for (int j = 0; j < SIZE; j++){
*(*(target+i)+j) = *(*(source+i)+j);
}
}
printf("指针表示法拷贝sou[]如下:\n");
for ( int i = 0; i < HANG; i++){
for (int j = 0; j < SIZE; j++){
printf("%.3lf ", *(*(target+i)+j));
}
printf("\n");
}
}
好,接着我们再来看第八题,将原数组中的部分数据复制到目标数组中,还是用第二题的编程练习的函数,完整程序代码以及运行结果如下:
#include<stdio.h>
#define SIZE 7
void copy_ptr(double *target, double *source, int x);
int main(void){
double source[SIZE];
double target[3];
printf("请输入七个数据:\n");
for (int i = 0; i < SIZE; i++){
scanf("%lf",&source[i]);
}
copy_ptr(target, source+2, 3);
printf("DONE,BYE!!");
return 0;
}
void copy_ptr(double *target, double *source, int x){
int i;
for(i=0;i<x;i++){
*(target + i)=*(source + i);
}
printf("复制过来的数组元素为:\n");
for(i=0;i<x;i++){
printf("%.2lf ",*(target + i));
}
printf("\n");
}
好的,接下来来看第九题,题目要求我们写两个处理变长数组的函数,一个去复制数据,一个展示数据。我们先来看一下为变长数组复制数据的函数
void copy(int rows, int cols, double arr[rows][cols], double ar[rows][cols]){
printf("复制开始*********\n");
for (int i = 0; i < rows; i++){
for (int j = 0; j < cols; j++){
ar[i][j] = arr[i][j];
}
}
printf("复制结束*********\n");
}
接着,是为变长数组回显数据的函数
void show(int rows, int cols, double arr[rows][cols], double ar[rows][cols]){
printf("原数组数据显示:\n");
for (int i = 0; i < rows; i++){
for (int j = 0; j < cols; j++){
printf("%.3lf ",arr[i][j]);
}
printf("\n");
}
printf("目标数组数据显示:\n");
for (int i = 0; i < rows; i++){
for (int j = 0; j < cols; j++){
printf("%.3lf ",ar[i][j]);
}
printf("\n");
}
}
综上,将其组合起来,在合适的位置调用相应的函数,完整程序代码以及运行结果如下:
#include<stdio.h>
#define HANG 3
#define SIZE 5
void copy(int rows, int cols, double arr[rows][cols], double ar[rows][cols]);
void show(int rows, int cols, double arr[rows][cols], double ar[rows][cols]);
int main(void){
//初始化定义数组
double arr[HANG][SIZE] = {{1.1, 2.2, 3.3, 4.4, 5.5},
{1.2, 2.2, 3.2, 4.2, 5.2},
{3.1, 3.2, 3.3, 3.4, 3.5}
};
double sou[HANG][SIZE];
printf("复制开始之前,展示两数组数据\n");
show(HANG, SIZE, arr, sou);
copy(HANG, SIZE, arr, sou);
printf("复制完成之后,展示两数组数据\n");
show(HANG, SIZE, arr, sou);
printf("Done!!");
getchar();
return 0;
}
void copy(int rows, int cols, double arr[rows][cols], double ar[rows][cols]){
printf("复制开始*********\n");
for (int i = 0; i < rows; i++){
for (int j = 0; j < cols; j++){
ar[i][j] = arr[i][j];
}
}
printf("复制结束*********\n");
}
void show(int rows, int cols, double arr[rows][cols], double ar[rows][cols]){
printf("原数组数据显示:\n");
for (int i = 0; i < rows; i++){
for (int j = 0; j < cols; j++){
printf("%.3lf ",arr[i][j]);
}
printf("\n");
}
printf("目标数组数据显示:\n");
for (int i = 0; i < rows; i++){
for (int j = 0; j < cols; j++){
printf("%.3lf ",ar[i][j]);
}
printf("\n");
}
}
理论上,只要将宏定义的常量进行修改,便可以处理任意二维数组。接下来,我们来看一下第十题。要求是让我们将两个数组中的值计算求和,将得到的值放到另一个数组中。也不是很复杂,完整程序代码以及运行结果如下:
#include<stdio.h>
#define SIZE 6
void add(double * a1, double * a2, double * a3, int x);
void show(double * a, int x);
int main(void){
double a1[SIZE] = {1, 2, 3, 4, 5, 6};
double a2[SIZE] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6};
double a3[SIZE];
printf("第一个数组元素如下:\n");
show(a1,SIZE);
printf("第二个数组元素如下:\n");
show(a2,SIZE);
printf("计算开始***********\n");
add(a1, a2, a3, SIZE);
printf("计算结束***********\n");
printf("计算得到的数组元素如下:\n");
show(a3,SIZE);
printf("DONE,BYE!!");
return 0;
}
void add(double * a1, double * a2, double * a3, int x){
for (int i = 0; i < x; i++){
*(a3+i) = *(a1+i) + *(a2+i);
}
}
void show(double * a, int x){
printf("该数组元素如下:\n");
for (int i = 0; i < x; i++){
printf("%.3lf ", *(a+i));
}
printf("\n");
}
接着,我们来看一下第十一题。题目要求将一个数组中的数据翻倍,并且将先后的值分别展示一次,结果图相较于代码少两个换行符,因为运行之后效果格式不太好看,后加的,但是没有再运行一遍,无伤大雅。完整程序代码以及运行结果如下:
#include<stdio.h>
#define ROWS 3
#define COLS 5
void add(int (* a)[COLS], int x);
void show(int (* a)[COLS], int x);
int main(void){
int arr[ROWS][COLS] = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 6},
{11, 22, 33, 44, 55}
};
printf("数组元素如下:\n");
show(arr,ROWS);
printf("翻倍操作开始*********\n");
add(arr,ROWS);
printf("翻倍操作结束*********\n");
printf("更新之后的数组元素如下:\n");
show(arr,ROWS);
printf("DONE,BYE!!");
return 0;
}
void add(int (* a)[COLS], int x){
for (int i = 0; i < x; i++){
for (int j = 0; j < COLS; j++){
*(*(a+i)+j) = 2**(*(a+i)+j);
}
}
}
void show(int (* a)[COLS], int x){
printf("该数组元素如下:\n");
for (int i = 0; i < x; i++){
for (int j = 0; j < COLS; j++){
printf("%d ", *(*(a+i)+j));
}
printf("\n");
}
printf("\n");
}
接着,来看一下第十二题。唉,又是程序清单10.7,我们回看一下,要求将main()中的任务挪用到函数中进行实现,将内容放到函数体中,然后传递合适的参数即可实现这个要求,完整程序代码以及运行结果如下:
#include <stdio.h>
#define MONTHS 12 // 一年的月份数
#define YRS 5 // 年数
void function(const float rain[][MONTHS]);
int main(void){
// 用2010-2014年的降水量数据初始化数组
const float rain[YRS][MONTHS] = {
{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}
};
printf("计算开始**********\n");
function(rain);
printf("计算结束**********\n");
return 0;
}
void function(const float rain[][MONTHS]){
int year, month;
float subtot, total;
printf(" YEAR RAINFALL (inches)\n");
for (year = 0, total = 0; year < YRS; year++){
//每一年,各月的降水量总和
for (month = 0, subtot = 0; month < MONTHS; month++)
subtot += *(*(rain + year) + month);
printf("%5d %15.1f\n", 2010 + year, subtot);
total += subtot; //五年的总降水量
}
printf("\nThe yearly average is %.1f inches.\n\n", total/YRS);
printf("MONTHLY AVERAGES:\n\n");
printf(" Jan Feb Mar Apr May Jun Jul Aug Sep Oct ");
printf(" Nov Dec\n");
for (month = 0; month < MONTHS; month++){
//每个月,五年的总降水量
for (year = 0, subtot =0; year < YRS; year++)
subtot += *(*(rain + year) + month);
printf("%4.1f ", subtot/YRS);
}
printf("\n");
}
好的,接着来看一下第十三题
首先分析一下1都有哪些要求,一开始,让在键盘输入三组数,double类型,a要求将数据放到3乘5的数组中,b要求计算每组数据的平均值,c要求计算所有数据的平均值,d要求找到所有数据中的最大值,e要求将上面的结果都打印出来。要求每个任务都用单独的函数来处理,且如何调用这几个函数也是有要求的,任务c和d还要去将结果返回到主调函数去打印显示。
好,第一步,我们要创建一个double类型的二维数组,然后写一个获取数据,并且将数据存入到数组中的函数
void cun(double (* arr)[COLS], int x, int y){
printf("请输入数据:\n");
printf("输入数据开始***********\n");
for (int i = 0; i < x; i++){
printf("请输入第%d组数据:\n",i+1);
for (int j = 0; j < y; j++){
scanf("%lf",*(arr+i)+j);
}
}
printf("输入数据结束***********\n");
}
上面是第一版的函数代码,如果后续调试出现问题的话,我们会对其进行修正。获取到数据之后,就要看一下任务b,要求我们编写一个计算并返回一维数组平均值的函数,然后在主调函数中循环调用其三次。
printf("计算每组数据的平均值开始*******");
for (int i = 0; i < ROWS; i++){
printf("第%d组数据的平均值为:\n",i+1);
jiSuan1(*(arr+i),COLS);
}
printf("计算每组数据的平均值结束*******");
/*--------------分割线---------------------------*/
void jiSuan1(double * arr, int x){
double sum = 0;
double n;
for (int i = 0; i < x; i++){
sum = sum + *(arr+i);
}
n = sum/x;
printf("%.2lf",n);
printf("\n");
}
上面是第一版调用以及实现任务b的内容,接着,来看任务c,计算所有数据的平均值。
printf("*******计算所有数据的平均值开始*******");
c = jiSuanc(arr);
printf("所有数据的平均值为:%,2lf\n",c);
printf("*******计算所有数据的平均值结束*******");
/*------------分割线--------------------*/
double jiSuanc(double (*arr)[COLS] ){
double sum = 0;
double n;
for (int i = 0; i < ROWS; i++){
for (int j = 0; j < COLS; j++){
sum = sum + *(*(arr+i)+j);
}
}
n = sum/(ROWS*COLS);
return n;
}
第一版调用以及实现任务c的内容如上,接着来看任务d,找出所有数据中的最大值。
printf("*******计算所有数据的最大值开始*******");
d = jiSuand(arr);
printf("所有数据中的最大值为:%,2lf\n",d);
printf("*******计算所有数据的最大值结束*******");
/*------------分割线--------------------*/
double jiSuand(double (*arr)[COLS]){
double max = 0;
double n;
for (int i = 0; i < ROWS; i++){
for (int j = 0; j < COLS; j++){
if (*(*(arr+i)+j)>=max){
max = *(*(arr+i)+j);
}
}
}
n = max;
return n;
}
第一版调用以及实现任务d的内容如上,接着,我们来开始调试这个程序,调试的过程其实也很关键,因为偶尔会有一些令人哭笑不得的错误出现。将编译时出现的错误修正之后,得到第一版运行结果,输入数据,存储数据没有问题,任务a完成,计算每一组的平均值没有问题,经计算,结果是对的,任务b完成,然后,任务分隔符应该加几个换行符,接着,任务c和任务d输出的值有问题
检查发现在转换说明处写成了,应该是.。修正后,再运行一次
OK,计算后得出各个数据都没有问题,后面几个任务也实现了,这个问题就结束了。最后的程序代码如下:
#include<stdio.h>
#define ROWS 3
#define COLS 5
void cun(double (* arr)[COLS], int x, int y);
void jiSuanb(double * arr, int x);
double jiSuanc(double (*arr)[COLS] );
double jiSuand(double (*arr)[COLS]);
int main(void){
double arr[ROWS][COLS];
double c,d;
cun(arr,ROWS,COLS);
printf("*******计算每组数据的平均值开始*******\n");
for (int i = 0; i < ROWS; i++){
printf("第%d组数据的平均值为:\n",i+1);
jiSuanb(*(arr+i),COLS);
}
printf("*******计算每组数据的平均值结束*******\n");
printf("*******计算所有数据的平均值开始*******\n");
c = jiSuanc(arr);
printf("所有数据的平均值为:%.2lf\n",c);
printf("*******计算所有数据的平均值结束*******\n");
printf("*******计算所有数据的最大值开始*******\n");
d = jiSuand(arr);
printf("所有数据中的最大值为:%.2lf\n",d);
printf("*******计算所有数据的最大值结束*******\n");
printf("DONE!!!");
getchar();
return 0;
}
void cun(double (* arr)[COLS], int x, int y){
printf("请输入数据:\n");
printf("*******输入数据开始***********\n");
for (int i = 0; i < x; i++){
printf("请输入第%d组数据:\n",i+1);
for (int j = 0; j < y; j++){
scanf("%lf",*(arr+i)+j);
}
}
printf("*******输入数据结束***********\n");
}
void jiSuanb(double * arr, int x){
double sum = 0;
double n;
for (int i = 0; i < x; i++){
sum = sum + *(arr+i);
}
n = sum/x;
printf("%.2lf",n);
printf("\n");
}
double jiSuanc(double (*arr)[COLS] ){
double sum = 0;
double n;
for (int i = 0; i < ROWS; i++){
for (int j = 0; j < COLS; j++){
sum = sum + *(*(arr+i)+j);
}
}
n = sum/(ROWS*COLS);
return n;
}
double jiSuand(double (*arr)[COLS]){
double max = 0;
double n;
for (int i = 0; i < ROWS; i++){
for (int j = 0; j < COLS; j++){
if (*(*(arr+i)+j)>=max){
max = *(*(arr+i)+j);
}
}
}
n = max;
return n;
}
下面来看最后一个问题,让用变长数组作为函数形参,修改程序13。呵呵,敢问变长数组的作用到底是啥,第13题,你要是感觉数组长度不够,你直接改宏定义的维度数据修改长度不就完了,非要在函数调用的时候才说明数组的长度,也许是为了在多个c文件中仍然可以使用该函数吧。唉,将函数的形参换一下。完整程序代码以及运行结果如下:
#include<stdio.h>
#define ROWS 3
#define COLS 5
void cun(int x, int y,double arr[x][y]);
void jiSuanb(int x,double arr[x]);
double jiSuanc(int x, int y,double arr[x][y] );
double jiSuand(int x, int y,double arr[x][y]);
int main(void){
double arr[ROWS][COLS];
double c,d;
cun(ROWS,COLS,arr);
printf("*******计算每组数据的平均值开始*******\n");
for (int i = 0; i < ROWS; i++){
printf("第%d组数据的平均值为:\n",i+1);
jiSuanb(COLS,*(arr+i));
}
printf("*******计算每组数据的平均值结束*******\n");
printf("*******计算所有数据的平均值开始*******\n");
c = jiSuanc(ROWS,COLS,arr);
printf("所有数据的平均值为:%.2lf\n",c);
printf("*******计算所有数据的平均值结束*******\n");
printf("*******计算所有数据的最大值开始*******\n");
d = jiSuand(ROWS,COLS,arr);
printf("所有数据中的最大值为:%.2lf\n",d);
printf("*******计算所有数据的最大值结束*******\n");
printf("DONE!!!");
getchar();
return 0;
}
void cun(int x, int y,double arr[x][y]){
printf("请输入数据:\n");
printf("*******输入数据开始***********\n");
for (int i = 0; i < x; i++){
printf("请输入第%d组数据:\n",i+1);
for (int j = 0; j < y; j++){
scanf("%lf",*(arr+i)+j);
}
}
printf("*******输入数据结束***********\n");
}
void jiSuanb(int x,double arr[x]){
double sum = 0;
double n;
for (int i = 0; i < x; i++){
sum = sum + *(arr+i);
}
n = sum/x;
printf("%.2lf",n);
printf("\n");
}
double jiSuanc(int x, int y,double arr[x][y] ){
double sum = 0;
double n;
for (int i = 0; i < x; i++){
for (int j = 0; j < y; j++){
sum = sum + *(*(arr+i)+j);
}
}
n = sum/(x*y);
return n;
}
double jiSuand(int x, int y,double arr[x][y]){
double max = 0;
double n;
for (int i = 0; i < x; i++){
for (int j = 0; j < y; j++){
if (*(*(arr+i)+j)>=max){
max = *(*(arr+i)+j);
}
}
}
n = max;
return n;
}
最后一个问题其实就是修改了一下每个函数的形参,变长数组的意义有可能是为了函数可以适配更多的数组,如果其他的c文件去调用这一个文件的函数,也许不需要根据宏定义去设置数组长度,直接使用函数的变长数组就可以处理理论上所有的二维数组。
好,以上就是第十章所有的编程练习,怎么说呢,不愧是指针,确实比较难理解,符合我对于他之前的印象。不过相信通过积累会对指针有更深刻的认识和了解。还望诸君共勉。