C Primer Plus_第10章_数组和指针_编程练习

1.

/*rain.c 针对若干年的降水量数据,计算年降水总量、年降水平均量,以及月降水平均量*/
#include <stdio.h>
#define MONTHS 12
#define YEARS 5

int main (void)
{
    //把数组初始化为2000到2004年的降水量数据
    const float rain[YEARS][MONTHS] = //const声明和初始化数组可保护数据
    {
        {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 years,months;
    float totyear, totmonth;

    printf("YEAR  RAIN:\n");
    for(years=0; years<YEARS; years++)
    {
        for(months=0,totyear=0; months<MONTHS; months++)
            totyear += *(*(rain+years)+months);  //此处应题目要求使用指针形式,同样可以用数组形式
        printf("%4d %4.2f\n",2000+years,totyear);
    }

    printf("\nmonth average:\n");
    printf("JUN  FEB  MAT  APR  MAY  JUN  JLY  AUG  SPT  OCT  NOV  DEC:\n");
    for(months=0; months<MONTHS; months++)
    {
        for(years=0,totmonth=0; years<YEARS; years++)
            totmonth += *(*(rain+years)+months);  //可用数组形式
        printf("%-4.1f ",totmonth/5);
    }
    printf("\nDone!\n");

    return 0;
}

2.

/*一维数组函数调用*/
#include <stdio.h>
void copy_arr (double [], double [], int);
void copy_ptr (double *, double *, int);

int main (void)
{
    double source[] = {1.1, 2.2, 3.3, 4.4, 5.5};
    double target1[5] = {0};    //初始化一个元素全为0的数组可以这样赋值
    double target2[5] = {0};

    printf ("Before operation:\n");
    printf ("source: \t%g\t%g\t%g\t%g\t%g\n",
         source[0], source[1], source[2], source[3], source[4]);
    printf ("target1: \t%g\t%g\t%g\t%g\t%g\n",
         target1[0], target1[1], target1[2], target1[3], target1[4]);
    printf ("target2: \t%g\t%g\t%g\t%g\t%g\n",
         target2[0], target2[1], target2[2], target2[3], target2[4]);

    copy_arr (source, target1, 5);
    copy_ptr (source, target2, 5);

    printf ("\n\nAfter operation:\n");
    printf ("source: \t%g\t%g\t%g\t%g\t%g\n",
         source[0], source[1], source[2], source[3], source[4]);
    printf ("target1: \t%g\t%g\t%g\t%g\t%g\n",
         target1[0], target1[1], target1[2], target1[3], target1[4]);
    printf ("target2: \t%g\t%g\t%g\t%g\t%g\n",
         target2[0], target2[1], target2[2], target2[3], target2[4]);

    return 0;
}

void copy_arr (double a1[], double a2[], int n)
{
    int i;
    for (i = 0; i < n; i++)
        a2[i] = a1[i];  //简单的赋值就可以实现复制数组
}

void copy_ptr (double *p1, double *p2, int n)
{
    int i;
    for (i = 0; i < n; i++)
        *(p2 + i) = *(p1 + i);  //同样,赋值即可实现复制数组
}

/*******************************************PS: 有关%g输出的补充说明************************************************/
//1.%g用于打印浮点型数据时,会去掉多余的零,至多保留六位有效数字(不同于%e的默认保留小数点后6位)
//2.当%g用于打印超过6位的浮点型数据时,因为精度问题,%f不得不输出一个不精确的超过六位的数字,
//  %e也是同样,而%g此时会选择%e格式进行输出,并且按第一条要求,去掉多余的零,并且四舍五入到6位数字。
//3.当一个数字的绝对值很小的时候,要表示这个数字所需要的字符数目就会多到让人难以接受。
//  例如,把π*10^-10写作0.00000000000314159就会显得非常丑陋不雅,反之,如果我们写作3.14159e-10,就不但简洁而且易读好懂。
//  当指数是-4时,这两种表现形式大小相同。对于比较小的数值,除非该数的指数小于或者等于-5,%g才会采用科学计数(%e的格式)进行输出。

3.

/* 找出一个int数组中的最大数 */
#include <stdio.h>
int max (int[], int);

int main (void)
{
    int array[] = {4, 3, 6, 2, 8, 6};
    printf("%d\n",sizeof(array)/sizeof(int));
    printf ("The max is: %d\n", max (array, sizeof(array)/sizeof(int)));

    return 0;
}

int max (int a[], int n)
{
    int i, max;  //for (i = 0, max = a[0]; i < (sizeof(a)/sizeof(int)); i++)//sizeof(a)不能反应sizeof(array)的大小,所以处理数组的函数应该包括一个数组大小的参数
    for (i=0,max=a[0]; i<n; i++)    //n反应出sizeof(array)的大小
        max = (max>a[i]) ? max : a[i]; 

    return max;
}

4.

#include <stdio.h>
int MaxIndex (double * ptr, int n);

int main (void)
{
    double array[] = {4.3, 5.3, 2.6, 9.2, 2.8, 3.6};
    printf ("The max number‘s index is: %d\n", MaxIndex(array, sizeof(array)/sizeof(double)));

    return 0;
}

int MaxIndex (double a[], int n)
{
    int i;
    double max;
    for (i=0,max=a[0]; i<n; i++)
        max = (max>a[i]) ? max : a[i];
    for (i=0; max!=a[i]; i++)
        continue;
    return i;
}

5.

/*求数组中最大值最小值间的差值*/
#include <stdio.h>
double gap (double *, int);

int main (void)
{
    double array[] = {4.3, 5.3, 2.6, 9.2, 2.8, 3.6};
    printf ("The gap between max and min is: %g\n", gap (array, sizeof(array)/sizeof(double)));

    return 0;
}

double gap (double a[], int n)
{
    int i;
    double max, min;
    for (i = 1, max = a[0], min = a[0]; i < n; i++)
    {
        if (max < a[i])  max = a[i];
        if (min > a[i])  min = a[i];
    }
    return (max - min);
}

6.

/*复制二维数组*/
#include <stdio.h>
#define ROWS 2
#define COLS 3
void copy_2d (double source[][COLS], double target[][COLS], int);    //复制二维数组,注意声明处理二维数组的函数时要给出子数组大小信息
void copy_1d (double a1[], double a2[], int n);                        //复制一维数组

int main (void)
{
    int i, j;
    double source[ROWS][COLS] = {{1, 2, 3}, {4, 5, 6}};
    double target[ROWS][COLS] = {0};

    copy_2d (source, target, ROWS);
    for (i=0; i<ROWS; i++)
    {
        for (j = 0; j < COLS; j++)
            printf ("%g\t", target[i][j]);
        printf ("\n");
    }
    return 0;
}

void copy_2d (double (*source)[COLS], double target[][COLS], int n)
{
    int i;
    for (i = 0; i < n; i++)
        copy_1d ( *(source + i), target[i], COLS);    //*(source + i), target[i]都是double(* )[3]型
}

void copy_1d (double a1[], double *a2, int n)
{
    int i;
    for (i = 0; i < n; i++)
        a2[i] = a1[i];
}

7.

/*一维数组函数调用,复制数组中某部分的元素们*/
#include <stdio.h>
void copy (double *, double *, int);

int main (void)
{
    double source[] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7};
    double target[3] = {0};

    printf ("Before operation:\n");
    printf ("source: \t%g\t%g\t%g\t%g\t%g\t%g\t%g\n",
         source[0], source[1], source[2], source[3], source[4], source[5], source[6]);
    printf ("target: \t%g\t%g\t%g\n",
         target[0], target[1], target[2]);

    copy (source + 2, target, 3);    //函数在这里哦,怕你看得心烦不想找

    printf ("\nAfter operation:\n");
    printf ("source: \t%g\t%g\t%g\t%g\t%g\t%g\t%g\n",
         source[0], source[1], source[2], source[3], source[4], source[5], source[6]);
    printf ("target: \t%g\t%g\t%g\n",
         target[0], target[1], target[2]);

    return 0;
}

void copy (double *p1, double *p2, int n)
{
    int i;
    for (i = 0; i < n; i++)
        *(p2 + i) = *(p1 +i);
}

8.

#include <stdio.h>
#define COLS 5
void copy (double (*)[COLS], double (*)[COLS], int);
void display (double (*)[COLS], int);

int main (void)
{
    double source[3][COLS] =
    {
        {1.1, 2.2, 3.3, 4.4, 5.5},
        {6.6, 7.7, 8.8, 9.9, 10.10},
        {11.11, 12.12, 13.13, 14.14, 15.15}
    };
    double target[6][COLS] = {0};

    copy (source, target, 3);

    puts ("source:");
    display (source, 3);
    puts ("\ntarget:");
    display (target, 5);

    return 0;
}

void copy (double (*source)[COLS], double target[][COLS], int rows)    //double (*source)[COLS]等同于double source[][COLS]
{
    int i, j;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < COLS; j++)
            target[i][j] = source[i][j];
    }
}

void display (double (*p)[COLS], int rows)
{
    int i,j;

    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < COLS; j++)
            printf ("%g\t", p[i][j]);
        printf ("\n");
    }

}

突然发现自己写的程序自己都不愿意去读,因为全是代码没有模块化的注释,仅仅偶尔有个细节注释啥的,所以看起来要找,要想,这一段函数是干什么的,实现某个功能的函数在哪里等等。本来程序就是密密麻麻的东西,而且又不是汉语形式的,本身看起来就很费劲。所以还是要多写注释,尤其是模块化地去注释,最好能让人一眼看清程序的整体思路以及模块。

9.

/*两数组对应元素相加放在第三个数组中*/
#include <stdio.h>
void add (double [], double *, double [], int n);

int main (void)
{
    /**************声明和初始化两个源数组和一个目标数组*****************/
    double source1[5] = {1.1, 2.2, 3.3, 4.4, 5.5};
    double source2[5] = {6.6, 7.7, 8.8, 9.9, 10.10};
    double target[5] = {0};

    /**************执行两个源数组相加并且赋值给目标数组*****************/
    add (source1, source2, target, sizeof(source1)/sizeof(double));

    /**************显示两个源数组和目标数组*****************/
    printf ("source1: \t%g\t%g\t%g\t%g\t%g\n",source1[0],source1[1],source1[2],source1[3],source1[4]);
    printf ("source2: \t%g\t%g\t%g\t%g\t%g\n",source2[0],source2[1],source2[2],source2[3],source2[4]);
    printf ("target:  \t%g\t%g\t%g\t%g\t%g\n",target[0],target[1],target[2],target[3],target[4]);

    return 0;
}

/**************定义函数:两个源数组相加并且赋值给目标数组*****************/
void add (double source1[], double source2[], double target[], int n)
{
    int i;
    for (i = 0; i < n; i++)
        target[i] = source1[i] + source2[i];
}

这样就清楚些了吧。其实写出来牛逼的代码确实牛逼,但是做好注释方便维护则是素养!

10.

打算用指针的形式,不能老用数组,正好可以加强一下对指针的认识。

/*二维数组元素翻一番*/
#include <stdio.h>
#define ROWS 3
#define COLS 5
void twice (double (*)[COLS], int);
void display (double (*)[COLS], int);

int main (void)
{
    /*******************声明和初始化二维源数组********************/
    double array[ROWS][COLS] =
    {
        {1.1, 2.2, 3.3, 4.4, 5.5},
        {6.6, 7.7, 8.8, 9.9, 10.10},
        {11.11, 12.12, 13.13, 14.14, 15.15}
    };

    /*******************显示源数组,对源数组执行翻倍,显示翻倍后的数组********************/
    puts ("before: \n");
    display (array, 3);
    twice (array, 3);
    puts ("\nafter:\n");
    display (array, 3);

    return 0;
}

/*******************定义函数:翻倍源数组********************/
void twice (double (*p)[COLS], int rows)
{
    int i, j;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < COLS; j++)
            *(*(p+i)+j) = 2 *(*(*(p+i)+j));
    }
}

/*******************定义函数:显示二维数组********************/
void display (double (*p)[COLS], int rows)
{
    int i, j;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < COLS; j++)
            printf ("%g\t", p[i][j]);
        printf ("\n");
    }
}

11.

/*rain.c 针对若干年的降水量数据,计算年降水总量、年降水平均量,以及月降水平均量*/
#include <stdio.h>
#define MONTHS 12
#define YEARS 5
void RainPerYear(const float (*)[12]);    //注意使用const定义形参(因为实参都用const定义了,更别说形参了)
void RainAveMon(const float (*)[12]);

int main (void)
{
    /***********把数组初始化为2000到2004年的降水量数据****************/
    const float rain[YEARS][MONTHS] = //const声明和初始化数组可保护数据
    {
        {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}
    };

    /************计算和显示年总降水量*****************/
    RainPerYear(rain);
    /***********计算和显示月平均降水量****************/
    RainAveMon(rain);

    return 0;
}

/************定义函数:计算和显示年总降水量*****************/
void RainPerYear(const float (*rain)[12])
{
    int years,months;
    float totyear;

    printf("YEAR  RAIN:\n");
    for(years=0; years<YEARS; years++)
    {
        for(months=0,totyear=0; months<MONTHS; months++)
            totyear += *(*(rain+years)+months);
        printf("%4d %4.2f\n",2000+years,totyear);
    }
}

/***********定义函数:计算和显示月平均降水量****************/
void RainAveMon(const float (*rain)[12])
{
    int years,months;
    float totmonth;

    printf("\nmonth average:\n");
    printf("JUN  FEB  MAT  APR  MAY  JUN  JLY  AUG  SPT  OCT  NOV  DEC:\n");
    for(months=0; months<MONTHS; months++)
    {
        for(years=0,totmonth=0; years<YEARS; years++)
            totmonth += *(*(rain+years)+months);
        printf("%-4.1f ",totmonth/5);
    }
    printf("\nDone!\n");
}

12.

/*键盘输入储存3*5数组数据,计算平均,找最值,显示*/
#include <stdio.h>
#define COLS 5
void store (double p[][COLS], int row);
double average_row (double p[], int n);
double average_total (double p[][COLS], int row);
double max(double p[][COLS], int row);
//void display (double p[][COLS], int rows, double average0, double average1, double average2, double average_total, double max);

int main (void)
{
    int i;
    double array[3][COLS];
    double ave_row[3];
    double ave_tot;
    double max_tot;

    /**********************读入array的3个数集,每个数集5个数据***********************/
    store (array, 3);

    /****************************计算每个数集的平均值********************************/
    for(i=0; i<3; i++)
        ave_row[i] = average_row (array[0],5);

    /****************************计算整个数集的平均值********************************/
    ave_tot = average_total(array, 3);

    /****************************找出整个数集的最大值********************************/
    max_tot = max (array, 3);

    /**********************************输出结果**************************************/
    printf("ave_row[0],ave_row[1],ave_row[2] are: %g %g %g\n",ave_row[0],ave_row[1],ave_row[2]);
    printf("ave_total is %g:\n", ave_tot);
    printf("max is %g:\n", max_tot);
    printf("Done!\n");

    return 0;
}

/**********************定义函数:读入array的3个数集,每个数集5个数据***********************/
void store (double p[][COLS], int row)
{
    int i, j;
    printf ("Please enter 15 double numbers:\n");
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < COLS; j++)
            scanf ("%lf", *(p+i)+j);    // *(p+i)+j等同于&p[i][j]
    }
    puts ("Now you have finished.\n");
}

/****************************定义函数:计算每个数集的平均值********************************/
double average_row (double p[], int n)
{
    int i;
    double sum;
    for (i=0,sum=0; i<n; i++)
        sum += p[i];

    return sum/n;
}

/****************************定义函数:计算整个数集的平均值********************************/
double average_total(double p[][COLS], int row)
{
    int i,j;
    double total=0;
    for(i=0; i<row; i++)
    {
        for(j=0; j<COLS; j++)
            total += p[i][j];
    }

    return total/row/COLS;
}

/****************************定义函数:找出整个数集的最大值********************************/
double max(double p[][COLS], int row)
{
    int i,j;
    double m=p[0][0];

    for(i=0; i<row; i++)
        for(j=0; j<COLS; j++)
            m = (m>p[i][j]) ? m : p[i][j];

    return m;
}

终于搞定,不难,就是有点烦,嘿嘿

时间: 2024-10-08 10:09:00

C Primer Plus_第10章_数组和指针_编程练习的相关文章

C++自学笔记_数组和指针_《C++ Primer》

1.数据定义中的类型可以是内置数据类型或者类类型,除引用数据类型之外,数组元素的类型可是是任何数据类型.没有所有元素都是引用数据类型的数组. 2.数组的维数必须要用值大于等于1的表达式定义.此常量表达式只能包含整形字面值常量.枚举常量或者用常量表达式初始化的const对象,否则在编译阶段不知道数组的维数,对于一个非const对象,只有运行时才能获得它的值. const unsigned buf_size=512; int staff_size=27; char input_buffer[buf_

C语言学习_数组与指针2

数组其实是一种变相的指针,数组名同时也是指针,eg: CODE == &CODE[0]; 数组的加法: #include<stdio.h> #define SIZE 4 int main(void) { shortdates[SIZE]; short* pti; shortindex; doublebills[SIZE]; double* ptf; pti= dates;//把数组地址付给指针 ptf= bills; printf("%23s  %10s\n", &

第六章:数组、指针、与字符串

主要内容: 1.数组 2.指针 3.动态存储分配 4.指针与数组 5.指针与函数 6.字符串 内存地址: 1.内存地址的访问方式 通过变量名访问 通过地址访问 2.& var; //表示var在内存中的起始地址 void类型的指针就相当于一个hook(钩子),可以指向任何数据类型. 1.const 数据类型 * ptr //指向常量的指针 常量指针不可以改变所指对象的值,但是可以指向另外的对象(ptr本身可以改变). 2.数据类型 * const ptr //指针常量 指针本身不能改变,只能指向

第10章 网络安全(4)_网络层安全IPSec

5. 网络层安全IPSec 5.1 IPSec协议 (1)前面使用Outlook进行数字签名和数字加密是应用层实现的安全.安全套接字实现的安全是在应用层和传输层之间插入了一层来实现数据通信安全.而IPSec是网络层实现的安全.不需要应用程序的支持,只要配置通信双方的安全规则,传输层的数据传输单元就会被加密后封装到网络层,实现数据通信安全.IPSec工作在OSI模型的网络层. (2)IPSec主要的两个协议 ①鉴别首部(Authentication Header, AH)协议:提供源点鉴别和数据完

第10章 网络安全(1)_对称加密和非对称加密

1 网络安全概述 1.1 计算机网络面临的安全威协 (1)截获:攻击者从网络上窃听他人的通信内容,通常把这类攻击称为"截获".在被动攻击中,攻击者只是观察和分析某一个协议数据单元(PDU)而不干扰信息流. (2)篡改:攻击者篡改网络上传递的报文.这里包括彻底中断传递的报文,甚至把完全伪造的报文传送给接收方,这种攻击也有时也称为"更改报文流".如DNS劫持(域名劫持),安装黑客软件Cain可以进行验证. (3)恶意程序:是一种特殊的主动攻击形式.如计算机病毒.蠕虫.木

第10章 网络安全(2)_应用层安全(数字签名)

3. 应用层安全--数字签名 3.1 数字签名 (1)数字签名细节 ①A有一个密钥对(A的私钥SK和公钥PK).发送文件前先使用哈希函数生成该文件的摘要,再使用A的私钥加密摘要(这个过程称为签名,私钥持有者才能做这个操作). ②然后将加密后的摘要.A的公钥和文件(不加密该文件)一起发送给B. ③B收到后,将加了密的摘要使用A的公钥进行解密.同时B将收到的文件通过哈希函数生成一个摘要,比较这两个摘要,如果一样,就认为A的签名有效,说明该文件来源可靠,也没被修改过. (2)优点 ①能确定消息是否由发

第四章:数组与指针

1:初始化:内置类型的数组在函数体内没有初始化,在外是有的:而指针是都没有的. 2:null叫空字符—‘\0’为0--char--1个字节:NULL---叫空指针--为0--int---4个字节的. 3:数组是不能直接赋值与复制的:而容器可以: 4:size_t   ptrdiff_t 数组==== size_type difference_type 容器 5:void*是类型不确定:NULL是对象不确定,类型确定 6:超出末端指针,末端迭代器:用途一样,看门狗 7:const对象的指针不可以初

网易云课堂_艾叔:零基础一站式C语言|C程序设计精讲_章节12:指针_课时63指针操作数组

二维数组 #include <stdio.h> #include <stdlib.h> int main() { int age[2][4] = { 1,2,3,4,5,6,7,8 }; int* p = &(age[0][0]); int i = 0; int j = 0; for (i = 0; i < 2; i++) { for (j = 0; j < 4; j++) { printf("age[%d][%d] %p %d\n", i,

C Primer Plus 第5章 运算符、表达式和语句 编程练习

1. #include <stdio.h> const int S_PER_M = 60; int main(void) { int min, hour, lmin; printf("请输入分钟数: \n"); scanf("%d", &min); while(min > 0) { hour = min / S_PER_M; lmin = min % S_PER_M; printf("%d分钟 = %d小时, %d分钟\n&quo