C Primer Plus (第五版) 第十章 数组和指针 编程练习

第十章 数组和指针

编程练习

1.修改程序清单10.7中的程序rain,使它不使用数组下标,而是使用指针进行计算(程序中仍然需要声明并初始化数组)。

# include <stdio.h>
# define MONTHS 12
# define YEARS 5

int main(void)
{
	//把数组初始化为2000年到2004年的降水量数据
	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;

	//降水总量
	for (year = 0, total = 0; year < YEARS; year++)
	{
		for (month = 0, subtot = 0; month < MONTHS; month++)
		{
			subtot += *(*(rain + year) + month);
			//(rain+year)表示行地址增加,移动范围是一个数组大小。
			//*rain + year表示列地址增加,移动范围是一个int类型大小。
		}
		printf("%d年的总降水量:%.2f\n", 2010+year, subtot);
		total += subtot;
	}
	printf("%d年的平均降水量:%.2lf\n", YEARS, total / YEARS);
	printf("5年来每个月份的平均降水量:\n"  );
	printf(" 1月  2月  3月  4月  5月  6月  7月  8月  9月 10月 11月 12月\n");
	for (month = 0; month < MONTHS; month++)
	{
		for (year = 0, total = 0; year < YEARS; year++)
			total += *(*(rain + year) + month);
		printf("%4.1f ", total / YEARS);
	}
	putchar(‘\n‘);

	return 0;
}

2.编写一个程序,初始化一个double数组,然后把数组内容复制到另外两个数组(3个数组都需要在主程序中声明)。

制作第一份拷贝的函数使用数组符号。制作第二份拷贝的函数使用指针符号,并使用指针的增量操作。

把目标数组名和要复制的元素数目做为参数传递给函数。也就是说,如果给定了下列声明,函数调用应该如下面所示:

double  source [5]={1.1,  2.2,  3.3,  4.4,  5.5};

double  targetl[5];

double  target2 [5];

copy_arr (source, target1, 5);

copy_ptr (source, target1,5);

#include <stdio.h>

void copy_ptr(double * source, double * target, int n);
void copy_arr(double source[], double target[], int n);
void show(double *, int);

int main(void)
{
	double source[5] = { 1.1, 2.2, 3.3, 4.4, 5.5 };
	double target1[5] = { 0 };
	double target2[5] = { 0 };

	copy_arr(source, target1, 2);
	copy_ptr(source, target2, 4);

	printf("source: "); show(source, 5);
	printf("target1: "); show(target1, 5);
	printf("target2: "); show(target2, 5);

	return 0;
}

void copy_ptr(double * source, double * target, int n)
{
	int i;
	for (i = 0; i < n; i++)
		*target++ = *source++;
}
void copy_arr(double source[], double target[], int n)
{
	int i;
	for (i = 0; i < n; i++)
		target[i] = source[i];
}

void show(double * a, int n)
{
	int i;
	for (i = 0; i < n; i++)
		printf("%.2lf ", a[i]);
	printf("\n");
}

3.编写一个函数,返回一个int数组中存储的最大数值,并在一个简单的程序中测试这个函数。

#include <stdio.h>

int max(int *, int);

int main(void)
{
	int a[5] = { 2, 4, 1, 0, -3 };

	printf("数组中最大的值:%d\n", max(a, 5));

	return 0;
}

int max(int * a, int n)
{
	int i, temp = a[0];
	for (i = 1; i < n; i++)
	{
		if (temp < a[i])
			temp = a[i];
	}	

	return temp;
}

4.编写一个函数,返回一个double数组中存储的最大数值的索引,并在一个简单程序中测试这个函数。

#include <stdio.h>

int max(double *, int);

int main(void)
{
	double a[5] = { 25.6, 41.2, 13.0, 0.5, -0.03 };

	printf("数组中最大值的索引:%d\n", max(a, 5));

	return 0;
}

int max(double * a, int n)
{
	int i, temp = 0;
	for (i = 1; i < n; i++)
	{
		if (a[temp] < a[i])
		{
			temp = i;
		}
	}	

	return temp;
}

5.编写一个函数,返回一个double数组中最大的和最小的数之间的差值,并在一个简单的程序中测试这个函数。

#include <stdio.h>

double sub(const double *, int);

int main(void)
{
	double a[5] = { 25.6, 41.2, 13.0, 0.5, 0.03 };

	printf("数组中最大值和最小值的差值:%.2lf\n", sub(a, 5));

	return 0;
}

double sub(const double * a, int n)
{
	int i, max = 0, min = 0;
	for (i = 1; i < n; i++)
	{
		if (a[max] < a[i])
			max = i;
		if (a[min] > a[i])
			min = i;
	}	

	return a[max] - a[min];
}

6.编写一个程序,初始化一个二维double数组,并利用练习2中的任一函数来把这个数组复制到另一个二维数组(因为二维数组是数组的数组,所以可以使用处理一维数组的函数来复制数组的每个子数组)。

#include <stdio.h>

void copy_ptr(double * source, double * target, int n);

int main(void)
{
	double source[2][5] = {
		{ 25.6, 41.2, 13.0, 0.5, 0.03 },
		{ 12.0, 23.0, -12.0, 3.0, 0.9 }
	};
	double target[2][5] = { 0 };

	copy_ptr(source[0], target[0], 8);

	printf("target: ");
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 5; j++)
			printf("%.2lf ", target[i][j]);
	}
	printf("\n");

	return 0;
}

void copy_ptr(double * source, double * target, int n)
{
	int i;
	for (i = 0; i < n; i++)
		*target++ = *source++;
}

7.利用练习2中的复制函数,把一个包含7个元素的数组内第3到第5元素复制到一个包含3个元素的数组中,函数本身不需要修改,只需要选择合适的实际参数(实际参数不需要是数组名和数组大小,而只需是数组元素的地址和需要复制的元素数目)

#include <stdio.h>

void copy_ptr(double * source, double * target, int n);

int main(void)
{
	double source[7] = 
		{ 25.6, 41.2, 13.0, 0.5, 0.03, 3.0, 0.9 };
	double target[3] = { 0 };

	copy_ptr(&source[2], target, 3);

	printf("target: ");
	for (int i = 0; i < 3; i++)
		printf("%.2lf ", target[i]);

	printf("\n");

	return 0;
}

void copy_ptr(double * source, double * target, int n)
{
	int i;
	for (i = 0; i < n; i++)
		*target++ = *source++;
}

8.编写一个程序,初始化一个3*5的二维double数组,并利用一个基于变长数组的函数把该数组复制到别一个二维数组。还要编写一个基于变长数组的函数来显示两个数组的内容。这两个函数应该能够处理任意的N*M数组(如果没有可支持变长数组的编译器,就使用传统C中处理N*5数组的函数方法)。

#include <stdio.h>

void copy_ptr(int x, int y, double source[x][y], double target[x][y]);
void show(int x, int y, double source[x][y], double target[x][y]);
int main(void)
{
	double source[3][5] = {
		{ 25.6, 41.2, 13.0, 0.5, 0.03},
		{ 21.0, 32.0, 10.9, 5.6, 4.2 },
		{ 41.2, 13.0, 0.5, 2.0, 32.1 }
	};
	double target[3][5] = { 0 };

	copy_ptr(3, 5, source, target);

	printf("source: \n"); 
	show(3, 5, source, target);
	printf("target: \n");
	show(3, 5, source, target);

	return 0;
}

/* VC2013不支持变长数组,用gcc编译可通过 */
void copy_ptr(int x, int y, double source[x][y], double target[x][y])
{
	int i, j;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 5; j++)
			target[i][j] = source[i][j];
	}

}

void show(int x, int y, double source[x][y], double target[x][y])
{
	int i, j;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 5; j++)
			printf("%.2lf ", target[i][j]);
		printf("\n");
	}
}

9.编写一个函数,把两个数组内的相应元素相加,结果存储到第3个数组内。也就是说,如果数组l具有值2、4、5、8,数组2具有值1、0、4、6,则函数对数组3赋值为3、4、9、140函数的参数包括3个数组名和数组大小。并在一个简单的程序中测试这个函数。

#include <stdio.h>
#define LEN 5
void add(const int *, const int *, int *, int);
void show(int *, int);
int main(void)
{
	int array1[LEN] = { 1, 3, 6, 8, 2 };
	int array2[LEN] = { 2, 4, 7, 4, 9 };
	int array3[LEN] = { 0 };

	add(array1,array2,array3,LEN);

	printf("array1: \n"); show(array1, LEN);
	printf("array2: \n"); show(array2, LEN);
	printf("array3: \n"); show(array3, LEN);

	return 0;
}

void add(const int *a1, const int *a2, int *a3, int n)
{
	for (int i = 0; i < n; i++)
		a3[i] = a1[i] + a2[i];

}

void show(int *a, int n)
{
	for (int i = 0; i < n; i++)
		printf("%5d ", a[i]);
	printf("\n");
}

10.编写一个程序,声明一个3x5的数组并初始化,具体数值可以随意。程序打印出数值,然后数值翻1番,接着再次打印出新值。编写一个函数来显示数组的内容,再编写另一个函数执行翻倍功能。数组名和数组行数作为参数由程序传递给函数

#include <stdio.h>
void add(int array[][5], int c);
void show(int (*a)[5], int);
int main(void)
{
	int array[3][5] ={
		{ 1, 3, 6, 8, 2 },
		{ 2, 4, 7, 4, 9 },
		{ 3, 2, 1, 2, 3 }
	};

	printf("array: \n"); show(array, 3);
	add(array, 3);
	printf("array: \n"); show(array, 3);

	return 0;
}

void add(int array[][5], int c)
{
	for (int i = 0; i < c; i++)
	for (int j = 0; j < 5; j++)
		array[i][j] *= 2;
}

void show(int (*a)[5], int n)
{
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < 5; j++)
			printf("%5d ", a[i][j]);
		printf("\n");
	}
}

11.重写程序清单10.7的程序rain,main()中的主要功能改为由函数来执行。(针对若干年的降水量数据,计算年降水总量、年降水平均量,以及月降水平均量)

# include <stdio.h>
# define MONTHS 12
# define YEARS 5
float year_total(float a[][MONTHS], int n);		//五年总降水量
float month_sub(float a[][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 }
	};

	year_total(rain, YEARS);
	month_sub(rain, YEARS);

	return 0;
}
float year_total(float a[][MONTHS], int n)
{
	int i, j;
	float total_y, total;
	for (i = 0, total = 0; i < n; i++)
	{
		for (j = 0, total_y = 0; j < MONTHS; j++)
			total_y += a[i][j];
		printf("%d年总降水量:%.1f\n", 2010 + i, total_y);
		total += total_y;
	}
	printf("%d年-%d年平均降水量:%.1f\n", 2010, 2010 + i-1, total / YEARS);

	return total;
}

float month_sub(float a[][MONTHS], int n)
{
	int i, j;
	float total;
	for (i = 0; i < MONTHS; i++)
	{
		for (j = 0, total = 0; j < n; j++)
			total += a[j][i];
		printf("%d年-%d年 %d月的平均降水量%.1f\n", 2010, 2010+j-1, i+1, total/YEARS);
	}

	return total;
}

12.编写…个程序,提示用户输入3个数集,每个数集包括5个double值。程序应当实现下列所有功能:

a.把输入信息存储到一个3x5的数组中

b.计算出每个数集(包含5个数值)的平均值

c.计算所有数值的平均数

d.找出这15个数中的最大值.

e.打印出结果

每个任务需要用一个单独的函数来实现(使用传统C处理数组的方法)。对于任务b,需要编写计算并返回一维数组平均值的函数,循环3次调用该函数来实现任务b。

对于其他任务,函数应当把整个数组做为参数,并且完成任务c和d的函数应该向它的调用函数返回答案。

#include <stdio.h>

void input(double(*a)[5], int n);
double sub(const double *a, int n);
double sub_total(const double a[][5], int n);
double max(const double a[][5], int n);
void show(const double a[][5], int n);

int main(void)
{
	double array[3][5];
	int i;

	input(array, 3);
	for (i = 0; i < 3; i++)
		printf("第%d个数集的平均值:%.2lf\n",i+1, sub(array[i], 5));
	printf("所有数的平均值:%.2lf\n", sub_total(array, 3));
	printf("所有数中最大的数:%.2lf\n", max(array, 5));
	printf("整个数集:\n");
	show(array, 3);

	return 0;
}
void input(double(*a)[5], int n)
{
	int i, j;
	for (i = 0; i < n; i++)
	{
		printf("请输入第%d个数集中的5个值:", i+1);
		for (j = 0; j < 5; j++)
			scanf("%lf", &a[i][j]);
	}
}
double sub(const double *a, int n)
{
	int i;
	double total = 0;
	for (i = 0; i < n; i++)
		total += a[i];

	return total / n;
}
double sub_total(const double a[][5], int n)
{
	int i, j;
	double total = 0;
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < 5; j++)
			total += a[i][j];
	}

	return total / (n * 5);
}
double max(const double a[][5], int n)
{
	int i, j;
	double temp = a[0][0];
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < 5; j++)
		if (temp < a[i][j])
			temp = a[i][j];
	}

	return temp;
}
void show(const double a[][5], int n)
{
	int i, j;
	double max = a[0][0];
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < 5; j++)
			printf("%.2lf ", a[i][j]);
		printf("\n");
	}
}

13.下面是两个函数原型:

void show(double ar[], int n); //n是元素数

void show2(double ar2[][3], int n); //n是行数

a,编写一个函数调用,把包含数值8、3、9和2的复合文字传递给函数shows()。

b,编写一个函数调用,把包含2行3列数值的复合文字传递给函数show2(),其中第一行为8、3、9;第二行为5、4、1。

#include <stdio.h>

void show(double ar[], int n);
void show2(double ar2[][3], int n);

