(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; //返回平均数
}
结果:
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)输入超过十个数,只读前十个数。
(2)使用-1提前结束输入。
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值
}
结果:
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; //返回概率值
}
结果:
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
}
结果:
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.修改程序清单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++;
}
}
结果:
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;
}
结果:
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;
}
结果:
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;
}
结果:
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;
}
结果:
代码:(使用指针数组)
#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均可表示函数的地址,因此两段代码在此程序中作用等同。