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指向由3int值构成的指针(非法)
    pa = ar1;          // pa指向由3int值构成的数组,ar1也指向由3int值构成的数组
    pa = ar2;          // pa指向由3int值构成的数组,ar2指向由2int值构成的数组(非法)
    p2 = &pt;          // p2是(指向int指针)的指针,&pt(头一次见,得记下来)也是(指向int指针)的指针
    *p2 = ar2[0];      // *p2为指向int的指针,ar2[0]也是指向int的指针
    p2 = ar2;          // p2是(指向int指针)的指针,ar2是指向由2int值构成的数组(非法)
    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');
    }
}
posted @ 2017-10-14 17:28  AprilieJin  阅读(324)  评论(0编辑  收藏  举报