C++ Primier Plus(第六版) 第七章 函数——C++的编程模块编程练习答案
- 1. 编写一个程序,不断要求用户输入两个数,直到其中的一个为0。对于每两个数,程序将使用一个函数来计算他们的调和平均数,并将结果返回给main(),而后者将报告结果。调和平均数指的是倒数平均值的倒数,计算公式如下:
- 2. 编写一个程序,要求用户输入最多10个高尔夫成绩,并将其存储在一个数组中。程序允许用户提早结束输入,并在一行上显示所有成绩,然后报告平均成绩。请使用3个数组处理函数来分别进行输入、显示和计算平均成绩。
- 3. 下面是一个结构声明:
- 4. 许多州的彩票发行机构都使用程序清单7.4所示的简单彩票玩法的变体。在这些玩法中,玩家从一组被称为域号码(field number)的几个号码中选择几个。例如,可以从域号码147中选择5个号码;还可以从区第二个区间(如127)选择一个号码(称为特选号码)。要赢得头奖,必须正确猜中所有的号码。中头奖的几率是选中所有域号码的几率与选中特选号号码的几率的乘积。例如,在这个例子中,中头奖的几率是从47个号码中正确选取5个号码的几率乘以从27个号码中正确选取一个号码的的几率的乘积。请修改程序清单7.4,以计算这种彩票中头奖的概率。
- 5. 定义一个递归函数,接受一个整数参数,并返回该参数的阶乘。前面讲过,3的阶乘写作3!,等于3*2!,一次类推:而0!被定义为1。通用计算公式是,如果n>0,则n! = n* (n-1)!。在程序中对该函数进行测试,程序使用循环让用户输入不同的值,程序将报告这些值的阶乘。
- 6. 编写一个程序,它使用下列函数:
- 7. 程序清单7.7中的3个数组处理函数,使之使用两个指针参数来表示区间。fill_array()函数不返回实际读取了多少个数字,而是返回一个指针,该指针指向最后被填充的位置;其他的函数可以将该指针作为第二个参数,以标识数据结尾。
- 8. 在不使用array类的情况下完成程序清单7.15的工作。编写两个这样的版本:
- 9. 这个练习让您编写处理数组和结构的函数。下面时程序框架,请提供其中描述的函数,完成该程序。
- 10. 设计一个名为calculate()的函数,它接受两个double值和一个指向函数的指针,而被指向的函数接受两个double参数,并返回一个double值。calculate()函数的类型也是double,并返回被指向的函数使用calculate()的两个参数计算得到的值。例如,假设add()函数的定义如下:
1. 编写一个程序,不断要求用户输入两个数,直到其中的一个为0。对于每两个数,程序将使用一个函数来计算他们的调和平均数,并将结果返回给main(),而后者将报告结果。调和平均数指的是倒数平均值的倒数,计算公式如下:
调和平均数 = 2.0 * x * y / (x + y)
本题首先编写计算调和平均值的函数,然后利用while()循环实现不断输入的效果,
程序如下:
// ex1.cpp -- calculate average with function
#include<iostream>
double cal_average(double x1, double x2);
int main()
{
using namespace std;
double num1, num2, result;
cout << "Enter two number(enter 0 to quit): ";
cin >> num1 >> num2;
while(num1 * num2 != 0)
{
if(!cin)
{
cin.clear();
while (cin.get() != '\n')
continue;
cout << "Bad input, process will terminate.\n";
break;
}
result = cal_average(num1, num2);
cout << "The calculate reuslt is " << result << ".\n";
cout << "Enter next two number(enter 0 to quit): ";
cin >> num1 >> num2;
}
cout << "Bye\n";
return 0;
}
double cal_average(double x, double y)
{
double aver;
aver = 2.0 * x * y / (x + y);
return aver;
}
运行结果如下:
2. 编写一个程序,要求用户输入最多10个高尔夫成绩,并将其存储在一个数组中。程序允许用户提早结束输入,并在一行上显示所有成绩,然后报告平均成绩。请使用3个数组处理函数来分别进行输入、显示和计算平均成绩。
首先编写三个函数。其中输入函数是核心函数,声明函数时,输入函数的参数应该时数组指针,返回值应该时一个int型变量,返回输入的个数。
其函数如下:
int input_ar(double *grades, int Max)
{
using namespace std;
int count = 0;
cout << "Enter the grade of golf(enter q to quit): ";
while(count < Max && cin >> grades[count])
{
count++;
if(count == 10) // last will cout Next grade(enter q to quit):
break;
cout <<"Next grade(enter q to quit): ";
}
return count;
}
显示成绩的函数如下:
void show(double grade[], int n)
{
using namespace std;
cout << "All grades: ";
for(int i = 0; i < n; i++)
cout << grade[i] << " ";
cout << endl;
}
计算平均成绩的函数如下:
double cal_av(double grade[], int n)
{
double sum = 0;
for(int i = 0; i < n; i++)
sum += grade[i];
return sum / n;
}
代码如下:
// ex2.cpp -- calculate the average grade of golf
#include<iostream>
const int Max = 10;
int input_ar(double *grades, int Max);
void show(double grade[], int n);
double cal_av(double grade[], int n);
int main()
{
using namespace std;
double grade[Max];
double average_g;
int len = input_ar(grade,Max);
show(grade,len);
average_g = cal_av(grade,len);
cout << "Average grade = " << average_g << endl;
return 0;
}
int input_ar(double *grades, int n)
{
using namespace std;
int count = 0;
cout << "Enter the grade of golf(enter q to quit): ";
while(count < n && cin >> grades[count])
{
count++;
if(count == 10)
break;
cout <<"Next grade(enter q to quit): ";
}
return count;
}
void show(double grade[], int n)
{
using namespace std;
cout << "All grades: ";
for(int i = 0; i < n; i++)
cout << grade[i] << " ";
cout << endl;
}
double cal_av(double grade[], int n)
{
double sum = 0;
for(int i = 0; i < n; i++)
sum += grade[i];
return sum / n;
}
运行结果如下:
3. 下面是一个结构声明:
struct box
{
char maker[40];
float height;
float width;
float length;
float volume;
};
a. 编写一个函数,按值传递box结构,并显示每个成员的值。
b. 编写一个函数,传递box结构的地址,并将volume成员设置为其他三维长度的乘积。
c. 编写一个使用这两个函数的简单程序。
程序如下:
// ex3.cpp -- using struct with function
#include<iostream>
struct box
{
char maker[40];
float height;
float width;
float length;
float volume;
};
void show(box b);
void set_volume(box *);
int main()
{
using namespace std;
box b1;
cout << "Enter the maker: ";
cin.getline(b1.maker,40);
cout << "Enter the box of hight: ";
cin >> b1.height;
cout << "Enter the box of width: ";
cin >> b1.width;
cout << "Enter the box of length: ";
cin >> b1.length;
set_volume(&b1);
show(b1);
return 0;
}
void show(box b)
{
using namespace std;
cout << "Maker: " << b.maker << endl;
cout << "Hight: " << b.height << endl;
cout << "Width: " << b.width << endl;
cout << "length: " << b.length << endl;
cout << "Volume: " << b.volume << endl;
}
void set_volume(box *pb)
{
pb->volume = pb->height * pb->width * pb->length;
}
运行结果如下:
4. 许多州的彩票发行机构都使用程序清单7.4所示的简单彩票玩法的变体。在这些玩法中,玩家从一组被称为域号码(field number)的几个号码中选择几个。例如,可以从域号码147中选择5个号码;还可以从区第二个区间(如127)选择一个号码(称为特选号码)。要赢得头奖,必须正确猜中所有的号码。中头奖的几率是选中所有域号码的几率与选中特选号号码的几率的乘积。例如,在这个例子中,中头奖的几率是从47个号码中正确选取5个号码的几率乘以从27个号码中正确选取一个号码的的几率的乘积。请修改程序清单7.4,以计算这种彩票中头奖的概率。
代码如下:
// ex4.cpp -- cal the property of get number
#include<iostream>
long double cal_property(int r1, int n, int r2);
int main()
{
using namespace std;
int range1, range2, num;
cout << "Enter the number of field number: ";
cin >> range1;
cout << "Enter the number of choose field number: ";
cin >> num;
cout << "Enter the number of specific number: ";
cin >> range2;
long double property = cal_property(range1, num, range2);
cout << "The property of get money is one in " << property << endl;
return 0;
}
long double cal_property(int r1, int n, int r2)
{
long double result = 1.0;
for(int i = r1,j = n; j > 0; i--, j--)//conditon write wrongly
result = result * i / j;
result *= r2;
return result;
}
运行结果如下:
5. 定义一个递归函数,接受一个整数参数,并返回该参数的阶乘。前面讲过,3的阶乘写作3!,等于3*2!,一次类推:而0!被定义为1。通用计算公式是,如果n>0,则n! = n* (n-1)!。在程序中对该函数进行测试,程序使用循环让用户输入不同的值,程序将报告这些值的阶乘。
本题的核心是利用递归实现计算阶乘的函数,调用函数n! = n * (n-1)!;则核心的递归是,result = n * cal_factorial(n-1);同时还需要处理1!与0!,利用if语句进行判断。
代码如下:
// ex5.cpp -- calculate the n!
#include<iostream>
long long cal_factorial(int n);
int main()
{
using namespace std;
int num;
long long factorial;
cout << "Enter the number(enter q to quit): ";
while(cin >> num)
{
factorial = cal_factorial(num);
cout << num << "! = " << factorial << endl;
cout << "Enter next number(enter q to quit): ";
}
cout << "Done\n";
return 0;
}
long long cal_factorial(int n)
{
long long result = 1;
if(n > 1)
result = n * cal_factorial(n-1);
else if(n == 1 || n ==0)
result *=1;
return result;
}
运行结果如下:
6. 编写一个程序,它使用下列函数:
Fill_array()将一个double数组的名称和长度作为参数。它提示用户输入double值,并将这些值存储到数组中。当数组被填满或者用户输入了非数字时,输入将停止,并返回实际输入了多少个数字。
Show_array()将一个double数组的名称和长度作为参数,并显示该数组的内容。
Reverse_array()将一个double数组的名称和长度作为参数,并将存储在该数组中的值顺序反转。
程序将使用这些函数来填充数组,然后显示数组;反转数组,然后显示数组;反转数组中除第一个和最后一个元素之外的所有元素,然后显示数组。
本题填充函数用while循环和if语句;显示函数用for循环即可;反转函数使用for循环,关键时for(int i = 0, j = len-1; i < j; i++,j--) // the last number of array is array[len-1]
代码如下:
// ex6.cpp -- using function to deal with array
#include<iostream>
const int Size = 5;
int Fill_array(double [], int len);
void Show_array(double arr[], int len);
void Reverse_array(double *, int len);
int main()
{
using namespace std;
double grade[Size];
int len = Fill_array(grade, Size);
Show_array(grade, len);
Reverse_array(grade, len);
cout << "Reverse array:\n";
Show_array(grade, len);
Reverse_array(grade + 1, len -2);
cout << "Reverse part of array:\n";
Show_array(grade,len);
return 0;
}
int Fill_array(double arr[], int len)
{
using namespace std;
int count = 0;
cout << "Enter a number(enter q to quit): ";
while(cin >> arr[count])
{
count++; // the position of count++ is important
if(count >= len)
break;
cout << "Enter next number(enter q to quit): ";
}
return count;
}
void Show_array(double arr[], int len)
{
using namespace std;
for(int i = 0; i < len; i++)
cout << arr[i] << " ";
cout << endl;
}
void Reverse_array(double *par, int len)
{
double temp;
for(int i = 0, j = len-1; i < j; i++,j--)
{
temp = par[i];
par[i] = par[j];
par[j] = temp;
}
}
运行结果如下:
7. 程序清单7.7中的3个数组处理函数,使之使用两个指针参数来表示区间。fill_array()函数不返回实际读取了多少个数字,而是返回一个指针,该指针指向最后被填充的位置;其他的函数可以将该指针作为第二个参数,以标识数据结尾。
首先从函数声明开始改,改完开始改函数定义,改完函数定义改函数调用。
代码如下:
//ex7.cpp -- array functions and point
#include<iostream>
const int Max = 5;
double * fill_arr(double *, double *);
void show_arr(double *, double *);
void revalue(double r, double *, double *);
int main()
{
using namespace std;
double property[Max];
double * ptend = fill_arr(property, property + Max);
show_arr(property, ptend);
if(ptend - property > 0)
{
cout << "Enter the revaluation facctor: ";
double factor;
while(!(cin >> factor))
{
cin.clear();
while(cin.get() != '\n')
continue;
cout << "Bad input; Please enter a number: ";
}
revalue(factor, property, ptend);
show_arr(property, ptend);
}
cout << "Done.\n";
cin.get();
cin.get();
return 0;
}
double * fill_arr(double * begin, double * end)
{
using namespace std;
double temp;
double * pt;
int count = 0;
for(pt = begin; pt != end; pt++) // for condition is pt != end, not pt == end
{
cout << "Enter value #" << (count + 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;
*pt = temp;
count++;
}
return pt;
}
void show_arr(double * begin, double * end)
{
double *pt;
int i = 0;
for(pt = begin; pt != end; pt++)
std::cout << "Property #" << (i + 1)
<< " : $" << *pt << std::endl;
i++;
}
void revalue(double r, double * begin, double * end)
{
double *pt;
for(pt = begin; pt != end; pt++)
*pt *= r;
}
运行结果如下:
8. 在不使用array类的情况下完成程序清单7.15的工作。编写两个这样的版本:
a. 使用const char *数组存储表示季度的字符串,并使用double数组存储开支。
b. 使用const char *数组存储表示季度的字符串,并使用一个结构,该结构只有一个成员——一个用于存储开支的double数组。这种设计与使用array类的基本设计类似。
本题编写程序时,使用const char *数组存储表示季度的字符串,刚开始一直编写不出来,想复杂了,以为需要一个二维的字符数组才可以表示,实际上声明一个char *类型的数组,存储四个字符串;该代码:
const char *Sname[4] = {"Spring", "Summer", "Winter"}
;
调用显示时有两种方法,分别是:
cout << Sname[i];
cout << *(Sname + i)
a的代码如下:
// ex8_a.cpp -- functions with double array(C++11)
#include<iostream>
#include<string>
using namespace std;
const int Seasons = 4;
const char* Sname[Seasons] =
{"Spring", "Summer", "Fall", "Winter"};
void fill(double *,int n);
void show(double [], int);
int main()
{
double expense[Seasons];
fill(expense, Seasons);
cout << "Your expense list:\n";
show(expense,Seasons);
return 0;
}
void fill(double *pta, int n)
{
double temp;
int count = 0;
cout << "Enter your expense of every season, enter q to quit.\n";
while(count < n)
{
cout << Sname[count] << ": " ;
cin >> temp;
if(!cin)
{
cin.clear();
while(cin.get() != '\n')
continue;
cout << "Bad input, process will terminated.";
break;
}
else if(temp < 0)
break;
*(pta + count) = temp;
count ++;
}
}
void show(double arr[], int n)
{
for (int i = 0; i < n; i++)
{
cout << Sname[i] << ": " << arr[i] << endl;
}
}
运行结果如下:
b.代码如下:
// ex8_b.cpp -- functions with double structure(C++11)
#include<iostream>
#include<string>
const int Seasons = 4;
const char* Sname[Seasons] =
{"Spring", "Summer", "Fall", "Winter"};
struct Expense
{
double expense[Seasons];
};
using namespace std;
void fill(double *,int n);
void show(double [], int);
int main()
{
Expense ex;
fill(ex.expense, Seasons);
cout << "Your expense list:\n";
show(ex.expense,Seasons);
return 0;
}
void fill(double *pta, int n)
{
double temp;
int count = 0;
cout << "Enter your expense of every season, enter q to quit.\n";
while(count < n)
{
cout << *(Sname + count) << ": " ;
cin >> temp;
if(!cin)
{
cin.clear();
while(cin.get() != '\n')
continue;
cout << "Bad input, process will terminated.";
break;
}
else if(temp < 0)
break;
*(pta + count) = temp;
count ++;
}
}
void show(double arr[], int n)
{
for (int i = 0; i < n; i++)
{
cout << Sname[i] << ": " << arr[i] << endl;
}
}
运行结果如下:
9. 这个练习让您编写处理数组和结构的函数。下面时程序框架,请提供其中描述的函数,完成该程序。
// ex9.cpp -- wirte the function
#include<iostream>
using namespace std;
const int SLEN = 30;
struct student
{
char fullname[SLEN];
char hobby[SLEN];
int ooplevel;
};
// getinfo() has tow arguments: a pointer to the first element of
// an array of student structure and an int representing the
// number og element of the array. The function solicits and
// stores data about students. It terminates input upon filling
// the array or upon encountering a blank line for the student
// name. The function returns the actual number of array elements
// filled.
int getinfo(student pa[], int n);
// display1() takes a student structure as an argument
// and diplay its contents
void display1(student st);
// display2() takes the address of student structure as an
// argument and diplay the structure's contents
void display2(student * ps);
// display3() takes the address of the first element of an array
// of student structure as and the number of array elements as
// arguments and diplay the structure's contents
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\n";
return 0;
}
本题实现几个函数的功能不难,在实现输入姓名为空格跳出程序时,出现了问题,原因是使用char字符串数组用==
与空行字符串比较,因此不能实现,后想起应该使用strcmp()函数,于是实现该功能。
代码如下:
// ex9.cpp -- wirte the function
#include<iostream>
#include<cstring>
using namespace std;
const int SLEN = 30;
struct student
{
char fullname[SLEN];
char hobby[SLEN];
int ooplevel;
};
// getinfo() has tow arguments: a pointer to the first element of
// an array of student structure and an int representing the
// number og element of the array. The function solicits and
// stores data about students. It terminates input upon filling
// the array or upon encountering a blank line for the student
// name. The function returns the actual number of array elements
// filled.
int getinfo(student pa[], int n);
// display1() takes a student structure as an argument
// and diplay its contents
void display1(student st);
// display2() takes the address of student structure as an
// argument and diplay the structure's contents
void display2(student * ps);
// display3() takes the address of the first element of an array
// of student structure as and the number of array elements as
// arguments and diplay the structure's contents
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\n";
return 0;
}
int getinfo(student pa[], int n)
{
int count = 0;
for(int i = 0; i < n; i ++)
{
cout << "Student #" << i+1 << ":\n";
cout << "Enter the name(enter blank line to quit): ";
cin.getline(pa[i].fullname, SLEN);
if(!strcmp(pa[i].fullname," ")) //
break;
count++;
cout << "Enter the hobby: ";
cin.getline(pa[i].hobby,SLEN);
cout << "Enter the opplevel: ";
cin >> pa[i].ooplevel;
cin.get();
}
return count;
}
void display1(student st)
{
cout << "Fullname: " << st.fullname << endl;
cout << "Hobby: " << st.hobby << endl;
cout << "Ooplevel: " << st.ooplevel << endl;
}
void display2(student *ps)
{
cout << "Fullname: " << ps->fullname << endl;
cout << "Hobby: " << ps->hobby << endl;
cout << "Ooplevel: " << ps->ooplevel << endl;
}
void display3(const student pa[], int n)
{
for (int i = 0; i < n; i++)
{
cout << "Student #" << i + 1 << ":\n";
cout << "Fullname: " << pa[i].fullname << endl;
cout << "Hobby: " << pa[i].hobby << endl;
cout << "Ooplevel: " << pa[i].ooplevel << endl;
}
}
运行结果如下:
10. 设计一个名为calculate()的函数,它接受两个double值和一个指向函数的指针,而被指向的函数接受两个double参数,并返回一个double值。calculate()函数的类型也是double,并返回被指向的函数使用calculate()的两个参数计算得到的值。例如,假设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)
;
本题考查的是函数指针作为参数被函数调用,调用时可以用(* pf) 也可以直接用pf,还考察了指针函数数组的初始化。
代码如下:
// ex10.cpp -- using point to function
#include<iostream>
double calculate(double , double , double (*p) (double , double ));
double add(double x, double y);
double sub(double x, double y);
double multi(double x, double y);
double div(double x, double y);
int main()
{
using namespace std;
double (*pf[4]) (double , double) = {add, sub, multi, div};
char op[4] = {'+','-','*','/'};
double num1, num2;
cout << "Enter two number(enter q to quit): ";
while(cin >> num1 >> num2)
{
for(int i = 0; i < 4; i++)
{
double result = calculate(num1,num2, pf[i]);
cout << num1 << " "<< op[i] << " " << num2 << " = " << result << endl;
}
cout << "Enter next two number(enter q to quit): ";
}
cout << "Done\n";
return 0;
}
double calculate(double x, double y, double (*p) (double , double ))
{
return (*p)(x,y); // return p(x,y) is right
}
double add(double x, double y)
{
return x + y;
}
double sub(double x, double y)
{
return x - y;
}
double multi(double x, double y)
{
return x * y;
}
double div(double x, double y)
{
return x / y;
}
运行结果如下: