C++ Primier Plus(第六版) 第九章 内存模型和名称空间 编程练习答案
1. 下面是一个头文件:
// golf.h -- for ex1.cpp
const int Len = 40;
struct golf
{
char fullname[Len];
int handicap;
};
// non-interactive version
// function sets golf structure to provided name, handicap
// using values passed as arguments to function
void setgolf(golf & g, const char * name, int hc);
// interactive version
// function solicits name and handicap from user
// and sets the members of g to the values entered
// return 1 if name is entered,0 if name is empty string
int setgolf(golf & g);
// function resets handicap to new value
void handicap(golf & g, int hc);
// funciton displays contents of golf structure
void showgolf(const golf & g);
注意到setgolf()被重载,可以这样使用其第一个版本:
golf ann;
setgolf(ann, "Ann Birdfree", 24);
上述函数调用提供了存储在ann结构中的信息。可以这样使用第二个版本:
golf andy;
setgolf(andy);
上述函数将提示用户输入姓名和等级,并将它们存储在andy结构中。这个函数可以(但不是不一定必须)在内部使用第一个版本。根据这个头文件,创建一个多文件程序。其中一个文件名为golf.cpp,它提供了与头文件中的原型匹配的函数定义;另一个文件包含main(),并演示原型化函数的所有特性。例如,包含一个让用户输入的循环,并使用输入的数据来填充一个由golf结构组成的数组,数组被填满或用户将高尔夫选手的姓名设置为空字符串时,循环将结束。main()函数只是用头文件中原型化的函数来访问golf结构。
本题首先按照题目的要求编写golf.cpp文件,这几个函数没有什么难度,在int setgolf(golf & g);函数中,忘了将临时定义的值name与handicap赋给g,需要注意的是字符串数组赋值需要用到函数strcpy();判断字符串为空需要用到strcmp()函数。主函数文件实现了输入用户的功能,显示用户的功能,修改用户等级的功能。代码如下:
// golf.cpp -- defination of dealing with golf function
#include<iostream>
#include<cstring>
#include"golf.h"
void setgolf(golf & g, const char * name, int hc)
{
strcpy(g.fullname, name);
g.handicap = hc;
}
int setgolf(golf & g)
{
using std::cout;
using std::cin;
using std::endl;
char name[Len];
int hc;
cout << "Enter the users'name: ";
cin.getline(name, Len);
if(!strcmp(name,""))
return 0;
strcpy(g.fullname,name);
cout << "Enter the users'level: ";
while(!(cin>>hc))
{
cin.clear();
while(cin.get()!='\n')
continue;
cout << "Bad input, please enter a integer: ";
}
g.handicap = hc;
cin.get();
return 1;
}
void handicap(golf & g, int hc)
{
g.handicap = hc;
}
void showgolf(const golf & g)
{
using std::cout;
cout << "Name: " << g.fullname << ", level: " << g.handicap << "\n" ;
}
// main_ex1.cpp -- using golf.cpp's function
#include<iostream>
#include"golf.h"
const int Arsize = 5;
int main()
{
using std::cout;
using std::cin;
using std::endl;
char name[Len];
int hd, number;
int count = 0;
golf gar[Arsize];
cout << "Enter the Users' name and level(enter empty string to name to quit):\n";
for(int i = 0; i < Arsize; i++)
{
cout << "User #" << i + 1 << ":\n";
int end_flag = setgolf(gar[i]);
if (end_flag == 0)
break;
count++;
}
for(int i = 0; i < count; i++)
{
cout << "User #" << i + 1 << ":\t";
showgolf(gar[i]);
}
// using handicap
cout << "Enter the number of user you need to change level(q to quit): ";
while(cin >> number)
{
cout << "The new Level: ";
cin >> hd;
handicap(gar[number - 1], hd);
cout << "Enter next number(q to quit): ";
}
cout << "The new golf users list:\n";
for(int i = 0; i < count; i++)
{
cout << "User #" << i + 1 << ":\t";
showgolf(gar[i]);
}
cout << "Bye\n";
return 0;
}
运行结果如下:
2. 修改程序清单9.9:用string对象代替字符数组。这样,该程序将不在需要检查输入的字符串是否过长,同时可以将输入的字符串同字符串""进行比较,以判断是否为空行。
本题首先增加头文件string,接下来修改函数strcount()的函数声明,修改完函数声明之后重点修改函数定义,定义需要修改的是while的判断条件,str为const常量,因此应该用判断str[count]是否为'\0'的方法,接着修改主函数调用,样例代码如下:
// ex2.cpp -- using a static local variable and using string
#include<iostream>
#include<string>
// constants
const int ArSize = 10;
// function prototype
void strcount(const std::string str);
int main()
{
using namespace std;
string input;
char next;
cout << "Enter a line:\n";
getline(cin, input);
while(cin)
{ if(input == "")
break;
strcount(input);
cout << "Enter next line(empty line to quit):\n";
getline(cin, input);
}
cout << "Bye\n";
}
void strcount(const std::string str)
{
using namespace std;
static int total = 0;
int count = 0;
cout << "\"" << str << "\" contains ";
while(str[count])
{
count++;
}
total += count;
cout << count << " characters\n";
cout << total << " characters total\n";
}
运行结果如下:
3. 下面是一个结构声明:
struct chaff
{
char dross[20];
int slag;
};
编写一个程序,使用定位new运算符将一个包含两个这种结构的数组放在一个缓冲区中。然后,给结构的成员赋值(对于char数组,使用函数strcpy()),并使用一个循环来显示内容。一种方法是程序清单9.10那样将一个静态数组用作缓冲区;另一种方法是使用常规new运算符来分配缓冲区。
本题考查的是定位new运算符的使用,这里使用new来创建动态缓冲区,需要最后释放掉该缓冲区。使用了两个函数,分别给结构赋值和显示结构,样例代码如下:
// ex3.cpp -- using placement new to store structure array
#include<iostream>
#include<cstring>
const int BUF = 500;
const int CSize = 20;
struct chaff
{
char dross[CSize];
int slag;
};
// dynamic ram
char * buffer = new char[BUF];
//enter dross is empty string to stop enter
int setchaff(chaff & c);
void showchaff(const chaff & c);
int main()
{
using std::cout;
using std::cin;
using std::endl;
int num;
int count = 0; // store the enter num of chaff
cout << "Enter the number of chaff: ";
cin >> num;
cin.get();
chaff *arr = new(buffer) chaff[num];
for(int i = 0; i < num; i++)
{
cout << "Chaff #" << i + 1 << ":\n";
if(!setchaff(arr[i]))
break;
count++;
}
for(int i = 0; i < count; i++)
{
cout << "Chaff #" << i + 1 << ":\t";
showchaff(arr[i]);
}
cout << "Bye\n";
delete []buffer;
return 0;
}
int setchaff(chaff & c)
{
using std::cout;
using std::cin;
char name[CSize];
cout << "Dross(enter empty string to quit): ";
cin.getline(name,CSize);
if(!strcmp(name,""))
return 0;
strcpy(c.dross,name);
cout << "slag: ";
cin >> c.slag;
cin.get();
return 1;
}
void showchaff(const chaff & c)
{
using std::cout;
cout << "Dross: " << c.dross << ", slag = " << c.slag << "\n";
}
运行结果如下:
4. 请基于下面这个名称空间编写一个由3个文件组成的程序:
namespace SALES
{
const int QUARTERS = 4;
struct Sales
{
double sales[QUARTERS];
double average;
double max;
double min;
};
// copies the lesser of 4 or n items for the array ar
// to the sales member of s and computes and stores the
// average, maximum,and minimum values of the entered items;
// remaining elements of sales, if any, set to 0
void setSales(Sales & s, const double ar[], int n);
// gathers sales for 4 quraters interactively, stores them
// in the sales member of s and computes and stores the
// average, maximum, and minimum values
void setSales(Sales & s);
// display all information in structure s
void showSales(const Sales & s);
}
第一个文件时一个头文件,其中包含名称空间;第二文件是一个源代码文件,它对这个名称空间进行拓展,以提供这三个函数的定义;第三个文件声明两个Sales对象,并使用setSales()的交互版本为一个结构提供值,然后使用setSales()的非交互式版本为另一个结构提供值。另外它还使用showSales()来显示这个结构提供值。
本题比较难,编程过程中遇到了很多错误;第一个难点是void setSales(Sales & s, const double ar[], int n);函数的实现,要求函数找出数组ar中四个较小的值,我采用了一个方法,首先找出最小值,找次小值的时候给首先赋初始值为最大值,让每一个值先判断大于最小值,大于然后和次小值比较大小,给次小值赋两个中较小的值,由此来得到最小值。
还有就是命名空间的使用我还不够熟悉,刚开始联合编译时,编译出现了错误。原因是没有将函数的定义补充到命名空间中,编译时找不到函数的定义。声明静态函数时应该在补充命名空间的上方声明,这样命名空间里的函数参可以调用这些函数。样例代码如下:
// sale.cpp -- function definiation of sale
#include<iostream>
#include"sale.h"
static double find_min(const double ar[], int n);
static double find_max(const double ar[], int n);
static double average(const double ar[], int n);
static double * find_4less(const double ar[], int n);
namespace SALES
{
void setSales(Sales & s, const double ar[], int n)
{
s.min = find_min(ar, n);
s.max = find_max(ar, n);
s.average = average(ar,n);
if(n <= 4)
{
int i;
for(i = 0; i < n; i++)
s.sales[i] = ar[i];
for(;i < 4; i++)
s.sales[i] = 0;
}
else
{
for(int i = 0; i < 4; i++)
s.sales[i] = find_4less(ar, n)[i];
}
}
void setSales(Sales & s)
{
using std::cout;
using std::cin;
cout << "Enter four sales:\n";
for(int i = 0; i < 4; i++)
{
cout << "Sales #" << i + 1 << ": ";
cin >> s.sales[i];
}
s.min = find_min(s.sales, 4);
s.max = find_max(s.sales, 4);
s.average = average(s.sales, 4);
}
void showSales(const Sales & s)
{
using std::cout;
cout << "Sales list:\n";
for(int i = 0; i < 4; i++)
{
cout << "Sales #" << i + 1 << ": ";
cout << s.sales[i] << "\t";
}
cout << "\n";
cout << "Average = " << s.average << ", max = " << s.max;
cout << ", min = " << s.min << "\n";
}
}
double find_min(const double ar[], int n)
{
double min = ar[0];
for(int i = 0; i < n; i++)
min = min < ar[i] ? min : ar[i];
return min;
}
double find_max(const double ar[], int n)
{
double max = ar[0];
for(int i = 0; i < n; i++)
max = max < ar[i] ? ar[i] : max;
return max;
}
double average(const double ar[], int n)
{
double sum = 0;
for(int i = 0; i < n; i++)
sum += ar[i];
return sum / n;
}
static double * find_4less(const double ar[], int n)
{
double * lesser4 = new double[4];
double lesser;
lesser4[0] = find_min(ar, n);
for(int i = 1; i < 4; i++)
{
lesser = find_max(ar, n);
for(int j = 0; j < n; j++)
{
if(ar[j] > lesser4[i-1])
lesser = lesser < ar[j] ? lesser : ar[j];
}
lesser4[i] = lesser;
}
return lesser4;
}
// ex4.cpp -- main() of sale.cpp
#include<iostream>
#include"sale.h"
int main()
{
using namespace SALES;
using std::cout;
Sales s1,s2;
double arr[6] = {1111.1, 666.6, 999.9, 333.3, 2222.2, 1234.5};
setSales(s1);
showSales(s1);
setSales(s2, arr, 6);
showSales(s2);
cout << "Bye\n";
return 0;
}
运行结果如下: