C++ Primer Plus课后编程练习第7章参考代码

本文分享了C++PrimerPlus课程的编程练习代码,包括调和平均数计算、高尔夫成绩管理、结构体操作、中奖概率计算、阶乘计算、数组处理、结构数组处理等实例,适合初学者参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(C++ Primer Plus课后编程练习第7章参考代码)

声明:

作者入门小白,将学习过程中的代码做一些分享,仅供大家参考,欢迎大家交流指正。全部编译运行过,水平有限,不喜勿喷。

环境:

Windows 7操作系统,Dev C++ 5.11,TDM-GCC 4.9.2 64-bit Release

1.编写一个程序,不断要求用户输入两个数,知道其中一个为0.对于每两个数,程序将使用一个函数来计算他们的调和平均数,并将结果返回给main(),而后者将报告结束。调和平均数指得是倒数平均值的倒数,公式:调和平均数=2.0xy/(x+y)。

代码:

#include <iostream> 

using namespace std;

double average( double ,double );		//函数声明

int main()
{
	cout << "Please input 2 numbers, (0 to quit): " << endl;
	double n1,n2;
	cin >> n1 >> n2;			//获取两个输入
	while( n1!=0 && n2!=0 )
	{
		cout << "average: " << average( n1, n2 ) << endl;		//调用函数
		cout << "Please input 2 numbers, (0 to quit): " << endl;
		cin >> n1 >> n2;
	}
	cout << "Bye" << endl;
	
	return 0;
}

double average( double x, double y )		//函数定义,将获取的两个输入作为参数
{
	double ave = 0.0;
	ave = (2.0 * x * y)/( x + y );		//求调和平均数
	return ave;				//返回平均数
}

结果:
图7.12.1

2.编写一个程序,要求用户输入最多10个高尔夫成绩,并将其存储在一个数组中。程序允许用户提早结束输入,并在一行上显示所有成绩,然后报告平均成绩。请使用3个数组处理函数来分别进行输入、显示和计算平均成绩。

代码:

#include <iostream> 

using namespace std;

int input( double [], int );			//输入函数声明
double average( double [], int );		//求平均值函数声明
void display( double [], int );			//显示函数声明

int main()
{
	const int Max = 10;				//最大元素个数
	double score[Max] = {0.0};			//初始化数组
	int n = input( score, Max );			//获取输入,并返回有效元素个数
	cout << "add " << n << " elements success!" << endl;
	display( score, n );			//显示数组的有效元素
	cout << "\nAverage: " << average( score, n ) << endl;		//计算并输出平均值
	
	return 0;
}

int input( double score[], int size )		//将数组名和数组最大长度作为参数,返回获取的有效元素个数
{
	cout << "Please input 10 numbers, (-1 to quit): " << endl;
	double num;
	int i = 0;
	while( cin>>num && num>=0 && i<size)		//获取double数据、数据>=0、元素个数不大于10个
	{
		score[i] = num;				//将合法数据存入数组,由于采用指针方式,score[]值会改变
		i++;
	}
	return i;				//返回正确读入的数据的个数
}

double average( double score[], int size )		//将数组名和数组有效参数个数作为参数,返回平均值
{
	double ave = 0.0;
	for( int i=0; i<size; i++ )		//对数组中有效元素求和
	{
		ave += score[i];
	}
	ave /= size;			//求平均数
	return ave;				//返回平均数
}

void display( double score[], int size )		//将数组名和数组有效参数个数作为参数
{
	cout << endl;
	for( int i=0; i<size; i++ )				//遍历输出所有有效元素
	{
		cout << score[i] << ", ";
	}		
}

结果:
(1)输入超过十个数,只读前十个数。
图7.12.2-1
(2)使用-1提前结束输入。
图7.12.2-2

3.下面是一个结构声明:

struct box{ char maker[40]; float height; float width; float length; float volume;};

a.编写一个函数,按值传递box结构,并显示每个成员的值。
b.编写一个函数,传递box结构的地址,并将volume成员设置为其他三维长度的乘积。
c.编写一个使用这两个函数的简单程序。

代码:

#include <iostream> 

using namespace std;

struct box			//结构声明
{
	char maker[40];			//制造者
	float height;			//高度
	float width;			//宽度
	float length;			//长度
	float volume;			//体积
};

void display( box );			//按值传递

void capcity( box * );			//按地址传递

int main()
{
	box aa = {"liao", 30.0, 40.0, 50.0, 0.0};			//创建一个box结构并初始化
	box *pa = &aa;						//指针pa指向该box结构
	
	capcity( pa );				//使用地址传递方式修改volume值
	
	display( aa );				//使用值传递方式显示每个成员的值
	
	return 0;
}

void display( box bb )			//参数为一个box结构
{
	cout << "Box: " << endl;
	cout << "Maker: " << bb.maker << endl;
	cout << "Height: " << bb.height << endl;
	cout << "Width: " << bb.width << endl;
	cout << "Length: " << bb.length << endl;
	cout << "Volume: " << bb.volume << endl;
}

void capcity( box * pb )			//参数为一个指向box结构的指针
{
	pb->volume = pb->height * pb->width * pb->length;		//计算并修改volume值
}

结果:
图片7.12.3

4.中头奖的几率是从47个号码中正确选择5个号码的几率与从27个号码中正确选择1个号码的几率的乘积。请修改程序清单7.4,以计算中这种头奖的几率。

代码:

#include <iostream> 

using namespace std;

long double probability( );			//函数声明

int main()
{
	long double rate = probability();			//获取中头奖概率(小数形式)
	rate *= 100;				//转为百分数形式
	cout.setf( ios_base::fixed );			//使用定点小数表示法
	cout.precision( 10 );			//10位有效数字
	cout << "The rate of winning: " << rate << " %" << endl;
	
	return 0;
}

long double probability( )			//计算中头奖概率函数
{
	long double result = 1.0;			//存放最终结果
	long double n;					//分子
	unsigned int p;					//分母
	for( n=47,p=5; p>0; n--,p-- )
	{
		result = result * n / p;		//一乘一除可以使得结果不会超出long double表示范围
	}
	result *= 27;				//计算中头奖概率的分母
	result = 1.0 / result;			//倒数即为中奖概率
	return result;				//返回概率值
}

结果:
图7.12.4

5.定义一个递归函数,接受一个整数参数,并返回该参数的阶乘。前面讲过,3的阶乘写作3!等于32!,以此类推:而0!被定义为1.通用的计算公式是,如果n大于0,则n!=n(n-1)!。在程序中对该函数进行测试,程序使用循环让用户输入不同的值,程序将报告这些值的阶乘。

代码:

#include <iostream> 

using namespace std;

long int factorial( int n );			//函数声明

int main()
{
	cout << "Please input n: ";
	int n;
	cin >> n;
	while( n>=0 )			//当输入的n值小于0,就结束程序
	{
		cout << "Factorial: " << factorial(n) << endl;		//输出n的阶乘的值
		cout << "Please input n: ";
		cin >> n;
	}
	cout << "Bye!" <<  endl;			//程序结束
	
	return 0;
}


long int factorial( int n )				//函数定义
{
	long int result = 1;				//输入n<0程序会退出,因此传递进来的n只能>=0
	if( n>1 )					//n>1时使用递归计算阶乘
	{
		result = n * factorial( n-1 );		//递归调用,每次调用n-1
	}
	
	return result;		//当n不大于1即n=0时,返回result的初值1
}

结果:
图7.12.5

6.编写一个程序,它使用下列函数:

Fill_array()将一个double数组的名称和长度作为参数。它提示用户输入double值,并将这些值存储到数组中。当数组被填满或用户输入了非数字时,输入将停止,并返回实际输入了多少个数字。
Show_array()将一个double数组的名称和长度作为参数,并显示该数组的内容。
Reverse_array()将一个double数组的名称和长度作为参数,并将存储在数组中的值的顺序反转。
程序将使用这些函数来填充数组,然后显示数组;反转数组,然后显示数组;反转数组中除第一个和最后一个元素之外的所有元素,然后显示数组。
代码:

#include <iostream> 

using namespace std;

int Fill_array( double [], int );			//函数声明
void Show_array( double [], int );
void Reserve_array( double [], int );

int main()
{
	const int Max = 10;					//最大元素数
	double a[Max] = {0.0};				//定义数组并初始化
	cout << "Please input elements:" << endl;
	int n = Fill_array( a, Max );			//获取数据填入数组,并获取实际输入元素的个数
	cout << "Success add " << n << " elements:\n";
	Show_array( a, n );				//显示数组a中元素
	Reserve_array( a, n );			//元素反转
	Show_array( a, n );				//显示
	Reserve_array( a+1, n-2 );		//除首尾外其他元素反转
	Show_array( a, n );				//显示
	
	return 0;
}

int Fill_array( double arr[], int size )		//数组名和长度作为参数
{
	double num;
	int i = 0;
	while( cin>>num && i<size )			//当输入非数字或者元素数量多于size时停止
	{
		arr[i] = num;				//存入数据
		i++;
	}
	return i;					//返回被填入数据的个数
}

void Show_array( double arr[], int size )
{
	for( int i=0; i<size; i++ )				//遍历显示
	{
		cout << arr[i] << ", ";
	}
	cout << endl;
}

void Reserve_array( double arr[], int size )
{
	double temp;				//作为中间值
	for( int i=0; i<size/2; i++ )		//首尾互换
	{
		temp = arr[i];					//借助中间值进行交换
		arr[i] = arr[size-1 - i];
		arr[size-1 - i] = temp;
	}
}

结果:
图7.12.6

7.修改程序清单7.7中的3个数组处理函数,使之使用两个指针参数来表示区间。fill_array()函数不返回实际读取了多少个数字,而是返回一个指针,该指针指向最后被填充的位置;其他的函数可以将该指针作为第二个参数,以标识数据结尾。

代码:

#include <iostream> 

using namespace std;

const int Max = 5;			//符号变量

double * fill_array( double *, int );					//函数声明
void show_array( const double *, const double * );
void revalue( double r, double *, double * );

int main()
{
	double properties[Max];					//定义数组
	double * size = fill_array( properties, Max );			//获取值,返回最后被填充的位置指针
	show_array( properties, size );			//显示数组元素
	
	if( size-properties>0 )		//size-properties的值是当前数组中元素的个数
	{
		cout << "Enter revaluation factor: ";
		double factor;				//获取因子
		while( !( cin>>factor ) )		//获取数据不成功时,输出提示语并等待正确输入
		{
			cin.clear();
			while( cin.get() != '\n' )
				continue;
			cout << "Bad input; Please enter a number: ";
		}
		revalue( factor, properties, size );		//根据factor因子,改变数组中的值
		show_array( properties, size );				//显示当前数组元素
	}
	
	cout << "Done.\n";			//程序结束提示语
	cin.get();
	cin.get();		
	return 0;
}

double * fill_array( double * first, int n )		//参数1是数组名,参数2是要获取的元素个数
{
	double temp;
	int i;
	for( i=0; i<n; i++ )		//获取n个参数
	{
		cout << "Enter value #" << (i+1) << ": ";
		cin >> temp;
		if( !cin )
		{
			cin.clear();
			while( cin.get() != '\n' )
			{
				continue;
			}
			cout << "Bad input; input process terminated.\n";
			break;
		}
		else if( temp<0 )
		{
			break;
		}
		first[i] = temp;			//向数组装入值
	}
	return first+i;			//返回值为数组的最后一个元素后面的一个位置指针
}

void show_array( const double * first, const double * end )		//参数1为数据起始位置,参数2为数据结束位置
{
	int i = 1;
	while( first < end )			//输出区间内的元素
	{
		cout << "Property #" << i++ << ": $";
		cout << *first << endl;
		first++;
	}
}

void revalue( double r, double * first, double * end )		//参数1为数据起始位置,参数2为数据结束位置
{
	while( first < end )		//将区间内的元素乘以因子
	{
		*first *= r;
		first++;
	}
}

结果:
图7.12.7

8.在不使用array类的情况下完成程序清单7.15所做的工作。编写两个这样的版本:

a.使用const char * 数组存储表示季度名称的字符串,并使用double数组存储开支。
b.使用const char * 数组存储表示季度名称的字符串,并使用一个结构,该结构只有一个成员——一个用于存储开支的double数组。这种设计与使用array类的基本相似。
a.代码:

#include <iostream> 

using namespace std;

const int Seasons = 4;
const char * Sname[Seasons] = {"Spring","Summer","Fall","Winter"};			//用const char * 数组存储字符串

void Fill( double pa[] );
void show( double da[] );

int main()
{
	double expenses[Seasons];		//使用double数组存储开支
	Fill( expenses );
	show( expenses );
			
	return 0;
}

void Fill( double pa[] )			//获取每季度开支
{
	for( int i=0; i<Seasons; i++ )
	{
		cout << "Enter " << Sname[i] << " expenses: ";
		cin >> pa[i]; 
	}
}

void show( double da[] )			//显示每季度开支和总开支
{
	double total = 0.0;
	cout << "\nEXPENSES\n";
	for( int i=0; i<Seasons; i++ )
	{
		cout << Sname[i] << ":$" << da[i] << endl;
		total += da[i];
	}
	cout << "Total Expenses: $" << total << endl;
}

结果:
图7.12.8.a
b.代码:

#include <iostream> 

using namespace std;

const int Seasons = 4;				//符号常量
const char * Sname[Seasons] = {"Spring","Summer","Fall","Winter"};		//const char *数组存储字符串

struct Income				//声明结构
{
	double money[Seasons];			//用于存储开支的double数组
};

void Fill( Income * );			//函数声明
void show( Income );

int main()
{
	Income gain;				//定义Income结构对象gain
	Fill( &gain );				//传结构体地址
	show( gain );				//传值
			
	return 0;
}

void Fill( Income * pg )			//pg为指向结构的指针
{
	for( int i=0; i<Seasons; i++ )			//按季度获取输入
	{
		cout << "Enter " << Sname[i] << " expenses: ";
		cin >> pg->money[i]; 
	}
}

void show( Income gain )			//值传递
{
	double total = 0.0;
	cout << "\nEXPENSES\n";
	for( int i=0; i<Seasons; i++ )			//按季度输出
	{	
		cout << Sname[i] << ":$" << gain.money[i] << endl;
		total += gain.money[i];				//计算年支出
	}
	cout << "Total Expenses: $" << total << endl;
}

结果:
图7.12.8.b

9.这个练习让您编写处理数组结构的函数。下面是程序的框架,请提供其中描述的函数,已完成该程序。

代码:

#include <iostream> 

using namespace std;

const int SLEN = 30;
struct student
{
	char fullname[SLEN];
	char hobby[SLEN];
	int ooplevel;
};

int getinfo( student pa[], int n );
void display1( student st );
void display2( const student * ps );
void display3( const student pa[], int n );

int main()
{
	cout << "Enter class size: ";
	int class_size;
	cin >> class_size;
	while( cin.get() != '\n' )
		continue;
	
	student * ptr_stu = new student[class_size];
	int entered = getinfo( ptr_stu, class_size );
	for( int i=0; i<entered; i++ )
	{
		display1( ptr_stu[i] );
		display2( &ptr_stu[i] );
	}
	display3( ptr_stu, entered );
	delete [] ptr_stu;
	cout << "Done" << endl;
	
	return 0;
}

int getinfo( student pa[], int n )
{
	cout << "Please input the students information:" << endl;
	int i;
	for( i=0; i<n; i++ )		//获取不超过n个输入
	{
		cout << "The No." << i+1 << ": " << endl;
		cout <<"Fullname: ";
		cin.getline( pa[i].fullname, SLEN );		//获取姓名,允许多个单词用空格隔开
		if( pa[i].fullname[0]=='\0' )			//当输入的姓名为空行时退出
			break;
		cout << "Hobby: ";
		cin.getline( pa[i].hobby, SLEN );			//获取兴趣爱好
		cout << "Ooplevel: ";
		cin >> pa[i].ooplevel;				//获取等级
		cin.get();				//使用cin获取数字后需要使用cin.get()消除换行符,否则会影响下一次输入
	}
	cout << endl;
	return i;		//返回实际获取到的元素的数量
}

void display1( student st )			//使用值传递结构数组的一个元素
{
	cout << st.fullname << ", ";
	cout << st.hobby << ", ";
	cout << st.ooplevel;
	cout << endl << endl;
}

void display2( const student * ps )			//使用地址传递结构数组的一个元素
{
	cout << ps->fullname << ", ";
	cout << ps->hobby << ", ";
	cout << ps->ooplevel;
	cout << endl << endl;
}

void display3( const student pa[], int n )			//使用地址传递整个结构数组
{
	for( int i=0; i<n; i++ )
	{
		cout << pa[i].fullname << ", ";
		cout << pa[i].hobby << ", ";
		cout << pa[i].ooplevel << endl;
	}
	cout << endl << endl;
}

结果:
图7.12.9

10.设计一个名为calculate()的函数,它接受两个double值和一个指向函数的指针,而被指向的函数接受两个double参数,并返回一个double值。calculate()函数的类型也是double,并返回被指向的函数使用calculate()的两个double参数计算得到的值。例如,假设add()函数定义如下:

double add( double x, double y)
{
return x + y;
}

则下述代码中的函数调用将导致calculate()把2.5和10.4传递给add()函数,并返回add()的返回值(12.9):

double q = calculate(2.5, 10.4, add);

请编写一个程序,它调用上述两个函数和至少另一个与add()类似的函数。该程序使用循环来让用户成对的输入数字。对于每对数字,程序都使用calculate()来调用add()和至少一个其他函数。如果读者爱冒险。可以尝试创建一个指针数组,其中的指针指向add()样式的函数,并编写一个循环,使用这些指针连续让calculate()调用这些函数。

double (*pf[3])(double,double);

可以使用数组初始化语法,并将函数名作为地址来初始化这样的数据。

代码:(未使用指针数组)

#include <iostream> 

using namespace std;

typedef double (*P_F)( double, double );		//为指向函数的指针类型取一个别名

double add( double, double );			//被调函数声明
double sub( double, double );
double calculate( double, double, P_F );		//调用函数声明

int main()
{
	cout << "Enter 2 numbers(q to quit): ";
	double n1,n2;
	while( cin>>n1>>n2 )		//获取两个double输入
	{
		double q = calculate( n1, n2, add );		//通过函数调用add()函数
		cout << "The calculate_add: " << q << endl;
		double p = calculate( n1, n2, sub );		//通过函数调用sub()函数
		cout << "The calculate_add: " << p << endl;
		
		cout << "Enter 2 numbers(q to quit): ";
	}
	cout << "Done" << endl;
	
	return 0;
}

double add( double x, double y )
{
	return x+y;
}

double sub( double x, double y )
{
	return x-y;
}

double calculate( double x, double y, P_F pf )
{
	double result = pf( x, y );			//调用pf指针指向的函数
	return result;
}

结果:
图7.12.10
代码:(使用指针数组)

#include <iostream> 

using namespace std;

typedef double (*P_F)( double, double );

double add( double, double );
double sub( double, double );
double calculate( double, double, P_F );

int main()
{
	P_F pf[2] = { &add, &sub };		//数组pf中存储的是指向函数add()和sub()的指针
	
	cout << "Enter 2 numbers(q to quit): ";
	double n1,n2;
	while( cin>>n1>>n2 )
	{
		for( int i=0; i<2; i++ )		//通过传递不同的指针使calculate()函数调用不同的函数处理n1,n2
		{
			double q = calculate( n1, n2, pf[i] );
			cout << "The calculate_add: " << q << endl;
		}
		cout << "Enter 2 numbers(q to quit): ";
	}
	cout << "Done" << endl;
	
	return 0;
}

double add( double x, double y )
{
	return x+y;
}

double sub( double x, double y )
{
	return x-y;
}

double calculate( double x, double y, P_F pf )
{
	double result = pf( x, y );
	return result;
}

结果:与上图一致。

提示:

typedef double (*P_F)( double, double ); //第一段
P_F pf[2] = { &add, &sub };

double (*pf[2])(double,double) = { add, sub }; //第二段
以上两段代码作用一致,都声明一个指针数组,其中的指针指向函数。第一段使用typedef为指向函数的指针取了一个别名P_F,后续使用P_F声明的数据均是指向函数的指针,P_F声明的数组是以指向函数的指针为元素的数组。第二段直接声明pf[2]为数组,数组中元素是指向返回值为double、有两个double参数的函数的指针。因为add和&add均可表示函数的地址,因此两段代码在此程序中作用等同。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值