int main(void)
{
	show((double[]){ 8, 3, 9, 2 }, 4);
	show2((double[][3]){ { 8, 3, 9 }, { 5, 4, 1 } }, 2);

	return 0;
}
void show(double ar[], int n)
{
	int i;
	for (i = 0; i < n; i++)
		printf("%.2lf ", ar[i]);
	printf("\n");
}
void show2(double ar2[][3], int n)
{
	int i, j;
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < 3; j++)
			printf("%.2lf ", ar2[i][j]);
		printf("\n");
	}
}
时间: 2024-10-27 13:30:13

C Primer Plus (第五版) 第十章 数组和指针 编程练习的相关文章

C++ Primer【第五版】习题参考答案——第六章(函数)

本系列文章会不断更新,但是时间不能保证.另外基本上都是自己做的答案,仅供参考,如果有疑问欢迎交流. #include <iostream> #include <initializer_list> using namespace std; int test_Ex_6_27(std::initializer_list<int> li); int main() { cout << test_Ex_6_27({23,78,89,76,90}) << en

c++ primer(第五版)学习笔记及习题答案代码版(第十四章)重载运算与类型转换

笔记较为零散,都是自己不熟悉的知识点. 习题答案至于一个.h 和.cc 中,需要演示某一题直接修改 #define NUM****, 如运行14.30题为#define NUM1430: Alice Emma has long flowing red hair. Her Daddy says when the wind blows through her hair, it looks almost alive, like a fiery bird in flight. A beautiful f

C++ Primer【第五版】习题参考答案——第五章(语句)

#include <iostream> #include <vector> #include <string> using namespace std; /******************************************************************* Ex_5_1: 空语句就是只含有一个分号的语句. 如果在程序的某个地方,语法上要求有一条语句,但是逻辑上不需要, 这时就需要一条空语句. Ex_5_2: 块就是由花括号包围的复合语句

c++ primer(第五版)学习笔记及习题答案代码版(第十一章)关联容器

笔记较为零散,都是自己不熟悉的知识点. 习题答案至于一个.cc 中,包含Chapter7.h头文件,读入文件包括./test ./rules .需要演示某一题直接修改 #define NUM****, 如运行11.23题为#define NUM1123: chapter 11 1.  关联容器不支持顺序容器的位置相关的操作,例如push_front或push_back.原因是关联容器中元素是根据关键字存储的,这些操作对 关联容器没有意义.而且关联容器也不支持构造函数或插入操作这些接收一个元素值和

c++ primer(第五版)学习笔记及习题答案代码版(第六章)函数

笔记较为零散,都是自己不熟悉的知识点. 习题答案至于一个.cc 中,编译需要包含Chapter6.h头文件. 需要演示某一题直接修改 #define NUM***, 如运行6.23题为#define NUM623: chapter 6 1. 形参初始化的机理与变量初始化一样. 当形参是引用类型时,它对应的实参被引用传递或者函数被传引用调用. 2. const和实参 void fcn(const int i){ /*fcn能够读取i,但是不能向i写值*/} void fcn(int i){ /*.

C++ Primer(第五版) 笔记 C01-02

C01 ++val; 优于 val++; 对数量不定的输入数据:while(cin>>value)... 遇到无效的输入或eof后,cin变为无效状态,条件变为假. 来自标准库的头文件用<>包围,不属于标准库的用""包围. 文件重定向工作:exename.exe <infile >outfile 点运算符:左侧运算对象是类类型的,右侧是该类型的成员. 参数 = 实参 = 值,形参指出调用函数可使用什么实参. 定义在函数内部的内置类型通常不初始化. C

《C++Primer》第五版习题详细答案--目录

作者:cosefy ps: 答案是个人学习过程的记录,仅作参考. <C++Primer>第五版习题答案目录 第一章:引用 第二章:变量和基本类型 第三章:字符串,向量和数组 第四章:表达式 原文地址:https://www.cnblogs.com/cosefy/p/12180771.html

c++ primer plus(第6版)中文版 第十二章编程练习答案

第十二章编程练习答案 12.1根据以下类声明,完成类,并编小程序使用它 //12.1根据以下类声明,完成类,并编小程序使用它 #include <iostream> #include <cstring> using namespace std; class Cow{ char name[20]; char * hobby; double weight; public: Cow(); Cow(const char * nm, const char * ho, double wt);

C primer plus 第五版十二章习题

看完C prime plus(第五版)第十二章,随带完成了后面的习题. 1.不使用全局变量,重写程序清单12.4的程序. 先贴出12.4的程序,方便对照: 1 /* global.c --- 使用外部变量 */ 2 #include <stdio.h> 3 int units = 0; //一个外部变量 4 void critic(void); 5 int main(void) 6 { 7 extern int units; 8 9 printf ("How many pounds