第十章编程练习
这一章的练习题难度不是很大,但是要记的东西很多。最重要的是关于查找最大数和最小数的那道题,简单地算法对我这个初学者来说却是怎么都自己想不出,要去找别人的答案。
10.1
include <stdio.h>
#define MONTHS 12
#define YEARS 5
int main(void) {
const float rain[YEARS][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;
const float (*pi)[MONTHS] = rain;
printf("YEAR RAINFALL (inches)\n");
for (year = 0, total = 0; year < YEARS; ++year) {
for (month = 0, subtot = 0; month < MONTHS; ++month) subtot += *(*(pi + year) + month); //指针表示法,本题关键
printf("%5d %15.1f\n", 2010 + year, subtot);
total += subtot;
}
printf("\nThe yearly average is %.1f inches.\n\n", total / YEARS);
printf("MONTHLY AVERAGES:\n");
printf(" Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec\n");
for (month = 0; month < MONTHS; ++month) {
for (year = 0, subtot = 0; year < YEARS; ++year) subtot += *(*(pi + year) + month); //指针表示法,本题关键
printf("%4.1f ", subtot / YEARS);
}
printf("\n");
return 0;
}
10.2
#include <stdio.h>
const double source[5] = {1.1, 2.2, 3.3, 4.4, 5.5}; //本题不修改source数组得值,所以优先选择声明为const类型
void copy_arr(double [], const double [], int); //接收source数组得形参也要为const类型
void copy_ptr(double [], const double [], int);
void copy_ptrs(double [], const double [], const double *);
int main(void) {
double a[5], b[5], c[5]; //声明三个空数组
copy_arr(a, source, 5);
copy_ptr(b, source, 5);
copy_ptrs(c, source, source + 5); //最后一个实参是source数组末元素后面的那个内存地址,这个地址在C语言中是允许被存在的
return 0;
}
void copy_arr(double ai[], const double ar[], int n) { //数组表示法,可读性强,但有时编译效率不如指针表示法
for (int i = 0; i < n; ++i) {
ai[i] = ar[i];
printf("%2.2f ", ai[i]); //将打印操作内置于函数里
}
putchar('\n');
}
void copy_ptr(double ai[], const double ar[], int n) {
const double *pi = ar;
for (int i = 0; i < n; ++i, ++pi) { //这里用到题目要求的递增指针++pi
*(ai + i) = *pi;
printf("%2.2f ", ai[i]); //将打印操作内置于函数里
}
putchar('\n');
}
void copy_ptrs(double ai[], const double ar[], const double *ptr) { //const double *ptr 将迭代的终点设为数组末元素后一个地址
double *pi2 = ai;
for (const double *pi1 = ar; pi1 < ptr; ++pi1, ++pi2) {
*pi2 = *pi1;
printf("%2.2f ", *pi2); //将打印操作内置于函数里
}
}
10.3
#include <stdio.h>
int max(const int [], int);
int main(void) {
const int a[10] = {5, 6, 3., 67, 78, 65, 4, 3, 3, 3};
int n;
n = max(a, 10);
printf("%d", n);
return 0;
}
int max(const int ar[], int n) {
int i, max = ar[0];
for (i = 1; i < n; ++i) max = (max > ar[i]) ? max : ar[i]; //通过遍历来查找最大数,这是个经典的算法,但是目前还无法掌握;
return max;
}
10.4
#include <stdio.h>
int max(const double [], int);
int main(void) {
const double a[4] = {1.1, 2.2, 3.3, 4.4};
int n;
n = max(a, 4);
printf("%d", n);
return 0;
}
int max(const double ar[], int n) {
int index, i;
double max = ar[0];
for (i = 1; i < n; ++i) { //本题的算法思路:从第一个元素开始,并让它与下一个元素比大小
if (max < ar[i]) {
max = ar[i]; //如果比下一个元素小,最大值更新为下一个元素,如果比下一个元素大,则保持原样。
index = i;
}
}
return index;
}
10.5
#include <stdio.h>
const double ar[4] = {1.1, 4.4, 3.3, 2.2};
double max(const double [], int n);
double min(const double [], int n);
int main(void) {
double m, n;
m = max(ar, 4);
n = min(ar, 4);
printf("Delta is %g", m - n);
return 0;
}
double max(const double ai[], int n) {
int i;
double m = ai[0];
for (i = 1; i < n; ++i) m = (m > ai[i]) ? m : ai[i];
return m;
}
double min(const double ai[], int n) {
int i;
double m = ai[0];
for (i = 1; i < n; ++i) m = (m < ai[i]) ? m : ai[i];
return m;
}
10.6
#include <stdio.h>
void dxpx(double [], int);
int main(void) {
double ar[4] = {2.2, 4.4, 3.3, 1.1};
dxpx(ar, 4);
int i = 0;
for (i = 0; i < 4; ++i) printf("%g ", ar[i]);
return 0;
}
void dxpx(double ai[], int n) {
double temp;
int i;
for (i = 0; i < n / 2; ++i) {
temp = ai[i];
ai[i] = ai[n - i - 1];
ai[n - i - 1] = temp;
}
}
10.7
#include <stdio.h>
void copy_arr(double ai[][2], const double aar[][2], int n);
const double ar[2][2] = {{1.1, 2.2},
{3.3, 4.4}};
int main(void) {
double ai[2][2];
copy_arr(ai, ar, 2);
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 2; ++j) printf("%g ", ai[i][j]);
} //打印完成拷贝后的二维数组,看是否拷贝成功;
return 0;
}
void copy_arr(double ai[][2], const double aar[][2], int n) { //数组表示法,可读性强,但有时编译效率不如指针表示法
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) ai[i][j] = aar[i][j];
}
}
10.8
void copy_ptrs(int [], const int [], int);
const int ar[7] = {1, 2, 3, 4, 5, 6, 7};
int main(void) {
int ai[3];
int *pi = ai;
const int *ptr = ar;
copy_ptrs(pi, ptr, 3); //实参是地址和待处理元素个数,而非数组名和数组大小。
for (int i = 0; i < 3; ++i) printf("%d ", *(ai + i));
return 0;
}
void copy_ptrs(int *pi, const int *ptr, int n) { //const double *ptr 将迭代的终点设为数组末元素后一个地址
for (int i = 0; i < n; ++i) {
*(pi + i) = *(ptr + 2 + i); //ar+2表示为ar数组得第三个元素开始,i<n为在哪个元素结束loop;
}
}
10.9
#include <stdio.h>
double a[3][5] = {{1.1, 2.2, 3.3, 4.4, 5.5},
{1.1, 2.2, 3.3, 4.4, 5.5},
{1.1, 2.2, 3.3, 4.4, 5.5}};
void copy_arr(int n, int m, double ai[n][m], double ar[n][m]); //变长数组的声明规则
void show_arr(int n, int m, double ai[n][m]);
int main(void) {
double b[3][5];
copy_arr(3, 5, b, a);
printf("List a is :\n");
show_arr(3, 5, a);
printf("\nList b is :\n");
show_arr(3, 5, b);
return 0;
}
void copy_arr(int n, int m, double ai[n][m], double ar[n][m]) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
ai[i][j] = ar[i][j];
}
}
return;
}
void show_arr(int n, int m, double ai[n][m]) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
printf("%g ", ai[i][j]);
}
}
}
10.11
#include <stdio.h>
void fanbei_arr(int ai[][5], int n);
void show_arr(int ai[][5], int n);
int main(void) {
int ar[3][5] = {{1, 2, 3, 4, 5},
{1, 2, 3, 4, 5},
{1, 2, 3, 4, 5}};
show_arr(ar, 3); //函数名和行数作为参数;
fanbei_arr(ar, 3);
show_arr(ar, 3);
return 0;
}
void fanbei_arr(int ai[][5], int n) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < 5; ++j) {
ai[i][j] *= 2;
}
}
}
void show_arr(int ai[][5], int n) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < 5; ++j) {
printf("%d ", ai[i][j]);
}
}
putchar('\n');
}
10.12
#include <stdio.h>
#define MONTHS 12
#define YEARS 5
//本质上是将二维数组作为参数传入函数,处理二维数组的数据
void total_rain(float [][12], int n);
void month_average_rain(float [][12], int n);
int main() {
float rain[YEARS][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}
};
total_rain(rain, 5);
month_average_rain(rain, 5);
printf("\n");
return 0;
}
void total_rain(float a[][12], int n) {
int year, month;
float subtot, total;
printf("YEAR RAINFALL (inches)\n");
for (year = 0, total = 0; year < n; ++year) {
for (month = 0, subtot = 0; month < MONTHS; ++month) subtot += a[year][month];
printf("%5d %15.1f\n", 2010 + year, subtot);
total += subtot;
}
printf("\nThe yearly average is %.1f inches.\n\n", total / YEARS);
}
void month_average_rain(float a[][12], int n) {
int year, month;
float subtot, total;
printf("MONTHLY AVERAGES:\n");
printf(" Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec\n");
for (month = 0; month < MONTHS; ++month) {
for (year = 0, subtot = 0; year < n; ++year)subtot += a[year][month];
printf("%4.1f ", subtot / YEARS);
}
}
10.13
#include <stdio.h>
void in(double [][5], int n); //将用户输入的数字传入二维数组,采用传统C处理数组的方式
double average1d(double []); //对一维数组求平均值,采用传统C处理数组的方式
double average2d(double [][5], int n);//对整个二维数组求平均值,采用传统C处理数组的方式
double maxnum(double *);//直接用指针指向二维数组第一个数组的第一个元素,然后遍历所有double元素,查找最大值;
int main(void) {
double average, max;
double input[3][5];
in(input, 3);
for (int i = 0; i < 3; ++i) {
average = average1d(input[i]);
printf("The average of %dst list is %g\n", i, average);
}
average = average2d(input, 3);
printf("The average of whole list is %g\n", average);
double *ptr = &input[0][0];
max = maxnum(ptr);
printf("The max of whole list is %g\n", max);
return 0;
}
void in(double ai[][5], int n) {
double num;
int m = 0;
while (m < n) {
for (int i = 0; i < 5; ++i) {
scanf("%lf", &num);
while (getchar() != '\n') continue; //将用户输入的换行符消除掉
ai[m][i] = num;
}
m++;
}
}
double average1d(double ai[]) {
double sum = 0;
double average;
for (int i = 0; i < 5; ++i) {
sum += ai[i];
}
average = sum / 5;
return average;
}
double average2d(double ai[][5], int n) {
double sum = 0;
double average;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < 5; ++j) {
sum += ai[i][j];
}
}
average = sum / (3 * 5);
return average;
}
double maxnum(double *pi) {
double max = *pi;
for (int i = 1; i < 15; ++i) {
max = (max < *(pi + i)) ? *(pi + i) : max;
}
return max;
}
10.14
#include <stdio.h>
void in(int n, int m, double [n][m]); //将用户输入的数字传入二维数组,采用变长数组接收数组对象
double average1d(int n, double [n]); //对一维数组求平均值,采用变长数组接收数组对象
double average2d(int n, int m, double [n][m]);//对整个二维数组求平均值,采用变长数组接收数组对象
double maxnum(double *);//直接用指针指向二维数组第一个数组的第一个元素,然后遍历所有double元素,查找最大值;
int main(void) {
double average, max;
int n = 3;
int m = 5;
double input[n][m];
in(n, m, input);
for (int i = 0; i < 3; ++i) {
average = average1d(m, input[i]);
printf("The average of %dst list is %g\n", i, average);
}
average = average2d(3, 5, input);
printf("The average of whole list is %g\n", average);
double *ptr = &input[0][0];
max = maxnum(ptr);
printf("The max of whole list is %g\n", max);
return 0;
}
void in(int n, int m, double ai[n][m]) {
double num;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
scanf("%lf", &num);
while (getchar() != '\n') continue; //将用户输入的换行符消除掉
ai[i][j] = num;
}
}
}
double average1d(int n, double ai[n]) {
double sum = 0;
double average;
for (int i = 0; i < n; ++i) {
sum += ai[i];
}
average = sum / 5;
return average;
}
double average2d(int n, int m, double ai[n][m]) {
double sum = 0;
double average;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
sum += ai[i][j];
}
}
average = sum / (n * m); //直接用变量相乘得到二维数组的基本元素的个数
return average;
}
double maxnum(double *pi) {
double max = *pi;
for (int i = 1; i < 15; ++i) {
max = (max < *(pi + i)) ? *(pi + i) : max;
}
return max;
}