C Primer Plus 第10章 数组和指针 编程练习
这章感觉好难啊,放个别人的总结.
// 多维数组和指针
#include <stdio.h>
int main(void)
{
int zippo[4][2] = {{2, 4}, {6, 8}, {1, 3}, {5, 7}};
/*
zippo[0]是一个整数大小对象的地址,而zippo是两个整数大小对象的地址。
因为(一个)整数和两个整数组成的数组开始于同一个地址,因此zippo和zippo[0]具有相同的数值。
验证:
输出也显示出二维数组zippo的地址和一维数组zippo[0]的地址是相同的,均为相应的数组
首元素的地址,它的值是和&zippo[0][0]相同的;
而且,*zippo也是一个指针,它与一维数组zippo[0](也是一个指针)的地址相同,证明了我的猜想!
*/
printf("===========首先验证第一条结论===========\n");
printf("zippo: \t\t%p\n&zippo[0]: \t%p\n", zippo, &zippo[0]);
printf("zippo[0]: \t%p\n&zippo[0][0]: \t%p\n",zippo[0],&zippo[0][0]);
printf("*zippo: \t%p\n&*zippo: \t%p\n", *zippo, &*zippo);
printf("\n");
/*
zippo所指向对象的大小是两个int,而zippo[0]所指向对象的大小是一个int
验证:
zippo[0]指向4字节长的数据对象。对zippo[0]加1导致它的值增加4。数组名zippo是包含
两个int数的数组的地址,因此它指向8字节长的数据对象。所以,对zippo加1导致它的值增加8。
*/
printf("===========然后验证第二条结论===========\n");
printf("zippo: \t\t%p\nzippo+1: \t%p\n", zippo, zippo+1);
printf("zippo[0]: \t%p\nzippo[0]+1: \t%p\n", zippo[0], zippo[0]+1);
printf("\n");
/*
*zippo也是一个指针,它与一维数组zippo[0](也是一个指针)的地址相同,它们指向同一个int变量
即zippo[0][0]
*zippo[0] = zippo[0][0]
**zippo = *zippo[0] = zippo[0][0](得证)
------------------------------------------------
分析*(*(zippo+2)+1)
zippo------------------第1个大小为2个int的元素的地址
zippo+2----------------第3个大小为2个int的元素的地址
*(zippo+2)-------------第3个元素,即包含2个int值的数组,因此也是其第1个元素的(int值)的地址
*(zippo+2)+1-----------包含2个int值的数组的第2个元素(int值)的地址
*(*(zippo+2)+1)--------数组第3行第2列int(zippo[2][1])的值
总结:更一般地,要表示单个元素,可以使用数组符号或指针符号;并且在这两种表示中即可以使用
数组名,也可以使用指针:
zippo[m][n] == *(*(zippo+m)+n)
*/
printf("===========最后验证第三条结论===========\n");
printf("*zippo: \t%p\nzippo[0]: \t%p\n", zippo, zippo[0]);
printf("*(zippo+1): \t%p\nzippo[1]: \t%p\n", *(zippo+1), zippo[1]);
printf("**zippo: \t%d\nzippo[0][0]: \t%d\n", **zippo, zippo[0][0]);
printf("*(*(zippo+2)+1)\t%d\nzippo[2][1]: \t%d\n", *(*(zippo+2)+1), zippo[2][1]);
return 0;
}
===========首先验证第一条结论===========
zippo: 0x7fff1c31a900
&zippo[0]: 0x7fff1c31a900
zippo[0]: 0x7fff1c31a900
&zippo[0][0]: 0x7fff1c31a900
*zippo: 0x7fff1c31a900
&*zippo: 0x7fff1c31a900
===========最后验证第三条结论===========
*zippo: 0x7fff1c31a900
zippo[0]: 0x7fff1c31a900
*(zippo+1): 0x7fff1c31a908
zippo[1]: 0x7fff1c31a908
**zippo: 2
zippo[0][0]: 2
*(*(zippo+2)+1) 3
zippo[2][1]: 3
// 指针的兼容性
#include <stdio.h>
int main(void)
{
/*
指针之间的赋值规则比数值类型的赋值更严格
举例说明:
*/
int n = 5;
double x;
int * pi = &n;
double * pd = &x;
x = n; // 不需要进行类型转换就直接把一个int数值赋给一个double类型的变量(隐藏的类型转换)
pd = pi // 编译时错误,原因:pd指向一个double类型的数值,pi指向一个int类型的数值
int * pt;
int (* pa) [3];
int ar1[2][3];
int ar2[3][2];
int **p2; // (指向int指针)的指针
pt = &ar1[0][0]; // pt为指向一个int数值的指针,ar1[0][0]是一个int数值的变量
pt = ar1[0]; // pt为指向一个int数值的指针,ar1[0]也为指向一个int数值的指针
pt = ar1; // pt为指向一个int数值的指针,ar1指向由3个int值构成的指针(非法)
pa = ar1; // pa指向由3个int值构成的数组,ar1也指向由3个int值构成的数组
pa = ar2; // pa指向由3个int值构成的数组,ar2指向由2个int值构成的数组(非法)
p2 = &pt; // p2是(指向int指针)的指针,&pt(头一次见,得记下来)也是(指向int指针)的指针
*p2 = ar2[0]; // *p2为指向int的指针,ar2[0]也是指向int的指针
p2 = ar2; // p2是(指向int指针)的指针,ar2是指向由2个int值构成的数组(非法)
return 0;
}
复习题.
int ref[] = { 8, 4, 0, 2 };
3.
ref的地址是什么?ref + 1 是什么意思?++ref指向什么?
答:ref的数组名是指向首元素的地址。ref + 1 是指向该数组的第二个元素。 ++ref是错误的,因为ref是常量而不是变量。 (数组元素也是一种变量,其标识方法为数组名后跟一个下标。)有关变量和常量:http://c.biancheng.net/cpp/html/19.html
6.
假设有下面的声明:int grid[30][100];
a.用1种写法表示grid[22][56]
b.用2种写法表示grid[22][0]
c.用3种写法表示grid[0][0]
答:a:&grid[22][56] b:grid[22], &grid[22][0] c:grid[0], &grid[0][0], (int *) grid
(grid 是内含100个元素的grid[0]数组的地址。这两个地址数值相同,但是类型不同,可以用强制类型转换把他们转换成相同的类型。)
7.
d.psa是一个内含20个元素的数组,每个元素都是指向int的指针
e.pstr是一个指向数组的指针,该数组内含20个char类型的值
答:d. int * psa[20]; //[]比*先生效,所以每个元素都是指向int的指针.
e. char (*pstr)[20]; //这样就*先生效,所以pstr指向的数组含有20个char类型的值.
编程练习
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}
};
const float (*pt)[MONTHS] = rain; //const数据不可赋给普通指针,否则通过指针就能改变const中的数据.
float subtot, total;
int year, month;
printf(" YEAR RAINFALL (inches)\n");
for (year = 0, total = 0; year < YEARS; year++) {
for (month = 0, subtot = 0; month < MONTHS; month++)
subtot += *(*(pt + year) + month);
printf("%5d %15.1f\n", 2010 + year, subtot);
total = 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 Oct ");
printf(" Nov Dec\n");
for (month = 0; month < MONTHS; month++) {
for (year = 0, subtot = 0; year < YEARS; year++)
subtot += *(*(pt + year) + month);
printf("%4.1f ", subtot / YEARS);
}
printf("\n");
return 0;
}
2.
#include <stdio.h>
void copy_arr(double *ar, double *pt, int n);
void copy_arr2(double *ar, double *pt, int n);
void copy_arr3(double *ar, double *pt, double *pr);
int main(void) {
double source[5] = {1.1, 2.2, 3.3, 4.4, 5.5};
double targe1[5], targe2[5], targe3[5];
printf("targe1:\n");
copy_arr(targe1, source, 5);
putchar('\n');
printf("targe2:\n");
copy_arr2(targe2, source, 5);
putchar('\n');
printf("targe3:\n");
copy_arr3(targe3, source, source + 5);
return 0;
}
void copy_arr(double *ar, double *pt, int n) {
int i;
for (i = 0; i < n; i++) {
ar[i] = pt[i];
printf("[%d]: %.1lf\n", i, ar[i]);
}
}
void copy_arr2(double *ar, double *pt, int n) {
int i;
for (i = 0; i < n; i++) {
*(ar + i) = *(pt + i);
printf("[%d]: %.1lf\n", i, *(ar + i));
}
}
void copy_arr3(double *ar, double *start, double *end) {
int i = 0;
while (start < end) {
*ar = *start;
printf("[%d]: %.1lf\n", i++, *ar);
start++;
ar++;
}
}
3.
#include <stdio.h>
int max(int *ar, int n);
int main(void) {
int source[5] = {1, 10, 3, 4, 5};
printf("MAX: %d", max(source, 5));
return 0;
}
int max(int *ar, int n){
int max = ar[0];
for (int i = 0; i < n; ++i) {
if (max < ar[i])
max = ar[i];
}
return max;
}
4.
#include <stdio.h>
int max(double *ar, int n);
int main(void) {
double source[5] = {1, 10, 11, 4, 5};
printf("MAX_: %d", max(source, 5));
return 0;
}
int max(double *ar, int n){
int max = ar[0];
int x = 0;
for (int i = 0; i < n; ++i) {
if (max < ar[i]){
max = ar[i];
x = i;
}
}
return x;
}
5.
#include <stdio.h>
int max(int *ar, int n);
int main(void) {
int source[5] = {1, 10, 3, 4, 5};
printf("Difference: %d", max(source, 5));
return 0;
}
int max(int *ar, int n){
int max = ar[0];
int min = ar[0];
for (int i = 0; i < n; ++i) {
if (max < ar[i])
max = ar[i];
}
for (int i = 0; i < n; ++i) {
if (min > ar[i])
min = ar[i];
}
return max - min;
}
6.
#include <stdio.h>
void copy(double *pr, double *ar, int n);
int main(void) {
double source[5] = {1, 10, 3, 4, 5}, targe[5];
copy(targe, source, 5);
for (int i = 0; i < 5; ++i) {
printf("%5.1lf",targe[i]);
}
return 0;
}
void copy(double *pr, double *ar, int n){
int x = n - 1;
for (int i = 0; i < n; ++i,x--) {
pr[x] = ar[i];
}
}
7.
//运行完成后会出现*** stack smashing detected ***这个,我也不知道啥情况记一下先吧.
#include <stdio.h>
void copy(double ar[][3], double pt[][3], int n);
int main(void)
{
double soure[2][3] = {{1,2,3},{4,5,6}};
double target[2][3];
copy(target,soure,2);
for (int i = 0; i < 2; ++i) {
for (int m = 0; m < 3; ++m) {
printf("target[%d][%d]:%.1lf\n", i, m, target[i][m]);
}
}
return 0;
}
void copy(double ar[][3], double pt[][3], int n){
for (int i = 0; i < n; ++i) {
for (int m = 0; m < 5; ++m) {
ar[i][m] = pt[i][m];
}
}
}
8.
#include <stdio.h>
void copy(double ar[], double pt[], int n);
int main(void) {
double soure[7] = {1, 2, 3, 4, 5, 6, 7};
double target[3];
copy(target, soure + 2, 3);
for (int m = 0; m < 3; ++m) {
printf("target[%d]:%.1lf\n", m, target[m]);
}
return 0;
}
void copy(double ar[], double pt[], int n) {
for (int m = 0; m < n; ++m) {
ar[m] = pt[m];
}
}
9.
#include <stdio.h>
void copy(int n, int m, double ar[n][m], double pt[n][m]);
void print(int n, int m, double ar[n][m]);
int main(void){
double soure[3][5] = {{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};
double target[3][5];
copy(3, 5, target, soure);
printf("soure:\n");
print(3, 5, soure);
printf("target:\n");
print(3, 5, target);
return 0;
}
void copy(int n, int m, double ar[n][m], double pt[n][m]){
for (int i = 0; i < n; ++i) {
for (int a = 0; a < m; ++a) {
ar[i][a] = pt[i][a];
}
}
}
void print(int n, int m, double ar[n][m]){
for (int i = 0; i < n; ++i) {
for (int a = 0; a < m; ++a) {
printf("[%d][%d]:%.1lf\n", i, a, ar[i][a]);
}
}
}
10.
#include <stdio.h>
void copy(double pt[],double zr[], double ar[],int n);
void print(double ar[], int n);
int main(void){
double soure[5] = {1,2,3,4,5};
double soure2[5] = {1,2,3,4,5};
double target[5];
copy(target, soure, soure2, 5);
print(target, 5);
return 0;
}
void copy(double pt[],double zr[], double ar[],int n){
for (int i = 0; i < n; ++i) {
pt[i] = zr[i] + ar[i];
}
}
void print(double ar[], int n){
for (int i = 0; i < n; ++i) {
printf("[%d]:%.1lf\n", i, ar[i]);
}
}
11.
#include <stdio.h>
void doub(int n, int m, double ar[n][m]);
void print(int n, int m, double ar[n][m]);
int main(void) {
double soure[3][5] = {{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10},
{11, 12, 13, 14, 15}};
doub(3, 5, soure);
printf("soure:\n");
print(3, 5, soure);
return 0;
}
void doub(int n, int m, double ar[n][m]) {
for (int i = 0; i < n; ++i) {
for (int a = 0; a < m; ++a) {
ar[i][a] = ar[i][a] * 2;
}
}
}
void print(int n, int m, double ar[n][m]) {
for (int i = 0; i < n; ++i) {
for (int a = 0; a < m; ++a) {
printf("[%d][%d]:%.1lf\n", i, a, ar[i][a]);
}
}
}
12.
#include <stdio.h>
#define MONTHS 12
#define YEARS 5
void eachmonths(const float [][MONTHS], int n);
float sum(const float [][MONTHS], int n);
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}
};
float total;
printf(" YEAR RAINFALL (inches)\n");
total = sum(rain, YEARS);
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 Oct ");
printf(" Nov Dec\n");
eachmonths(rain, YEARS);
return 0;
}
float sum(const float ar[][MONTHS], int n) {
float subtot, total;
int i, m;
for (i = 0, total = 0; i < n; i++) {
for (m = 0, subtot = 0; m < MONTHS; m++)
subtot += ar[i][m];
printf("%5d %15.1f\n", 2010 + i, subtot);
total += subtot;
}
return total;
}
void eachmonths(const float ar[][MONTHS], int n) {
float subtot;
int m;
for (int i = 0; i < MONTHS; ++i) {
for (m = 0, subtot = 0; m < n; ++m) {
subtot += ar[m][i];
}
printf("%4.1f ", subtot / YEARS);
}
printf("\n");
}
//做完这题之后就感觉自己是个弱智!
/*爆炸级别弱智错误还找了半天.
float sum(const float ar[][MONTHS], int n) {
float subtot, total;
for (int i = 0, total = 0; i < n; i++) {
for (int m = 0, subtot = 0; m < MONTHS; m++)
subtot += ar[i][m];
printf("%5d %15.1f\n", 2010 + i, subtot);
total += subtot;
}
return total;
}
这样子之后就在for循环中把total和subtot声明成了int格式了,
然后我不就是个傻逼了吗!!哇 真的是被自己蠢哭了.*/
13 and 14
#include <stdio.h>
void enter_number(int n, int m, double ar[n][m]);
double average_group(double ar[], int n);
double average_all(int n, int m, double ar[n][m]);
double MAX(int n, int m, double ar[n][m]);
void show(int n, int m, double ar[n][m]);
int main(void) {
int row, col;
printf("请输入你需要的数组(例如3×5):");
scanf("%d %d", &row, &col);
double target1[row][col];
printf("请输入数据:\n");
enter_number(row, col, target1);
for (int i = 0; i < row; ++i) {
printf("第 %d 组 (%d个) 的平均值是: %.1lf\n", i + 1, col, average_group(target1[i], col));
}
printf("所有数据的平均值是: %.1lf\n", average_all(row, col, target1));
printf("所有数据的最大值是: %.1lf\n\n\n", MAX(row, col, target1));
printf("你输入的数组是:\n");
show(row, col, target1);
return 0;
}
void enter_number(int n, int m,double ar[n][m]) {
double number;
for (int i = 0; i < n; ++i) {
for (int x = 0; x < m; ++x) {
scanf("%lf", &number);
ar[i][x] = number;
}
}
}
double average_group(double ar[], int n){
double total = 0;
for (int i = 0; i < n; ++i) {
total += ar[i];
}
return total / n;
}
double average_all(int n, int m, double ar[n][m]){
double total = 0;
for (int i = 0; i < n; ++i) {
for (int x = 0; x < m; ++x) {
total += ar[i][x];
}
}
return total / (n * m);
}
double MAX(int n, int m, double ar[n][m]) {
double max = ar[0][0];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (max < ar[i][j])
max = ar[i][j];
}
}
return max;
}
void show(int n, int m, double ar[n][m]){
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
printf("%8.1lf", ar[i][j]);
}
putchar('\n');
}
}