C Primer Plus 第六版 第10章 程式設計練習
1.修改程式清單 10.7 的 rain.c 程式,用指針進行計算(仍要聲明并初始化數組)。
#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;
printf(" YEAR RAINFALL (inches)\n");
for (year = 0, total = 0; year < YEARS; 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/YEARS);
printf("MONTHLY AVERAGES:\n\n");
printf(" Jan Feb Mar Apr May Jun Jul Aug Sep ");
printf(" Oct Nov Dec\n");
for (month = 0; month < MONTHS; month++)
{
for (year = 0, subtot =0; year < YEARS; year++)
subtot += *(*(rain+year)+month);
printf("%4.1f ", subtot/YEARS);
}
printf("\n");
return 0;
}
2.編寫一個程式,初始化一個 double 類型的數組,然後把該數組的内容拷貝至 3 個其他數組中(在 main() 中聲明這 4 個數組)。使用帶數組表示法的函數進行第 1 份拷貝。使用帶指針表示法和指針遞增的函數進行第 2 份拷貝。把目标數組名和待拷貝的元素個數作為前兩個函數的參數。第 3 個函數以目标數組名、源數組名和指向源數組的最後一個元素後面元素的指針。也就是說,給定以下聲明,則函數調用如下所示:
copy_arr(target1, source, 5);
copy_ptr(target2, source, 5);
copy_ptrs(target3, source, source+5);
print(source,5);
print(target1,5);
print(target2,5);
print(target3,5);
#include <stdio.h>
void copy_arr(double ar[], double so[], int n);
void copy_ptr(double *ar, double *so, int n);
void copy_ptrs(double *ar, double *so, double *end);
void print(double *ar, int n);
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];
copy_arr(target1, source, 5);
copy_ptr(target2, source, 5);
copy_ptrs(target3, source, source+5);
print(source,5);
print(target1,5);
print(target2,5);
print(target3,5);
}
void copy_arr(double ar[], double so[], int n)
{
int i;
for (i = 0; i < n; i++)
ar[i] = so[i];
}
void copy_ptr(double *ar, double *so, int n)
{
while (--n >= 0)
*(ar++) = *(so++);
}
void copy_ptrs(double *ar, double *so, double *end)
{
while (so < end)
{
*(ar++) = *(so++);
}
}
void print(double *ar, int n)
{
int i;
for (i = 0; i < n; i++)
{
printf("%.1f ",ar[i]);
}
printf("\n");
}
3.編寫一個函數,傳回存儲在 int 類型的數組中的最大值,并在一個簡單的程式中測試該函數。
#include <stdio.h>
int maxar(int ar[], int n);
int main(void)
{
int ar[10]={12,2,9,8,7,6,5,4,11,2};
printf("最大值為:%d\n",maxar(ar,10));
return 0;
}
int maxar(int ar[], int n)
{
int i;
int max = ar[0];
for (i = 1; i < n; i++)
if (max < ar[i])
max = ar[i];
return max;
}
4.編寫一個函數,傳回存儲在 double 類型數組中最大值的下标,并在一個簡單的程式中測試該函數。
#include <stdio.h>
int maxar(double ar[], int n);
int main(void)
{
double ar[10]={1.1,2.2,4.4,3.3,9.9,
5.5,10.10,8.8,7.7,11.11};
printf("最大值下标為:%d\n",maxar(ar,10));
return 0;
}
int maxar(double ar[], int n)
{
int i;
int index = 0;
for (i = 1; i < n; i++)
if (ar[index] < ar[i])
index = i;
return index;
}
5.編寫一個函數,傳回存儲在 double 類型數組中的最大值和最小值的內插補點,并在一個簡單的程式中測試該函數。
#include <stdio.h>
double diffar(double ar[], int n);
int main(void)
{
double ar[10]={10.1,2.2,3.5,6.5,1.0,22.3,5.5,6.6,7.7,8.8};
printf("內插補點為:%f\n",diffar(ar,10));
return 0;
}
double diffar(double ar[], int n)
{
int i;
double max,min;
max = min = ar[0];
for (i = 0; i < n; i++)
if (min > ar[i])
min = ar[i];
for (i = 0; i < n; i++)
if (max < ar[i])
max = ar[i];
return (max-min);
}
6.編寫一個函數,把 double 類型數組中的資料倒序排列,并在一個簡單的程式中測試該函數。
#include <stdio.h>
void revorde(double ar[], int n);
void print(double ar[], int n);
int main(void)
{
double ar[10]={10.2,45.2,111.43,22.45,99.1,223.3,
55.44,66.55,66.77,77.88};
print(ar,10);
revorde(ar,10);
print(ar,10);
return 0;
}
void revorde(double ar[], int n)
{
int i,j;
double temp;
for (j = 0; j < n-1; j++)
for (i = j+1; i < n; i++)
if (ar[j] > ar[i])
{
temp = ar[j];
ar[j] = ar[i];
ar[i] = temp;
}
}
void print(double ar[], int n)
{
int i;
for (i = 0; i < n; i++)
{
printf("%.2f ",ar[i]);
}
putchar('\n');
}
7.編寫一個程式,初始化一個 double 類型的二維數組,使用程式設計練習 2 中的一個拷貝函數把該數組中的資料拷貝至另一個二維數組中 (因為二維數組是數組的數組,是以可以使用處理一維數組的拷貝函數來處理數組中的每個子數組)。
#include <stdio.h>
void copy(double *ar, double *so, int n);
void print(double (*ar)[5], int n);
int main(void)
{
int i;
double ar[5][5]={1,2,3,4,5,
6,7,8,9,10,
11,12,13,14,15,
16,17,18,19,20,
21,22,23,24,25};
double so[5][5];
for (i = 0; i < 5; i++)
copy(ar[i],so[i],5);
print(so,5);
return 0;
}
void copy(double *ar, double *so, int n)
{
int i;
for (i = 0; i < 5; i++)
*(so+i) = *(ar+i);
}
void print(double (*ar)[5], int n)
{
int i,j;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
printf("%.1f ",*(*(ar+i)+j));
putchar('\n');
}
}
8.使用程式設計練習 2 中的拷貝函數,把一個内含 7 個元素的數組中第 3~第 5 個元素拷貝至内含 3 個元素的數組中。該函數本身不需要修改,隻需要選擇合适的實際參數(實際參數不需要是數組名和數組大小,隻需要是數組元素的位址和待處理元素的個數)。
#include <stdio.h>
void copy_arr(int *ar, int *so, int n);
void print(int *ar, int n);
int main(void)
{
int so[7]={1,2,3,4,5,6,7};
int ar[3];
copy_arr(ar,so+2,3);
print(ar,3);
return 0;
}
void copy_arr(int *ar, int *so, int n)
{
int i;
for (i=0;i<n;i++)
ar[i] = so[i];
}
void print(int *ar, int n)
{
int i;
for (i=0;i<n;i++)
printf("%d ",ar[i]);
printf("\n");
}
9.編寫一個程式,初始化一個 double 類型 3 x 5 二維數組,使用一個處理變長數組的函數将其拷貝至另一個二維數組中。還要編寫一個以變長數組為形參的函數以顯示兩個數組的内容。這兩個函數應該能處理任意 N x M 數組。
#include <stdio.h>
void copy(int n, int m, double so[n][m], double ar[n][m]);
void print(int n, int m, double ar[n][m]);
int main(void)
{
double so[5][5]={{1,2,3,4,5},
{6,7,8,9,10},
{11,12,13,14,15}};
double ar[5][5];
copy(5,5,so,ar);
print(5,5,so);
print(5,5,ar);
return 0;
}
void copy(int n, int m, double so[n][m], double ar[n][m])
{
int i,j;
for (i=0;i<n;i++)
for (j=0;j<m;j++)
ar[i][j] = so[i][j];
}
void print(int n, int m, double ar[n][m])
{
int i,j;
for (i=0;i<n;i++)
{
for (j=0;j<5;j++)
printf("%.2f ",ar[i][j]);
printf("\n");
}
}
10.編寫一個函數,把兩個數組中相對應的元素相加,然後把結果存儲在第 3 個數組中。也就是說,如果數組 1 中包含的值是 2、4、5、8,數組 2 中包含的值是 1、0、4、6,那麼該函數把 3、4、9、14 賦給第 3 個數組。函數接受 3 個數組名和一個數組大小。在一個簡單的程式中測試該函數。
#include <stdio.h>
void sum(int *ar1, int *ar2, int *ar3, int n);
void print(int *ar, int n);
int main(void)
{
int ar1[4]={1,3,5,7};
int ar2[4]={2,4,6,8};
int ar3[4];
sum(ar1,ar2,ar3,4);
print(ar1,4);
print(ar2,4);
print(ar3,4);
return 0;
}
void sum(int *ar1, int *ar2, int *ar3, int n)
{
int i;
for (i = 0; i < n; i++)
*(ar3+i) = *(ar1+i) + *(ar2+i);
}
void print(int *ar, int n)
{
int i;
for (i = 0; i < n; i++)
printf("%5d",ar[i]);
printf("\n");
}
11.編寫一個程式,聲明一個 int 類型的 3 x 5 二維數組,并用合适的值初始化它。該程式列印數組中的值,然後個值翻倍(即是原值的 2 倍),并顯示出各元素的新值。編寫一個函數顯示數組的内容,在編寫一個函數把各元素的值翻倍。這兩個函數都以函數名和行數作為參數。
#include <stdio.h>
void print(int (*ar)[5], int n);
void dou(int (*ar)[5], int n);
int main(void)
{
int ar[3][5]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
print(ar,3);
dou(ar,3);
print(ar,3);
return 0;
}
void print(int ar[][5], int n)
{
int i,j;
for (i=0;i<n;i++)
{
for (j=0;j<5;j++)
printf("%5d",ar[i][j]);
printf("\n");
}
}
void dou(int (*ar)[5], int n)
{
int i,j;
for (i=0;i<n;i++)
for (j=0;j<5;j++)
ar[i][j] *= 2;
}
12.重寫程式清單 10.7 的 rain.c 程式,把 main() 中的主要任務都改成用函數來完成。
#include <stdio.h>
#define MONTHS 12
#define YEARS 5
float year(const float (*ar)[MONTHS], int n);
void month(const float (*ar)[MONTHS], int n);
int main(void)
{
float sum;
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}
};
printf(" YEAR RAINFALL (inches)\n");
sum=year(rain,YEARS);
printf("\nThe yearly average is %.1f inches.\n\n",
sum / YEARS);
printf("MONTHLY AVERAGES:\n\n");
printf(" Jan Feb Mar Apr May Jun Jul Aug Sep ");
printf(" Oct Nov Dec\n");
month(rain,MONTHS);
return 0;
}
float year(const float (*ar)[MONTHS], int n)
{
int i,j;
float total = 0;
float sum = 0;
for (i = 0; i < n; i++)
{
for (j = 0, total = 0; j < MONTHS; j++)
total += ar[i][j];
printf("%5d %15.1f \n", 2010+i,total);
sum += total;
}
return sum;
}
void month(const float (*ar)[MONTHS], int n)
{
int i,j;
float total = 0;
for (i = 0; i < n; i++)
{
for (j = 0, total = 0; j < YEARS; j++)
total += ar[j][i];
printf("%4.1f ", total/YEARS);
}
printf("\n");
}
13.編寫一個程式,提示使用者輸入 3 組數,每組數包含 5 個 double 類型的數(假定使用者都正确地響應,不會輸入非數值資料)。改程式完成以下任務。
a.把使用者輸入的資料存儲在 3 x 5 的數組中
b.計算每組(5 個)資料的平均值
c.計算所有資料的平均值
d.找出這 15 個資料中的最大值
e.列印結果
每個任務都要用單獨的函數來完成(使用傳統 C 處理數組的方式)。完成任務 b ,要編寫一個計算并傳回一維數組平均值的函數,利用循環調用該函數 3 次。對于處理其他任務的函數,應該把整個數組作為參數,完成任務 c 和 d 的函數應該把結果傳回主調函數。
#include <stdio.h>
#define N 3
#define M 5
void input(double (*ar)[M]);
void mean(double (*ar)[M], double *sum);
void means(double (*ar)[M], double *sums);
void sort(double (*ar)[M], double *max);
void print(double (*ar)[M],double *sum, double *sums, double *max);
int menu(void);
int main(void)
{
int ch;
double ar[N][M];
double sum[M],sums,max;
while ((ch = menu()) != 0)
{
switch (ch)
{
case 1 : input(ar);break;
case 2 : mean(ar,sum);break;
case 3 : means(ar,&sums);break;
case 4 : sort(ar,&max);break;
case 5 : print(ar,sum,&sums,&max);break;
}
}
return 0;
}
int menu(void)
{
int ch;
puts("======================");
puts("1) 輸入3x5的資料 |");
puts("2) 每組資料的平均值 |");
puts("3) 所有資料的平均值 |");
puts("4) 資料中的最大值 |");
puts("5) 列印結果 |");
puts("0) 退出 |");
while (scanf("%d",&ch) != 1)
{
while (getchar() != '\n');
puts("請輸入<0-5>:");
}
while (getchar() != '\n');
return ch;
}
void input(double (*ar)[M])
{
int i,j;
for (i = 0; i < N; i++)
{
printf("請輸入第%d組資料%d個:\n",i+1,M);
for (j = 0; j < M; j++)
scanf("%lf",&ar[i][j]);
}
}
void mean(double (*ar)[M], double *sum)
{
int i,j;
double total=0;
for (i = 0; i < N; i++)
{
for (j = 0, total = 0; j < M; j++)
{
total += ar[i][j];
}
sum[i] = total / M;
}
}
void means(double (*ar)[M], double *sums)
{
int i,j;
double total=0;
for (i = 0; i < N; i++)
{
for (j = 0; j < M; j++)
{
total += ar[i][j];
}
}
*sums = total / (N * M);
}
void sort(double (*ar)[M], double *max)
{
int i,j;
*max = ar[0][0];
for (i = 0; i < N; i++)
for (j = 0; j < M; j++)
if (*max < ar[i][j])
*max = ar[i][j];
}
void print(double (*ar)[M],double *sum, double *sums, double *max)
{
int i,j;
for (i = 0; i < N; i++)
{
printf("第%d組資料為:\n",i+1);
for (j = 0; j < M; j++)
printf("%6.1lf ",ar[i][j]);
putchar('\n');
}
for (i = 0; i < N; i ++)
{
printf("第%d組資料的平均值為:%lf\n",i+1,sum[i]);
}
printf("資料的最大值為:%lf\n",*max);
}
14.以變長數組作為函數形參,完成程式設計練習 13。
#include <stdio.h>
#define N 3
#define M 5
void input(int n, int m, double ar[n][m]);
void mean(int n, int m, double ar[n][m]);
void means(int n, int m, double ar[n][m]);
void sort(int n, int m, double ar[n][m]);
int menu(void);
int main(void)
{
int ch;
double ar[N][M];
while ((ch = menu()) != 0)
{
switch (ch)
{
case 1 : input(N,M,ar);break;
case 2 : mean(N,M,ar);break;
case 3 : means(N,M,ar);break;
case 4 : sort(N,M,ar);break;
}
}
return 0;
}
int menu(void)
{
int ch;
puts("======================");
puts("1) 輸入3x5的資料 |");
puts("2) 每組資料的平均值 |");
puts("3) 所有資料的平均值 |");
puts("4) 資料中的最大值 |");
puts("0) 退出 |");
while (scanf("%d",&ch) != 1)
{
while (getchar() != '\n');
puts("請輸入<0-4>:");
}
while (getchar() != '\n');
return ch;
}
void input(int n, int m, double ar[n][m])
{
int i,j;
for (i = 0; i < n; i++)
{
printf("請輸入第%d組資料%d個:\n",i+1,m);
for (j = 0; j < m; j++)
scanf("%lf",&ar[i][j]);
}
for (i = 0; i < n; i++)
{
printf("第%d組資料為:\n",i+1);
for (j = 0; j < m; j++)
printf("%6.1lf ",ar[i][j]);
putchar('\n');
}
}
void mean(int n, int m, double ar[n][m])
{
int i,j;
double total=0;
double sum[m];
for (i = 0; i < n; i++)
{
for (j = 0, total = 0; j < m; j++)
{
total += ar[i][j];
}
sum[i] = total / m;
}
for (i = 0; i < n; i ++)
{
printf("第%d組資料的平均值為:%lf\n",i+1,sum[i]);
}
}
void means(int n, int m, double ar[n][m])
{
int i,j;
double sums;
double total=0;
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
total += ar[i][j];
}
}
sums = total / (n * m);
printf("所有資料的平均值為:%4.1lf\n",sums);
}
void sort(int n, int m, double ar[n][m])
{
int i,j;
double max;
max = ar[0][0];
for (i = 0; i < n; i++)
for (j = 0; j < m; j++)
if (max < ar[i][j])
max = ar[i][j];
printf("資料最大值為:%4.1lf\n",max);
}