C++ Primer Plus第十二章课后习题总结
1. 对于下面的类声明:
class Cow {
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; // display all cow data
};
给这个类提供实现,并编写一个使用所有成员函数的小程序。
Cow.h:
#ifndef COW_H
#define COW_H
class Cow {
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; // display all cow data
};
#endif
Cow.cpp:
#include "Cow.h"
#include <iostream>
#include <cstring>
using namespace std;
Cow::Cow(){
name[0] = '\0';
hobby = nullptr;
weight = 0.0;
}
Cow::Cow(const char * nm, const char * ho, double wt){
strncpy(name, nm, 20);
int len2 = strlen(ho);
hobby = new char[len2 + 1];
strcpy(hobby, ho);
weight = wt;
}
Cow::Cow(const Cow &c){
strncpy(name, c.name, 20);
int len2 = strlen(c.hobby);
hobby = new char[len2 + 1];
strcpy(hobby, c.hobby);
weight = c.weight;
}
Cow::~Cow(){
delete[] hobby;
}
Cow & Cow::operator=(const Cow & c){
if(this == &c)
return *this;
strncpy(name, c.name, 20);
delete[] hobby;
int len2 = strlen(c.hobby);
hobby = new char[len2 + 1];
strcpy(hobby, c.hobby);
weight = c.weight;
return *this;
}
void Cow::ShowCow() const{
cout << "name:" << name;
cout << endl;
cout << "hobby:" << hobby;
cout << endl;
cout << "weight:" << weight;
cout << endl;
cout << endl;
}
main.cpp:
#include "Cow.h"
#include <iostream>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv) {
//c1调用构造函数Cow(const char * nm, const char * ho, double wt);
Cow c1("xiaoyu", "eating", 100);
c1.ShowCow();
//c2调用复制构造函数Cow(const Cow &c);
Cow c2 = c1;
c2.ShowCow();
//c3调用赋值运算符重载函数Cow & operator=(const Cow & c);
Cow c3;
c3 = c2;
c3.ShowCow();
return 0;
}
运行结果:
2. 通过下面的工作来改进String类声明(即将String1.h升级为String2.h)。
a. 对+运算符进行重载,使之可将两个字符串合并成一个。
b. 提供一个Stringlow()成员函数,将字符串中所有的字母字符转换为小写(别忘了cctype系列字符函数)。
c. 提供String()成员函数,将字符串中所有字母字符转换成大写。
d. 提供一个这样的成员函数,它接受一个char参数,返回该字符在字符串中出现的次数。
使用下面的程序来测试您的工作:
// pe12_2.cpp
#include <iostream>
using namespace std;
#include "string2.h"
int main()
{
String s1(" and I am a C++ student.");
String s2 = "Please enter your name: ";
String s3;
cout << s2; // overloaded << operator
cin >> s3; // overloaded >> operator
s2 = "My name is " + s3; // overloaded =, + operators
cout << s2 << ".\n";
s2 = s2 + s1;
s2.stringup(); // converts string to uppercase
cout << "The string\n" << s2 << "\ncontains " << s2.has('A')
<< " 'A' characters in it.\n";
s1 = "red"; // String(const char *),
// then String & operator=(const String&)
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(); // converts string to lowercase
for (int i = 0; i < 3; i++)
{
if (ans == rgb[i]) // overloaded == operator
{
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
String.h:
#ifndef STRING_H
#define STRING_H
#include <iostream>
using std::ostream;
using std::istream;
class String{
private:
char *str;
int len;
//static int num_strings;
public:
static const int CINLIM = 80;
//constructors and other methods
String();
String(const char*);
String(const String &);
~String();
int length()const{return len;}
void stringlow();
void stringup();
int has(char c)const;
//overload operator methods
String operator+(String &);
// String operator+(const char *s) const;
String &operator=(const String &);
String &operator=(const char *);
char &operator[](int);
const char &operator[](int)const;
//overload operator friends
//friend bool operator<(const String &, const String &);
//friend bool operator>(const String &, const String &);
friend bool operator==(const String &, const String &);
friend String operator+(const char *, String &);
friend ostream &operator<<(ostream &, const String &);
friend istream &operator>>(istream &, String &);
//static function
//static int HowMany();
};
#endif
String.cpp:
#include "String.h"
#include <cstring>
#include <cctype>
//constructors and other methods
String::String(){
str = new char[1];
str[0] = '\0';
len = 0;
}
String::String(const char* s){
len = strlen(s);
str = new char[len + 1];
strcpy(str, s);
}
String::String(const String &s){
len = s.len;
str = new char[len + 1];
strcpy(str, s.str);
}
String::~String(){
delete[] str;
}
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 c)const{
int ch = 0;
for(int i = 0; i < len; i++){
if(str[i] == '\n'){
break;
}
if(str[i] == 'c'){
ch++;
}
}
return ch;
}
//overload operator methods
String String::operator+(String &s){
int lengt = len + s.len;
char *temp = new char[lengt + 1];
strcpy(temp, str);
strcat(temp, s.str);
String result = temp;//调用构造函数
delete[] temp;
return result;
}
//String String::operator+(const char *s) const {
// String tmp = s;
// String sum = *this + tmp;
// return sum;
//}
String &String::operator=(const String &st){
if(this == &st)
return *this;
delete[] str;
len = strlen(st.str);
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];
}
//overload operator friends
bool operator==(const String &str1, const String &str2){
return (strcmp(str1.str, str2.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;//使用了赋值运算符重载函数
while(is && is.get() != '\n')
continue;
return is;
}
String operator+(const char *s, String &ss){
return String(s) + ss;
}
main.cpp:
#include "String.h"
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv) {
String s1(" and I am a C++ student.");//constructor
String s2 = "Please enter your name: ";//overloaded = operator
String s3;
cout << s2; // overloaded << operator
cin >> s3; // overloaded >> operator
s2 = "My name is " + s3; // overloaded =, + operators(friend)
cout << s2 << ".\n";// overloaded << operator
s2 = s2 + s1;// overloaded =, + operators
s2.stringup(); // converts string to uppercase
cout << "The string\n" << s2 << "\ncontains " << s2.has('A')
<< " 'A' characters in it.\n";// overloaded << operator
s1 = "red"; // String(const char *),
// then String operator=(const String&)
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(); // converts string to lowercase
for (int i = 0; i < 3; i++)
{
if (ans == rgb[i]) // overloaded == operator
{
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测试新的定义程序。
Stock.h:
#ifndef STOCK_H
#define STOCK_H
#include <iostream>
using namespace std;
class Stock{
private:
char *company;
int shares;
double share_val;
double total_val;
void set_tot() { total_val = shares * share_val; }
public:
Stock(); // default constructor
Stock(const char * co, long n, double pr);
~Stock(); // do-nothing destructor
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
friend ostream& operator<<(ostream& os, const Stock& st);
const Stock& topval(const Stock& s) const;
};
#endif
Stock.cpp:
#include "stock.h"
#include <cstring>
#include <iostream>
using namespace std;
Stock::Stock() {
company = new char[8];
strcpy(company, "no name");
shares = 0;
share_val = 0.0;
total_val = 0.0;
}
Stock::Stock(const char * co, long n, double pr) {
company = new char[strlen(co) + 1];
strcpy(company, co);
if(n < 0) {
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) {
cout << "Number of shares purchased can’t be negative. "
<< "Transaction is aborted.\n";
} else {
shares += num;
share_val = price;
set_tot();
}
}
void Stock::sell(long num, double price) {
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 have! "
<< "Transaction is aborted.\n";
} else {
shares -= num;
share_val = price;
set_tot();
}
}
void Stock::update(double price) {
share_val = price;
set_tot();
}
ostream& operator<<(ostream& os, const Stock& st) {
ios_base::fmtflags orig = os.setf(ios_base::fixed, ios_base::floatfield);
std::streamsize prec = os.precision(3);
os << "Company: " << st.company << " Shares: " << st.shares << '\n';
os << " Share Price: $" << st.share_val;
// set format to #.##
os.precision(2);
os << " Total Worth: $" << st.total_val << '\n';
// restore original format
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;
}
main.cpp:
#include <iostream>
#include "stock.h"
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
const int STKS = 4;
int main(int argc, char** argv) {
Stock stocks[STKS] = {
Stock("NanoSmart", 12, 20.0),
Stock("Boffo objects", 200, 2.0),
Stock("Monolithic belisks", 130, 3.25),
Stock("Fleep Enterprises", 60, 6.5),
};
cout << "Stock holdings:\n";
int st;
for(st = 0; st < STKS; st++){
cout << stocks[st];
}
const Stock *top = &stocks[0];
for(st = 1; st < STKS; st++){
top = &top->topval(stocks[st]);
}
cout << "\nMost valuable holding:\n";
cout << *top;
return 0;
}
输出结果:
4.请看下面程序清单10.10定义的Stack类的变量:
// stack.h -- class declaration for the stack ADT
typedef unsigned long Item;
class Stack
{
private:
enum {MAX = 10}; // constant specific to class
Item * pitems; // holds stack items
int size; // number of elements in stack
int top; // index for top stack item
public:
Stack(int n = MAX); // creates stack with n elements
Stack(const Stack & st);
~Stack();
bool isempty() const;
bool isfull() const;
// push() returns false if stack already is full, true otherwise
bool push(const Item & item); // add item to stack
// pop() returns false if stack already is empty, true otherwise
bool pop(Item & item); // pop top into item
Stack & operator=(const Stack & st);
};
正如私有成员表明的,这个类使用动态分配的数组来保存栈项。请重新编写方法,以适应这种新的表示法,并编写一个程序来演示所有的方法,包括复制构造函数和赋值运算符。
Stack.h:
#ifndef STACK_H
#define STACK_H
#include <iostream>
using namespace std;
typedef unsigned long Item;
class Stack {
private:
enum {MAX = 10}; // constant specific to class
Item * pitems; // holds stack items
int size; // number of elements in stack
int top; // index for top stack item
public:
Stack(int n = MAX); // creates stack with n elements
Stack(Item* it, int s, int t);
Stack(const Stack & st);
~Stack();
bool isempty() const;
bool isfull() const;
// push() returns false if stack already is full, true otherwise
bool push(const Item & item); // add item to stack
// pop() returns false if stack already is empty, true otherwise
bool pop(Item & item); // pop top into item
Stack & operator=(const Stack & st);
friend ostream &operator<<(ostream &, const Stack &);
};
#endif
Stack.cpp:
#include "Stack.h"
Stack::Stack(int n){
size = MAX;
top = 0;
pitems = new Item[size];
for(int i = 0; i < size; i++)
pitems[i] = 0;
}
Stack::Stack(Item* it, int s, int t){
size = s;
top = t;
pitems = new Item[s];
for(int i = 0; i < size; i++)
pitems[i] = it[i];
}
Stack::Stack(const Stack & st){
size = st.size;
top = st.top;
pitems = new Item[size];
for(int i = 0; i < size; i++)
pitems[i] = st.pitems[i];
}
Stack::~Stack(){
delete[] pitems;
size = 0;
top = 0;
}
bool Stack::isempty() const{
if(top == 0)
return true;
else
return false;
}
bool Stack::isfull() const{
if(top == MAX)
return true;
else
return false;
}
bool Stack::push(const Item & item){
if(this->Stack::isfull())
return false;
size += 1;
top++;
pitems[top] = item;
}
bool Stack::pop(Item & item){
if(this->isempty())
return false;
size -= 1;
item = pitems[top];
top--;
}
Stack & Stack::operator=(const Stack & st){
if(this == &st)
return *this;
size = st.size;
top = st.top;
delete[] pitems;
pitems = new Item[size];
for(int i = 0; i < size; i++)
pitems[i] = st.pitems[i];
return *this;
}
ostream &operator<<(ostream &os, const Stack &s){
for(int i = 0; i < s.size; i++)
os << s.pitems[i] << endl;
return os;
}
main.cpp:
#include <iostream>
#include <cctype>
#include "Stack.h"
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv) {
Stack st; // create an empty stack
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;
}
cout << "Please enter A to add a purchase order,\n"
<< "P to process a PO, or Q to quit.\n";
}
Stack st2;
st2 = st;
cout << "stack2 = stack is:\n" << st2;
cout << "Bye\n";
return 0;
}
输出如下: