《C++ Primer Plus》(第6版)第7章编程练习
《C++ Primer Plus》(第6版)第7章编程练习
1. 调和平均数
编写一个程序,不断要求用户输入两个数,直到其中的一个为0。对于每两个数,程序将使用一个函数来计算它们的调和平均数,并将结果返回给main(),而后者将报告结果。调和平均数指的是倒数平均值的倒数,计算公式如下:
调和平均数=2.0 * x * y / (x+ y)
代码:
#include <iostream>
using namespace std;
double cal_harmonic_mean(double, double);
int main()
{
int a, b;
cout << "Enter two numbers, I will calculate their harmonic average.\n";
while (1)
{
cout << "a:";
cin >> a;
cout << "b:";
cin >> b;
if (!a | !b)
break;
cout << "The harmonic mean of a and b is " << cal_harmonic_mean(a, b) << ".\n";
}
cout << "Done!\n";
system("pause");
return 0;
}
double cal_harmonic_mean(double x, double y)
{
return 2.0 * x * y / (x + y);
}
运行结果:
2. 高尔夫成绩
编写一个程序,要求用户输入最多10个高尔夫成绩,并将其存储在一个数组中。程序允许用户提早结束输入,并在一行上显示所有成绩,然后报告平均成绩。请使用3个数组处理函数来分别进行输入、显示和计算平均成绩。
代码:
#include <iostream>
using namespace std;
#define ArrSize 10
int elem = 0;
void input_score(double *);
void display_score(double *);
double cal_mean_score(double *);
int main()
{
double golfScore[ArrSize];
cout << "Enter golf scores(enter non number to quit)\n";
input_score(golfScore);
cout << "All golf score:\n";
display_score(golfScore);
cout << "Average golf score:" << cal_mean_score(golfScore) << endl;
system("pause");
return 0;
}
void input_score(double *arr)
{
for (int i = 0; i < ArrSize; i++)
{
cout << "Input the " << i + 1
<< "-th golf score: ";
if (cin >> arr[i])
{
}
else
{
elem = i;
break;
}
elem = i;
}
}
void display_score(double *arr)
{
for (int i = 0; i < elem; i++)
cout << arr[i] << " ";
cout << endl;
}
double cal_mean_score(double *arr)
{
double average = 0.0;
for (int i = 0; i < elem; i++)
average += arr[i];
return average / (double)elem;
}
运行结果:
3. box
下面是一个结构声明:
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(box);
void cal_volume(box *);
int main()
{
box example;
cout << "Enter the name of maker:";
cin.getline(example.maker, 40);
cout << "Enter the height:";
cin >> example.height;
cout << "Enter the width:";
cin >> example.width;
cout << "Enter the length:";
cin >> example.length;
cal_volume(&example);
display_box(example);
system("pause");
return 0;
}
void display_box(box b)
{
cout << "maker: " << b.maker << endl;
cout << "height: " << b.height << endl;
cout << "width: " << b.width << endl;
cout << "length: " << b.length << endl;
cout << "volume: " << b.volume << endl;
}
void cal_volume(box *b)
{
b->volume = b->length * b->width * b->height;
}
运行结果:
4. 彩票
许多州的彩票发行机构都使用如程序清单7.4所示的简单彩票玩法的变体。在这些玩法中,玩家从一组被称为域号码(field number)的号码中选择几个。例如,可以从域号码1 ~ 47中选择5个号码;还可以从第二个区间(如1~27)选择一个号码(称为特选号码)。要赢得头奖,必须正确猜中所有的号码。中头奖的几率是选中所有域号码的几率与选中特选号码几率的乘积。例如,在这个例子中,中头奖的几率是从47个号码中正确选取5个号码的几率与从27个号码中正确选择1个号码的几率的乘积。请修改程序清单7.4,以计算中得这种彩票头奖的几率。
代码:
#include <iostream>
using namespace std;
long double probability(unsigned, unsigned);
int main()
{
double field_total = 47, field_choices = 5;
double special_total = 27, special_choices = 1;
cout << "You have one chance in ";
cout << probability(field_total, field_choices) * probability(special_total, special_choices);
cout << " of winning.\n";
system("pause");
return 0;
}
long double probability(unsigned numbers, unsigned picks)
{
long double result = 1.0;
long double n;
unsigned p;
for (n = numbers, p = picks; p > 0; n--, p--)
{
result = result * n / p;
}
return result;
}
运行结果:
5. 阶乘
定义一个递归函数,接受一个整数参数,并返回该参数的阶乘。前面讲过,3的阶乘写作3!,等于32!,依此类推;而0!被定义为1。通用的计算公式是,如果n大于零,则n!=n(n-l)!。在程序中对该函数进行测试,程序使用循环让用户输入不同的值,程序将报告这些值的阶乘。
代码:
#include <iostream>
using namespace std;
long Factorial(int);
int main()
{
int n;
cout << "Enter a number n(n>0)(q to quit):";
while (cin >> n)
{
cout << n << "! = " << Factorial(n) << endl;
cout << "Next number(q to quit): ";
}
cout << "Done!\n";
system("pause");
return 0;
}
long Factorial(int n)
{
if (n > 0)
return n * Factorial(n - 1);
return 1;
}
运行结果:
6. 数组操作
编写一个程序,它使用下列函数:
Fill_array()将一个double数组的名称和长度作为参数。它提示用户输入double值,并将这些值存储到数组中。当数组被填满或用户输入了非数字时,输入将停止,并返回实际输入了多少个数字。
Show_array()将一个double数组的名称和长度作为参数,并显示该数组的内容。
Reverse_array()将一个double数组的名称和长度作为参数,并将存储在数组中的值的顺序反转。程序将使用这些函数来填充数组,然后显示数组;反转数组,然后显示数组;反转数组中除第一个和最后一个元素之外的所有元素,然后显示数组。
代码:
#include <iostream>
using namespace std;
const unsigned int ArrSize = 20;
int Fill_array(double *, unsigned int);
void Show_array(const double array[], int length);
void Reverse_array(double Array[], int length);
int main()
{
double arr[ArrSize];
int arrLen = 0;
cout << "Enter numbers(q to quit):" << endl;
arrLen = Fill_array(arr, ArrSize);
Show_array(arr, arrLen);
Reverse_array(arr, arrLen);
Show_array(arr, arrLen);
system("pause");
return 0;
}
int Fill_array(double array[], unsigned int ArrSize)
{
int len = 0;
while (cin >> array[len] && len < ArrSize)
len++;
return len;
}
void Show_array(const double array[], int length)
{
if (length == 0)
{
cout << "The array is empty.\n";
return;
}
cout << "Array content:\n";
for (int i = 0; i < length; i++)
cout << array[i] << " ";
cout << endl;
}
void Reverse_array(double *Array, int length)
{
if (length == 0)
{
cout << "The array is empty.\n";
return;
}
cout << "Reverse all elements in the array except the first and last\n";
for (int i = 0; i < length / 2; i++)
{
if (i == 0)
continue;
else
{
double temp = Array[i];
Array[i] = Array[length - i - 1];
Array[length - i - 1] = temp;
}
}
}
运行结果:
7. 数组处理函数
修改程序清单7.7中的3个数组处理函数,使之使用两个指针参数来表示区间。fill_array()函数不返回实际读取了多少个数字,而是返回一个指针,该指针指向最后被填充的位置;其他的函数可以将该指针作为第二个参数,以标识数据结尾。
代码:
#include <iostream>
using namespace std;
const int Max = 5;
double *fill_array(double *, double *);
void show_array(const double *, const double *);
void revalue(double, double *, double *);
int main()
{
double properties[Max];
double *end = fill_array(properties, properties + Max);
show_array(properties, end);
if (end != 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, end);
show_array(properties, end);
}
cout << "Done!\n";
system("pause");
return 0;
}
double *fill_array(double *begin, double *end)
{
double *temp = begin;
int i = 0;
for (; temp != end; temp++)
{
cout << "Enter value #" << (i + 1) << ":";
cin >> *temp;
if (!cin)
{
cin.clear();
while (cin.get() != '\n')
continue;
cout << "Bad input;Please enter a number:";
break;
}
else if (*temp < 0)
break;
i++;
}
return temp;
}
void show_array(const double *begin, const double *end)
{
int i = 0;
for (; begin != end; begin++)
{
cout << "Property #" << (i + 1) << ": $";
cout << *begin << endl;
i++;
}
}
void revalue(double r, double *begin, double *end)
{
for (double *temp = begin; temp != end; temp++)
*temp *= r;
}
运行结果:
8. 开支
在不使用array类的情况下完成程序清单7.15所做的工作。编写两个这样的版本:
a.使用const char * 数组存储表示季度名称的字符串,并使用double数组存储开支。
b.使用const char* 数组存储表示季度名称的字符串,并使用一个结构,该结构只有一个成员———个用于存储开支的double数组。这种设计与使用array类的基本设计类似。
a.
代码:
#include <iostream>
#include <string>
using namespace std;
const int Seasons = 4;
const string Snames[Seasons] = {"Spring", "Summer", "Fall", "Winter"};
void fill(double *);
void show(const double *);
int main()
{
double expenses[Seasons];
fill(expenses);
show(expenses);
system("pause");
return 0;
}
void fill(double expenses[])
{
for (int i = 0; i < Seasons; i++)
{
cout << "Enter " << Snames[i] << " expenses: ";
cin >> expenses[i];
}
}
void show(const double expenses[])
{
double total = 0.0;
cout << "\nEXPENSES\n";
for (int i = 0; i < Seasons; i++)
{
cout << Snames[i] << ": $" << expenses[i] << endl;
total += expenses[i];
}
cout << "Total Expenses: $" << total << endl;
}
运行结果:
b.
代码:
#include <iostream>
#include <string>
using namespace std;
const int Seasons = 4;
const string Snames[Seasons] = {"Spring", "Summer", "Fall", "Winter"};
typedef struct Expenses
{
double expenses[Seasons];
} Expenses;
void fill(Expenses *e);
void show(const Expenses *e);
int main()
{
struct Expenses e;
fill(&e);
show(&e);
system("pause");
return 0;
}
void fill(Expenses *e)
{
for (int i = 0; i < Seasons; i++)
{
cout << "Enter " << Snames[i] << " expenses: ";
cin >> e->expenses[i];
}
}
void show(const Expenses *e)
{
double total = 0.0;
cout << "\nEXPENSES\n";
for (int i = 0; i < Seasons; i++)
{
cout << Snames[i] << ": $" << e->expenses[i] << endl;
total += e->expenses[i];
}
cout << "Total Expenses: $" << total << endl;
}
运行结果:
9. student
这个练习让您编写处理数组和结构的函数。下面是程序的框架,请提供其中描述的函数,以完成该程序。
#include <iostream>
using namespace std;
const int SLEN = 30;
struct student
{
char fullname[SLEN];
char hobby[SLEN];
int ooplevel;
};
// getinfo () has two arguments: a pointer to the first element of
// an array of student structures and an int representing the
// number of elements 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 displays its contents
void display1(student st);
// display2 () takes the address of student structure as an
// argument and displays the structure's contents
void display2(const student *ps);
// display3 () takes the address of the first element of an array
// of student structures and the number of array elements as
// arguments and displays the contents of the structures
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;
}
代码:
#include <iostream>
using namespace std;
const int SLEN = 30;
struct student
{
char fullname[SLEN];
char hobby[SLEN];
int ooplevel;
};
// getinfo () has two arguments: a pointer to the first element of
// an array of student structures and an int representing the
// number of elements 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 displays its contents
void display1(student st);
// display2 () takes the address of student structure as an
// argument and displays the structure's contents
void display2(const student *ps);
// display3 () takes the address of the first element of an array
// of student structures and the number of array elements as
// arguments and displays the contents of the structures
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";
system("pause");
return 0;
}
int getinfo(student pa[], int n)
{
int i;
cout << "Please input the students information:" << endl;
for (i = 0; i < n; i++)
{
cout << "Student #" << i + 1 << ": " << endl;
cout << "Fullname: ";
cin.getline(pa[i].fullname, SLEN);
if (pa[i].fullname[0] == '\0')
break;
cout << "Hobby: ";
if (pa[i].hobby[0] == '\0')
break;
cin.getline(pa[i].hobby, SLEN);
cout << "Ooplevel: ";
if (!(cin >> pa[i].ooplevel))
break;
cin.get();
}
cout << "Enter End!" << endl;
return i;
}
void display1(student st)
{
cout << "fullname:" << st.fullname << " hobby:" << st.hobby << " opplevel:" << st.ooplevel << endl;
}
void display2(const student *ps)
{
cout << "fullname:" << ps->fullname << " hobby:" << ps->hobby << " opplevel:" << ps->ooplevel << endl;
}
void display3(const student pa[], int n)
{
for (int i = 0; i < n; i++)
{
cout << "Student #" << i + 1 << endl;
cout << "fullname:" << pa[i].fullname << " hobby:" << pa[i].hobby << " opplevel:" << pa[i].ooplevel << endl;
}
}
运行结果:
10. calculate()
设计一个名为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;
double add(double, double);
double subtract(double, double);
double multiply(double, double);
double calculate(double, double, double (*func)(double, double));
int main(void)
{
double x, y;
double (*pf[3])(double, double) = {add, subtract, multiply};
cout << "Enter two numbers(q to quit):";
while (cin >> x >> y)
{
for (int i = 0; i < 3; i++)
{
switch (i)
{
case 0:
cout << x << "+" << y << "=" << calculate(x, y, pf[i]) << endl;
break;
case 1:
cout << x << "-" << y << "=" << calculate(x, y, pf[i]) << endl;
break;
case 2:
cout << x << "*" << y << "=" << calculate(x, y, pf[i]) << endl;
break;
}
}
cout << "Enter two numbers(q to quit):";
}
cout << "Done!\n";
system("pause");
return 0;
}
double add(double x, double y)
{
return x + y;
}
double subtract(double x, double y)
{
return x - y;
}
double multiply(double x, double y)
{
return x * y;
}
double calculate(double x, double y, double (*func)(double, double))
{
return (*func)(x, y);
}
运行结果: