CPrimerPlus学习(十):数组和指针/*指针操作/编程练习

初始化数组

int powers[8] = {1,2,4,6,8,16,32,64}; 
/* day_mon1.c -- 打印每个月的天数 */

#include <stdio.h>

#define MONTHS 12

int main(void)
{
	int days[MONTHS] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	int index;

	for (index  = 0; index < MONTHS; index++)
		printf("Month %2d has %2d days.\n", index + 1, days[index]);

	return 0;
}

/*
Month  1 has 31 days.
Month  2 has 28 days.
Month  3 has 31 days.
Month  4 has 30 days.
Month  5 has 31 days.
Month  6 has 30 days.
Month  7 has 31 days.
Month  8 has 31 days.
Month  9 has 30 days.
Month 10 has 31 days.
Month 11 has 30 days.
Month 12 has 31 days.
*/
注意:使用const声明数组
	有时需要把数组设置为只读。
	这样,程序只能从数组中检索值,不能把新值写入数组。
	要创建只读数组,应该用const声明和初始化数组。
	因此, 程序清单10.1中初始化数组应改成:
		const int days[MONTHS] = {31,28,31,30,31,30,31,31,30,31,30,31};
	这样修改后,程序在运行过程中就不能修改该数组中的内容。
	和普通变量一样,应该使用声明来初始化 const 数据,因为一旦声明为 const,便不能再给它赋值。

如果不初始化数组, 数组元素和未初始化的普通变量一样,其中储存的都是垃圾值;
但是,如果部分初始化数组,剩余的元素就会被初始化为0。

如果初始化列表的项数多于数组元素个数,编译器将其视为错误。
但是,可以省略方括号中的数字,让编译器自动匹配数组大小和初始化列表中的项数(见程序清单10.4)。
	const int days[] = { 31, 28, 31, 30, 31, 30, 31, 31,  30, 31 };
	int index;
	for (index = 0;index < sizeof days / sizeof days[0]; index++)

指定初始化器

int arr[6] = {[5] = 212}; // 把arr[5]初始化为212
//对于一般的初始化,在初始化一个元素后,未初始化的元素都会被设置为0。

int stuff[] = {1, [6] = 23};     
int staff[] = {1, [6] = 4, 9, 10}; 
//编译器会把数组的大小设置为足够装得下初始化的值。
//所以,stuff数组有7个元素,编号为0~6;
//而staff数组的元素比stuff数组多两个(即有9个元素)。

多维数组

float rain[5][12]; // rain是一个内含5个元素的数组
这说明数组rain有5个元素,
至于每个元素的情况,要查看声明的其余部分:
floatrain[5][12] ; // 一个内含12个float类型元素的数组
这说明每个元素的类型是float[12],
也就是说,rain的每个元素本身都是一个内含12个float类型值的数组。
const float rain[5][12] =
{
	{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}
};

/*
如果第1个列表中只有10个数,则只会初始化数组第1行的前10个元素,而最后两个元素将被默认初始化为0。
如果某列表中的数值个数超出了数组每行的元素个数,则会出错,但是这并不会影响其他行的初始化。
初始化时也可省略内部的花括号,只保留最外面的一对花括号。
*/

指针和数组

数组名是数组首元素的地址。
也就是说,如果flizny是一个数组,下面的语句成立:
			flizny == &flizny[0]; // 数组名是该数组首元素的地址
flizny和&flizny[0]都表示数组首元素的内存地址(&是地址运算符)。 
两者都是常量,在程序的运行过程中,不会改变。
但是,可以把它们赋值给指针变量,然后可以修改指针变量的值,如程序清单10.8所示。
注意指针加上一个数时,它的值发生了什么变化(转换说明%p通常以十六进制显示指针的值)。
//程序清单10.8 pnt_add.c程序
// pnt_add.c -- 指针地址

#include <stdio.h>

#define SIZE 4

int main(void)
{
	short dates[SIZE];
	short * pti;
	short index;
	double bills[SIZE];
	double * ptf;

	pti = dates; //把数组地址赋给指针
	ptf = bills;
	printf("%23s %15s\n", "short", "double");

	for (index = 0; index < SIZE; index++)
		printf("pointers + %d: %10p %10p\n", index, pti + index, ptf + index);

	return 0;
}

/*
下面是该例的输出示例:
short        double
pointers + 0: 0x7fff5fbff8dc 0x7fff5fbff8a0
pointers + 1: 0x7fff5fbff8de 0x7fff5fbff8a8
pointers + 2: 0x7fff5fbff8e0 0x7fff5fbff8b0
pointers + 3: 0x7fff5fbff8e2 0x7fff5fbff8b8

第2行打印的是两个数组开始的地址,下一行打印的是指针加1后的地址,以此类推。
注意,地址是十六进制的,因此dd比dc大1,a1比a0大1。
但是,显示的地址是怎么回事?

0x7fff5fbff8dc + 1是否是0x7fff5fbff8de?
0x7fff5fbff8a0 + 1是否是0x7fff5fbff8a8?

我们的系统中,地址按字节编址,short类型占用2字节,double类型占用8字节。
在C中,指针加1指的是增加一个存储单元。
对数组而言,这意味着把加1后的地址是下一个元素的地址,而不是下一个字节的地址(见图 10.3)。
这是为什么必须声明指针所指向对象类型的原因之一。
只知道地址不够,因为计算机要知道储存对象需要多少字节
(即使指针指向的是标量变量,也要知道变量的类型,否则*pt就无法正确地取回地址上的值)。
*/

在这里插入图片描述

dates + 2 == &date[2]    // 相同的地址
*(dates + 2) == dates[2]  // 相同的值

*(dates + 2) // dates第3个元素的值
*dates + 2  // dates第1个元素的值加2
等价代码形式:

int sum(int *ar, int n)
{
// 其他代码已省略
}

int sum(int ar[], int n);
{
//其他代码已省略
}

程序清单10.12 order .c程序
/* order.c -- 指针运算中的优先级 */

#include <stdio.h>

int data[2] = { 100, 200 };
int moredata[2] = { 300, 400 };

int main(void)
{
	int * p1, *p2, *p3;
	
	p1 = p2 = data;
	p3 = moredata;
	
	printf(" *p1 = %d,  *p2 = %d,  *p3 = %d\n",*p1, *p2, *p3);
	printf("*p1++ = %d, *++p2 = %d, (*p3)++ = %d\n",*p1++, *++p2, (*p3)++);
	printf(" *p1 = %d,  *p2 = %d,  *p3 = %d\n",*p1, *p2, *p3);
	
	return 0;
}
/*
下面是该程序的输出:
*p1 = 100,  *p2 = 100,   *p3 = 300
*p1++ = 100, *++p2 = 200, (*p3)++ = 300
*p1 = 200,  *p2 = 200,   *p3 = 301
只有(*p3)++改变了数组元素的值,其他两个操作分别把p1和p2指向数组的下一个元素。
*/

指针操作

//程序清单10.13 ptr_ops.c程序
// ptr_ops.c -- 指针操作

#include <stdio.h>

int main(void)
{
	int urn[5] = { 100, 200, 300, 400, 500 }; //声明1个数组并初始化
	int * ptr1, *ptr2, *ptr3; //声明3个指针变量

	ptr1 = urn; // 把一个地址赋给指针ptr1(urn第一个元素的地址)
	ptr2 = &urn[2]; // 把一个地址赋给指针ptr2(urn第3个元素的地址)

	// 解引用指针,以及获得指针的地址
	printf("pointer value, dereferenced pointer, pointer address:\n");
	printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %p\n", ptr1, *ptr1, &ptr1);
	//ptr1 = 0x7fff5fbff8d0, *ptr1 = 100, &ptr1 = 0x7fff5fbff8c8
	//ptr1为元素urn[0]的地址
	//*ptr1为元素urn[0]的值
	//&ptr1为这个指针指向的地址

	//和所有变量一样,指针变量也有自己的地址和值。
	//对指针而言, &运算符给出指针本身的地址。
	//本例中,ptr1储存在内存编号为 0x7fff5fbff8c8 的地址上,该存储单元储存的内容是0x7fff5fbff8d0,即urn的地址。
	//因此&ptr1是指向ptr1的指针,而ptr1是指向utn[0]的指针。

	// 指针加法
	ptr3 = ptr1 + 4; //ptr1为一个指针,存储一个地址,地址加4
	//整数会和指针所指向类型的大小(以字节为单位)相乘,然后把结果与初始地址相加。
	//在C中,指针加1指的是增加一个存储单元。
	//对数组而言,这意味着把加1后的地址是下一个元素的地址,而不是下一个字节的地址。
	//因此 ptr1 + 4 与 &urn[4] 等价
	printf("\nadding an int to a pointer:\n");
	printf("ptr1 + 4 = %p, *(ptr1 + 4) = %d\n", ptr1 + 4, *(ptr1 + 4));
	//ptr1 + 4 = 0x7fff5fbff8e0, *(ptr1 + 4) = 500
	//ptr + 4为元素urn[4]的地址
	//*(ptr + 4)为元素urn[4]的值

	ptr1++;// 递增指针
	printf("\nvalues after ptr1++:\n");
	printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %p\n", ptr1, *ptr1, &ptr1);
	//ptr1 = 0x7fff5fbff8d4, *ptr1 = 200, &ptr1 = 0x7fff5fbff8c8
	//递增后ptr1表示下一个元素urn[1]的地址,加*表示值,加&表示该指针指向的地址

	ptr2--;// 递减指针
	printf("\nvalues after --ptr2:\n");
	printf("ptr2 = %p, *ptr2 = %d, &ptr2 = %p\n", ptr2, *ptr2, &ptr2);
	//ptr2 = 0x7fff5fbff8d4, *ptr2 = 200, &ptr2 = 0x7fff5fbff8c0
	//ptr2原来是表示urn[2]的地址,递减后表示urn[1]的地址

	--ptr1;// 恢复为初始值
	++ptr2;// 恢复为初始值
	printf("\nPointers reset to original values:\n");
	printf("ptr1 = %p, ptr2 = %p\n", ptr1, ptr2);
	//ptr1 = 0x7fff5fbff8d0, ptr2 = 0x7fff5fbff8d8

	// 一个指针减去另一个指针
	printf("\nsubtracting one pointer from another:\n");
	printf("ptr2 = %p, ptr1 = %p, ptr2 - ptr1 = %td\n", ptr2, ptr1, ptr2 - ptr1);
	//ptr2 = 0x7fff5fbff8d8, ptr1 = 0x7fff5fbff8d0, ptr2 - ptr1 = 2
	//指针相减表示元素urn[0]与urn[2]的距离,是指相隔2个int,而不是2字节
	/*
	可以计算两个指针的差值。
	通常,求差的两个指针分别指向同一个数组的不同元素,通过计算求出两元素之间的距离。
	差值的单位与数组类型的单位相同。
	例如,程序清单10.13的输出中,ptr2 - ptr1得2,
	意思是 这两个指针所指向的两个元素相隔两个int,而不是2字节。
	只要两个指针都指向相同的数组(或者其中一个指针指向数组后面的第1个地址),C都能保证相减运算有效。
	如果指向两个不同数组的指针进行求差运算可能会得出一个值,或者导致运行时错误。
	*/

	// 一个指针减去一个整数
	printf("\nsubtracting an int from a pointer:\n");
	printf("ptr3 = %p, ptr3 - 2 = %p\n", ptr3, ptr3 - 2);
	//ptr3 = 0x7fff5fbff8e0, ptr3 - 2 = 0x7fff5fbff8d8
	/*
	可以使用-运算符从一个指针中减去一个整数。
	指针必须是第1个运算对象,整数是第2个运算对象。
	该整数将乘以指针指向类型的大小(以字节为单位),然后用初始地址减去乘积。
	所以ptr3 - 2与 &urn[2]等价,因为ptr3指向的是&arn[4]。
	如果相减的结果超出了初始指针所指向数组的范围,计算结果则是未定义的。
	除非正好超过数组末尾第一个位置,C保证该指针有效。
	*/

	/*
	比较:使用关系运算符可以比较两个指针的值,前提是两个指针都指向相同类型的对象。

	注意,这里的减法有两种。
	可以用一个指针减去另一个指针得到一个整数,或者用一个指针减去一个整数得到另一个指针。
	*/

	return 0;
}

编程练习

1、
修改程序清单10.7的rain.c程序,用指针进行计算(仍然要声明并初始化数组)。

//程序清单10.7 rain.c程序
/* rain.c -- 计算每年的总降水量、年平均降水量和5年中每月的平均降 水量 */

#include <stdio.h>

#define MONTHS 12 // 一年的月份数
#define YEARS 5 // 年数

int main(void)
{
	// 用2010~2014年的降水量数据初始化数组
	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];
			//改成指针 subtot += *(*(rain + year) + month);
			printf("%5d %15.1f\n", 2010 + year, subtot);
		total += subtot; // 5年的总降水量
	}

	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++)
	{   // 每个月,5年的总降水量
		for(year = 0, subtot = 0;year < YEARS;year++)
			subtot += rain[year][month];
			//改成指针 subtot += *(*(rain + year) + month);
			printf("%4.1f ", subtot / YEARS);
	}
	printf("\n");

	return 0;
}

/*
下面是该程序的输出:
YEAR   RAINFALL  (inches)
2010        32.4
2011        37.9
2012        49.8
2013        44.0
2014        32.9
The yearly average is 39.4 inches.
MONTHLY AVERAGES:
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
7.3 7.3 4.9 3.0 2.3 0.6 1.2 0.3 0.5 1.7 3.6 6.7
*/

2、
编写一个程序,初始化一个double类型的数组,然后把该数组的内容 拷贝至3个其他数组中(在main()中声明这4个数组)。使用带数组表示法的函数进行第1份拷贝。
使用带指针表示法和指针递增的函数进行第2份拷贝。
把目标数组名、源数组名和待拷贝的元素个数作为前两个函数的参数。
第3个函数以目标数组名、源数组名和指向源数组最后一个元素后面的元素的指针。
也就是说,给定以下声明,则函数调用如下所示:
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);

#include <stdio.h>

void copy_arr();
void copy_ptr();
void copy_ptrs();

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];
	
	for (int i = 0; i < 5; i++)
	{
		printf("source[%d]  = %.1lf ", i, source[i]);
	}
	printf("\n");

	copy_arr(target1, source, 5);
	copy_ptr(target2, source, 5);
	copy_ptrs(target3, source, source + 5);

	return 0;
}

void copy_arr(double x[], double y[], int z)
{
	for (int i = 0; i < z; i++)
	{
		x[i] = y[i];
		printf("target1[%d] = %.1lf ", i, x[i]);
	}
	printf("\n");
}

void copy_ptr(double * x, double * y, int z)
{
	for (int i = 0; i < z; i++)
	{
		*(x + i) = *(y + i);
		printf("target2[%d] = %.1lf ", i, x[i]);
	}
	printf("\n");
}

void copy_ptrs(double * x, double * y, double * z)
{
	while (y < z)
	{
		*x = *y;
		x++;
		y++;
	}

	for (int i = 0; i < 5; i++)
	{
		printf("target3[%d] = %.1lf ", i, *(x+1+i));
	}
	printf("\n");
}

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

#include <stdio.h>

int max();

int main(void)
{
	int a[7] = { 19,97,12,26,3,9,8 };

	int m;
	m = max(a);
	printf("max = %d\n", m);

	return 0;
}

int max(int * x)
{
	int m = 0;

	for (int i = 0; i < 7; i++)
	{
		if (m < x[i])
			m = x[i];
	}

	return m;
}

4、
编写一个函数,返回储存在double类型数组中最大值的下标,
并在一个简单的程序中测试该函数。

#include <stdio.h>

int max();

int main(void)
{
	int a[7] = { 19,97,12,26,3,9,8 };

	int m;
	m = max(a);
	printf("max = %d\n", m);

	return 0;
}

int max(int * x)
{
	int m = 0;
	int z;

	for (int i = 0; i < 7; i++)
	{
		if (m < x[i])
		{
			m = x[i];
			z = i;
		}
	}

	return z;
}

5、
编写一个函数,返回储存在double类型数组中最大值和最小值的差值,
并在一个简单的程序中测试该函数。

#include <stdio.h>

int max();

int main(void)
{
	int a[7] = { 19,97,12,26,3,9,8 };

	int m;
	m = max(a);
	printf("max = %d\n", m);

	return 0;
}

int max(int * x)
{
	int m = 0;
	int z;

	for (int i = 0; i < 7; i++)
	{
		if (m < x[i])
			m = x[i];
	}

	int c = m;
	for (int i = 0; i < 7; i++)
	{
		if (c > x[i])
			c = x[i];
	}

	int s = m - c;

	return s;
}

6、
编写一个函数,把double类型数组中的数据倒序排列,
并在一个简单的程序中测试该函数。

#include<stdio.h>

#define SIZE 8

void revert_arr(double arr[], int n);

int main()
{
	int i;
	double arr[SIZE];

	printf("Before enter %d double numbers:\n", SIZE);
	for (i = 0; i < SIZE; i++)
		scanf("%lf", &arr[i]);

	printf("Before revert, the array is:\n");
	for (i = 0; i < SIZE; i++)
	{
		printf(" %.2lf", arr[i]);
	}
	printf("\n");

	revert_arr(arr, SIZE);

	printf("After revert, the array is:\n");
	for (i = 0; i < SIZE; i++)
	{
		printf(" %.2lf", arr[i]);
	}
	printf("\n");

	return 0;
}

void revert_arr(double arr[], int n)
{
	int i;

	for (i = 0; i < n / 2; i++)
	{
		double x = arr[i];
		arr[i] = arr[n - 1 - i];
		arr[n - 1 - i] = x;
	}
}

7、
编写一个程序,初始化一个double类型的二维数组,
使用编程练习2中的一个拷贝函数把该数组中的数据拷贝至另一个二维数组中
(因为二维数组是数组的数组,所以可以使用处理一维数组的拷贝函数来处理数组中的每个子数组)。

#include <stdio.h>

void copy_arr();

int main(void)
{
	double source[3][4] = 
	{
		{1,2,3,4},
		{5,6,7,8},
		{9,0,1,2}
	};
	double target1[3][4];

	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			printf("source[%d][%d]  = %.1lf ", i, j,source[i][j]);
		}
		printf("\n");
	}
	printf("\n");

	printf("\n");
	copy_arr(target1, source, 3,4);

	return 0;
}

void copy_arr(double x[][4], double y[][4], int m,int n)  //多维不能写成x[][]
{
	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < n; j++)
		{
			x[i][j] = y[i][j];
			printf("target1[%d][%d] = %.1lf ", i,j, x[i][j]);
		}
		printf("\n");
	}
	printf("\n");
}

8、
使用编程练习2中的拷贝函数,
把一个内含7个元素的数组中第3~第5 个元素拷贝至内含3个元素的数组中。
该函数本身不需要修改,只需要选择合适的实际参数(实际参数不需要是数组名和数组大小,只需要是数组元素的地址和待处理元素的个数)。

/* Programming Exercise 10-8 */ 

#include <stdio.h> 

#define LEN1 7  
#define LEN2 3 

void copy_arr(int ar1[], const int ar2[], int n);
void show_arr(const int[], int);

int main(void) 
{ 
	int orig[LEN1] = { 1,2,3,4,5,6,7 };  
	int copy[LEN2];    

	show_arr(orig, LEN1);   
	copy_arr(copy, orig + 2, LEN2);   
	show_arr(copy, LEN2);      
	
	return 0; 
}

void copy_arr(int ar1[], const int ar2[], int n)
{ 
	int i;   

	for (i = 0; i < n; i++)    
		ar1[i] = ar2[i]; 
}

void show_arr(const int ar[], int n)
{ 
	int i;     

	for (i = 0; i < n; i++)     
		printf("%d ", ar[i]);    
	putchar('\n'); 
}

9、
编写一个程序,初始化一个double类型的3×5二维数组,使用一个处理变长数组的函数将其拷贝至另一个二维数组中。
还要编写一个以变长数组为形参的函数以显示两个数组的内容。
这两个函数应该能处理任意N×M数组 (如果编译器不支持变长数组,就使用传统C函数处理N×5的数组)。

10、
编写一个函数,把两个数组中相对应的元素相加,然后把结果储存到第 3 个数组中。
也就是说,如果数组1中包含的值是2、4、5、8,数组2中包含的值是1、0、4、6,那么该函数把3、4、9、14赋给第3个数组。
函数接受3个数组名和一个数组大小。
在一个简单的程序中测试该函数。

#include <stdio.h> 

#define LEN 4

void add();

int main(void) 
{ 
	int x[LEN] = { 2,4,5,8 };
	int y[LEN] = { 1,0,4,6 };
	int z[LEN];

	for (int i = 0; i < LEN; i++)
	{
		printf("x[%d] = %d ", i, x[i]);
	}
	printf("\n");

	for (int i = 0; i < LEN; i++)
	{
		printf("y[%d] = %d ", i, y[i]);
	}
	printf("\n");

	add(x, y, z, LEN);
	
	return 0; 
}

void add(int a1[], int a2[],int a3[], int n)
{ 
	for (int i = 0; i < LEN; i++)
	{
		a3[i] = a1[i] + a2[i];
		printf("z[%d] = %d ", i, a3[i]);
	}
	printf("\n");
}

11、
编写一个程序,声明一个int类型的3×5二维数组,并用合适的值初始化它。
该程序打印数组中的值,然后各值翻倍(即是原值的2倍),并显示出各元素的新值。
编写一个函数显示数组的内容,再编写一个函数把各元素的值翻倍。
这两个函数都以函数名和行数作为参数。

#include <stdio.h> 

void doublex();
void show();

int main(void) 
{ 
	int x[3][5] = 
	{
		{1,2,3,2,1},
		{3,2,1,2,3},
		{1,2,3,2,1}
	};
	show(x, 3);

	int y[3][5];
	doublex(x, y, 3);
	show(y, 3);
	
	return 0; 
}

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

void doublex(int a1[][5], int a2[][5], int n)
{ 
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n + 2; j++)
		{
			a2[i][j] = a1[i][j] * 2;
		}
	}
}

12、
重写程序清单10.7的rain.c程序,把main()中的主要任务都改成用函数来完成。

13、
编写一个程序,提示用户输入3组数,每组数包含5个double类型的数 (假设用户都正确地响应,不会输入非数值数据)。
该程序应完成下列任务。
a.把用户输入的数据储存在3×5的数组中
b.计算每组(5个)数据的平均值
c.计算所有数据的平均值
d.找出这15个数据中的最大值
e.打印结果
每个任务都要用单独的函数来完成(使用传统C处理数组的方式)。
完成任务b,要编写一个计算并返回一维数组平均值的函数,利用循环调用该函数3次。
对于处理其他任务的函数,应该把整个数组作为参数,完成任务c和d的函数应把结果返回主调函数。

14、
以变长数组作为函数形参,完成编程练习13。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值