C++ Primer Plus章节编程练习第十二章
1
题目
对于下面的类声明:
class Cow{
private:
char name[20];
char* hobby;
double weight;
public:
Cow();
Cow(const char* nm,const char* ho,double wt);
Cow(const Cow &c);
~Cow();
Cow& operator=(const Cow &c);
void ShowCow()const;
};
给这个类提供实现,并编写一个使用所有成员函数的小程序。
题解
#include<iostream>
#include<cstring>
using namespace std;
class Cow{
private:
char name[20];
char* hobby;
double weight;
public:
Cow();
Cow(const char* nm,const char* ho,double wt);
Cow(const Cow &c);
~Cow();
Cow& operator=(const Cow &c);
void ShowCow()const;
};
Cow::Cow(){
name[0]='\0';
hobby=nullptr;
weight=0;
}
Cow::Cow(const char* nm,const char* ho,double wt){
int lena=strlen(nm); //name的复制不能超过最长长度
int len=lena>19?19:lena;
memcpy(name,nm,len); name[len]='\0';//使用memcpy,最后置为0
lena=strlen(ho); //hobby使用深层复制
hobby=new char[lena+1];
strcpy(hobby,ho);
weight=wt;
}
Cow::Cow(const Cow &c){
strcpy(name,c.name);
int len=strlen(c.hobby);
hobby=new char[len+1];
strcpy(hobby,c.hobby);
weight=c.weight;
}
Cow::~Cow(){
delete [] hobby;
}
Cow& Cow::operator=(const Cow &c){
if(this==&c)
return *this;
strcpy(name,c.name);
int len=strlen(c.hobby);
delete[] hobby;
hobby=new char[len+1];
strcpy(hobby,c.hobby);
weight=c.weight;
return *this;
}
void Cow::ShowCow()const{
cout<<"Name : "<<name<<endl;
cout<<"Hobby : "<<(hobby?hobby:"null")<<endl; //初始化为空的时候无法输出,所以要进行判定
cout<<"Weight: "<<weight<<endl;
}
//**************************main函数**************************
int main(){
Cow one;
Cow two("tow","eating",50);
Cow three;
three=two;
Cow four(two);
one.ShowCow();
two.ShowCow();
three.ShowCow();
four.ShowCow();
return 0;
}
2
题目
通过完成下面的工作来改进String类声明(即将String1.h升级为String2.h)。
a.对+运算符进行重载,使之可将两个字符串合并成1个。
b.提供一个Stringlow()成员函数,将字符串中所有的字母字符转换为小写(别忘了cctype系列字符函数)。
c.提供String()成员函数,将字符串中所有字母字符转换成大写。
d.提供一个这样的成员函数,它接受-一个char参数,返回该字符在字符串中出现的次数。
使用下面的程序来测试您的工作:
int main(){
String s1(" and I am a C++ student.");
String s2="Please enter your name: ";
String s3;
cout<<s2;
cin>>s3;
s2="My name is "+s3;
cout<<s2<<".\n";
s2=s2+s1;
s2.Stringup();
cout<<"The string\n"<<s2<<"\ncontains "<<s2.has('A')
<<" 'A' characters in it.\n";
s1="red";
String rgb[3]={String(s1),String("green"),String("blue")};
cout<<"Enter the name of a primary color for mixing light: ";
String ans;
bool success=false;
while(cin>>ans){
ans.Stringlow();
for(int i=0;i<3;i++){
if(ans==rgb[i]){
cout<<"That's right!\n";
success=true;
break;
}
}
if(success)
break;
else
cout<<"Try again!\n";
}
cout<<"Bye\n";
return 0;
}
输出应与下面相似:
Please enter your name: Fretta Farbo
My name is Fretta Farbo.
The string
My NAME IS FRETTA FARBO AND I AM A C== STUDENT.
contains 6 'A' characters in it.
Enter the name of a primary color for mixing light: yellow
Try again!
BLUE
That's right!
Bye
题解
#include<iostream>
#include<cstring>
using namespace std;
class String{
private:
char *str;
int len;
static int num_strings;
static const int CINLIM=80;
public:
String(const char*s);
String();
//复制构造函数
String(const String&);
~String();
int length()const{return len;}
//重载赋值运算符
String& operator=(const String&); //用一个类对象给另一个赋值
String& operator=(const char*); //用字符串给对象赋值
char& operator[](int i); //取下标,可修改
const char&operator[](int i)const; //const取下标,不可修改
//重载比较运算符
friend bool operator<(const String &st1,const String &st2);
friend bool operator>(const String &st1,const String &st2);
friend bool operator==(const String &st1,const String &st2);
//重载输入输出运算符
friend ostream& operator<<(ostream& os,const String&st);
friend istream& operator>>(istream& is,String &st);
//静态成员函数
static int HowMany();
//课后题扩充
//重载+运算符
String& operator+(const String &st);
friend String& operator+(const char* str,String &st);
void Stringlow(); //转化小写
void Stringup(); //转化大写
int has(char ch)const; //统计字符个数
};
int String::num_strings=0;
int String::HowMany(){
return num_strings;
}
String::String(const char*s){
len=strlen(s);
str=new char[len+1];
strcpy(str,s);
num_strings++;
}
String::String(){
len=0;
str=new char[1];
str[0]='\0';
num_strings++;
}
String::String(const String &st){
num_strings++;
len=st.len;
str=new char[len+1];
strcpy(str,st.str);
}
String::~String(){
--num_strings;
delete[] str;
}
String & String::operator=(const String &st){
if(this==&st)
return *this;
delete[] str;
len=st.len;
str=new char[len+1];
strcpy(str,st.str);
return *this;
}
String & String::operator=(const char*s){
delete[] str;
len=strlen(s);
str=new char[len+1];
strcpy(str,s);
return *this;
}
char & String::operator[](int i){
return str[i];
}
const char & String::operator[](int i)const{
return str[i];
}
bool operator<(const String&st1,const String &st2){
return (strcmp(st1.str,st2.str)<0);
}
bool operator>(const String&st1,const String &st2){
return st2<st1;
}
bool operator==(const String&st1,const String &st2){
return (strcmp(st1.str,st2.str)==0);
}
ostream & operator<<(ostream& os,const String &st){
os<<st.str;
return os;
}
istream & operator>>(istream& is,String &st){
char temp[String::CINLIM];
is.get(temp,String::CINLIM);
if(is)
st=temp; //使用了const char* 参数的重载运算符
while(is&&is.get()!='\n') //吸收多余字符
continue;
return is;
}
//成员函数版本的+运算符重载,
String& String::operator+(const String &st){
int totallen=len+st.len;
char *temp=new char[totallen+1]; //先合成一个
memcpy(temp,str,len);
memcpy(temp+len,st.str,st.len);
temp[totallen]='\0';
delete[] str;
str=new char[totallen+1];
strcpy(str,temp);
delete[] temp;
len=totallen; //注意更新字符串长度
return *this;
}
//友元函数版本的+运算符重载,处理办法类似于成员函数版本
String& operator+(const char* str,String &st){
int length=strlen(str);
int totallen=length+st.len;
char *temp=new char[totallen+1];
memcpy(temp,str,length);
memcpy(temp+length,st.str,st.len);
temp[totallen]='\0';
delete[] st.str;
st.str=new char[totallen+1];
strcpy(st.str,temp);
delete[] temp;
st.len=totallen;
return st;
}
void String::Stringlow(){
for(int i=0;i<len;i++)
str[i]=tolower(str[i]);
}
void String::Stringup(){
for(int i=0;i<len;i++)
str[i]=toupper(str[i]);
}
int String::has(char ch)const{
int cnt=0;
for(int i=0;i<len;i++)
if(str[i]==ch) cnt++;
return cnt;
}
//******************测试函数*************************
int main(){
String s1(" and I am a C++ student.");
String s2="Please enter your name: ";
String s3;
cout<<s2;
cin>>s3;
s2="My name is "+s3;
cout<<s2<<".\n";
s2=s2+s1;
s2.Stringup();
cout<<"The string\n"<<s2<<"\ncontains "<<s2.has('A')
<<" 'A' characters in it.\n";
s1="red";
String rgb[3]={String(s1),String("green"),String("blue")};
cout<<"Enter the name of a primary color for mixing light: ";
String ans;
bool success=false;
while(cin>>ans){
ans.Stringlow();
for(int i=0;i<3;i++){
if(ans==rgb[i]){
cout<<"That's right!\n";
success=true;
break;
}
}
if(success)
break;
else
cout<<"Try again!\n";
}
cout<<"Bye\n";
return 0;
}
3
题目
新编写程序清单10.7和程序清单10.8描述的Stock类,使之使用动态分配的内存,而不是string类对象来存储股票名称。另外,使用重载的operator<<()定义代替show()成员函数。再使用程序清单10.9测试新的定义程序。
题解
#include<iostream>
#include<cstring>
class Stock{
private:
enum{LEN=100};
char* company;
long shares;
double share_val;
double total_val;
void set_tot(){total_val=share_val*shares;}
public:
Stock();
Stock(const char* co,long n=0,double pr=0.0);
~Stock();
void buy(long num,double price);
void sell(long num,double price);
void update(double price);
friend std::ostream& operator<<(std::ostream &os,const Stock& s);
const Stock&topval(const Stock& s)const;
};
//默认构造函数
Stock::Stock(){
company=nullptr;
shares=0;
share_val=0.0;
total_val=0.0;
}
//重载的构造函数
Stock::Stock(const char* co,long n,double pr){
int len=std::strlen(co);
company=new char[len+1];
std::strcpy(company,co);
if(n<0){
std::cout<<"Number of shares can't be negative; "
<<company<<" shares set to 0\n";
shares=0;
}
else
shares=n;
share_val=pr;
set_tot();
}
//析构函数
Stock::~Stock(){
delete[] company;
}
void Stock::buy(long num,double price){
if(num<0){
std::cout<<"Number of shares purchased can't be negetive."
<<"Transaction is borted.\n";
}
else{
shares+=num;
share_val=price;
set_tot();
}
}
void Stock::sell(long num,double price){
using std::cout;
if(num<0){
cout<<"Number of shares sold can't be negative "
<<"Transaction is aborted\n";
}
else if(num>shares){
cout<<"You can't sell more than you hav! "
<<"Transaction is aborted.\n";
}
else{
shares-=num;
share_val=price;
set_tot();
}
}
void Stock::update(double price){
share_val=price;
set_tot();
}
std::ostream& operator<<(std::ostream &os,const Stock& s){
using std::ios_base;
ios_base::fmtflags orig=os.setf(ios_base::fixed,ios_base::floatfield);
std::streamsize prec=os.precision(3);
os<<"Company: "<<s.company
<<" Shares: $"<<s.shares<<"\n"
<<" Shares Price: $"<<s.share_val;
os.precision(2);
os<<" Total Worth: $"<<s.total_val<<"\n";
os.setf(orig,ios_base::floatfield);
os.precision(prec);
return os;
}
const Stock&Stock::topval(const Stock& s)const{
if(s.total_val>total_val)
return s;
else
return *this;
}
const int STKS=4;
//主函数
int main(){
Stock stocks[STKS]={
Stock("NanoSmart",12,20.0),
Stock("Boffo Objects",200,2.0),
Stock("Monolithic Obelisks",130,3.25),
Stock("Fleep Enterprises",60,6.5),
};
std::cout<<"Stock holdings:\n";
int st;
for(st=0;st<STKS;st++)
std::cout<<stocks[st];
const Stock *top=&stocks[0];
for(st=1;st<STKS;st++)
top=&top->topval(stocks[st]);
std::cout<<"\nMost valueable holding:\n"<<*top;
return 0;
}
4
题目
请看下面程序清单10.10定义的Stack类的变量:
typedef unsigned long Item;
class Stack{
private:
enum{MAX=10};
Item * pitems;
int size;
int top;
public:
Stack(int n=MAX);
Stack(const Stack &st);
~Stack();
bool isempty()const;
bool isfull()const;
bool push(const Item &item);
bool pop(Item &item);
Stack& operator=(const Stack &st);
};
正如私有成员表明的,这个类使用动态分配的数组来保存栈项。请重新编写方法,以适应这种新的表示法,并编写-一个程序来演示所有的方法,包括复制构造函数和赋值运算符。
题解
#include<iostream>
#include<cctype>
typedef unsigned long Item;
class Stack{
private:
enum{MAX=10};
Item * pitems;
int size;
int top;
public:
Stack(int n=MAX);
Stack(const Stack &st);
~Stack();
bool isempty()const;
bool isfull()const;
bool push(const Item &item);
bool pop(Item &item);
Stack& operator=(const Stack &st);
};
Stack::Stack(int n){
pitems=new Item[n];
size=n;
top=0;
}
Stack::Stack(const Stack &st){
pitems=new Item[st.size];
for(int i=0;i<st.size;i++)
pitems[i]=st.pitems[i];
size=st.size;
top=st.top;
}
Stack::~Stack(){
delete[] pitems;
}
bool Stack::isempty()const{
return top==0;
}
bool Stack::isfull()const{
return top==size;
}
bool Stack::push(const Item &item){
if(top<size){
pitems[top++]=item;
return true;
}
else
return false;
}
bool Stack::pop(Item &item){
if(top>0){
item=pitems[--top];
return true;
}
else
return false;
}
Stack& Stack::operator=(const Stack &st){
pitems=new Item[st.size];
for(int i=0;i<st.size;i++)
pitems[i]=st.pitems[i];
size=st.size;
top=st.top;
return *this;
}
int main(){
using namespace std;
Stack st;
Stack last_st;
char ch;
unsigned long po;
cout<<"Please enter A to add a Purchase order,\n"
<<"p to process a PO, or Q to quit.\n";
while(cin>>ch&&toupper(ch)!='Q'){
while(cin.get()!='\n')
continue;
if(!isalpha(ch)){
cout<<"\a";
continue;
}
switch(ch){
case 'A':
case 'a': cout<<"Enter a PO number to add: ";
cin>>po;
if(st.isfull())
cout<<"stack already full\n";
else
st.push(po);
break;
case 'P':
case 'p': if(st.isempty())
cout<<"Stack already empty\n";
else{
st.pop(po);
cout<<"PO #"<<po<<" popped\n";
}
break;
}
last_st=st;
cout<<"Please enter A to add a purchase order,\n"
<<"P to process a PO, or Q to quit.\n";
}
Stack last_st_cpoy(last_st);
if(!last_st.isempty()){
cout<<"Last stack contains(from top to bottom):\n";
while(!last_st.isempty()){
Item temp;
last_st.pop(temp);
cout<<temp<<" ";
}
}
cout<<"\n";
cout<<"Bye\n";
return 0;
}
5
题目
Heather银行进行的研究表明,ATM客户不希望排队时间不超过1分钟。使用程序清单12.10中的模拟,找出要使平均等候时间为1分钟,每小时到达的客户数应为多少(试验时间不短于100小时)?
题解
//使用queue.cpp测试即可,没有固定条件(队列大小),无法有唯一结果
6
题目
Heather银行想知道,如果再开设一台ATM,情况将如何。请对模拟进行修改,以包含两个队列。假设当第一台ATM前的排队人数少于第二台ATM时,客户将排在第一队,否则将排在第二队。然后再找出要使平均等候时间为1分钟,每小时到达的客户数应该为多少(注意,这是一个非线性问题,即将ATM数量加倍,并不能保证每小时处理的客户数量也翻倍,并确保客户等候的时间少于1分钟)?
题解
// 没有固定条件(队列大小),无法有唯一结果
Comments | NOTHING