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
[code]//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
[code]//cow.cpp #include <iostream> #include <cstring> #include "cow.h" using namespace std; Cow::Cow() { strcpy(name, "None"); hobby = new char[1]; hobby[0] = '\0'; weight = 0.0; } Cow::Cow(const char * nm, const char * ho, double wt) { strcpy(name, nm); hobby = new char[strlen(ho)+1]; strcpy(hobby, ho); weight = wt; } Cow::Cow(const Cow & c) { strcpy(name, c.name); hobby = new char[strlen(c.hobby)+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); delete [] hobby; hobby = new char[strlen(c.hobby)+1]; strcpy(hobby, c.hobby); weight = c.weight; return *this; } void Cow::ShowCow() const { cout << "Name:\t" << name << endl; cout << "Hobby:\t" << hobby << endl; cout << "Weight:\t" << weight << endl; cout << endl; }
//usecow.cpp
[code]//usecow.cpp #include <iostream> #include <cstring> #include "cow.h" using namespace std; int main() { Cow one; //使用默认构造函数 Cow two("Lucy", "吃草", 125.25); //使用构造函数 one.ShowCow(); two.ShowCow(); one = two; //使用重载赋值运算符 Cow three(one); //使用复制构造函数 Cow four = one; //使用复制构造函数 one.ShowCow(); three.ShowCow(); four.ShowCow(); return 0; }
2. 通过完成下面的工作来改进String类声明(即将String1.h升级为String2.h)
a.对+运算符进行重载,使之可将两个字符串合并成1个
b.提供一个Stringlow()成员函数,将字符串中所有的字母字符转换为小写(别忘了cctype系列字符函数)
c.提供Stringup()成员函数,将字符串中所有字母字符转换成大写
d.提供一个这样的成员函数,它接受一个char参数,返回该字符在字符串中出现的次数
使用下面的程序来测试您的工作:
[code]// 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
string1如下:
[code]//string1.h // string1.h -- fixed and augmented string class definition #ifndef STRING1_H_ #define STRING1_H_ #include <iostream> using std::ostream; using std::istream; class String { private: char * str; // pointer to string int len; // length of string static int num_strings; // number of objects static const int CINLIM = 80; // cin input limit public: // constructors and other methods String(const char * s); // constructor String(); // default constructor String(const String &); // copy constructor ~String(); // destructor int length () const { return len; } // overloaded operator methods String & operator=(const String &); String & operator=(const char *); char & operator[](int i); const char & operator[](int i) const; // overloaded operator friends friend bool operator<(const String &st, const String &st2); friend bool operator>(const String &st1, const String &st2); friend bool operator==(const String &st, const String &st2); friend ostream & operator<<(ostream & os, const String & st); friend istream & operator>>(istream & is, String & st); // static function static int HowMany(); }; #endif
[code]//string1.cpp // string1.cpp -- String class methods #include <cstring> // string.h for some #include "string1.h" // includes <iostream> using std::cin; using std::cout; // initializing static class member int String::num_strings = 0; // static method int String::HowMany() { return num_strings; } // class methods String::String(const char * s) // construct String from C string { len = std::strlen(s); // set size str = new char[len + 1]; // allot storage std::strcpy(str, s); // initialize pointer num_strings++; // set object count } String::String() // default constructor { len = 4; str = new char[1]; str[0] = '\0'; // default string num_strings++; } String::String(const String & st) { num_strings++; // handle static member update len = st.len; // same length str = new char [len + 1]; // allot space std::strcpy(str, st.str); // copy string to new location } String::~String() // necessary destructor { --num_strings; // required delete [] str; // required } // overloaded operator methods // assign a String to a String String & String::operator=(const String & st) { if (this == &st) return *this; delete [] str; len = st.len; str = new char[len + 1]; std::strcpy(str, st.str); return *this; } // assign a C string to a String String & String::operator=(const char * s) { delete [] str; len = std::strlen(s); str = new char[len + 1]; std::strcpy(str, s); return *this; } // read-write char access for non-const String char & String::operator[](int i) { return str[i]; } // read-only char access for const String const char & String::operator[](int i) const { return str[i]; } // overloaded operator friends bool operator<(const String &st1, const String &st2) { return (std::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 (std::strcmp(st1.str, st2.str) == 0); } // simple String output ostream & operator<<(ostream & os, const String & st) { os << st.str; return os; } // quick and dirty String input 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; }
2.1 修改后的string2.h
[code]#ifndef STRING2_H_ #define STRING2_H_ #include <iostream> using std::ostream; using std::istream; class String { private: char * str; // pointer to string int len; // length of string static int num_strings; // number of objects static const int CINLIM = 80; // cin input limit public: // constructors and other methods String(const char * s); // constructor String(); // default constructor String(const String &); // copy constructor ~String(); // destructor int length () const { return len; } void stringlow(); //成员函数,转换为小写 void stringup(); //成员函数,转换为大写 int has(const char); //成员函数,统计字符次数 // overloaded operator methods String & operator=(const String &); String & operator=(const char *); char & operator[](int i); const char & operator[](int i) const; // overloaded operator friends friend String operator+(const String &st1, const String &st2); //重载+运算符 friend bool operator<(const String &st, const String &st2); friend bool operator>(const String &st1, const String &st2); friend bool operator==(const String &st, const String &st2); friend ostream & operator<<(ostream & os, const String & st); friend istream & operator>>(istream & is, String & st); // static function static int HowMany(); }; #endif
[code]//string2.cpp // string2.cpp -- String class methods #include <cstring> // string.h for some #include <cctype> #include "string2.h" // includes <iostream> using std::cin; using std::cout; // initializing static class member int String::num_strings = 0; // static method int String::HowMany() { return num_strings; } // class methods String::String(const char * s) // construct String from C string { len = std::strlen(s); // set size str = new char[len + 1]; // allot storage std::strcpy(str, s); // initialize pointer num_strings++; // set object count } String::String() // default constructor { len = 4; str = new char[1]; str[0] = '\0'; // default string num_strings++; } String::String(const String & st) { num_strings++; // handle static member update len = st.len; // same length str = new char [len + 1]; // allot space std::strcpy(str, st.str); // copy string to new location } String::~String() // necessary destructor { --num_strings; // required delete [] str; // required } // overloaded operator methods // assign a String to a String String & String::operator=(const String & st) { if (this == &st) return *this; delete [] str; len = st.len; str = new char[len + 1]; std::strcpy(str, st.str); return *this; } // assign a C string to a String String & String::operator=(const char * s) { delete [] str; len = std::strlen(s); str = new char[len + 1]; std::strcpy(str, s); return *this; } // read-write char access for non-const String char & String::operator[](int i) { return str[i]; } // read-only char access for const String const char & String::operator[](int i) const { return str[i]; } // overloaded operator friends bool operator<(const String &st1, const String &st2) { return (std::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 (std::strcmp(st1.str, st2.str) == 0); } // simple String output ostream & operator<<(ostream & os, const String & st) { os << st.str; return os; } // quick and dirty String input 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; } 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(const char a) //成员函数,统计字符次数 { int num = 0; for (int i = 0; i < len; i++) { if(str[i] == a) num++; } return num; } String operator+(const String &st1, const String &st2) { String add; add.len = st1.len + st2.len; add.str = new char[add.len + 1]; strcpy(add.str, st1.str); strcat(add.str, st2.str); return add; }
2.2 或者 修改后的string2.h
[code]#ifndef STRING2_H_ #define STRING2_H_ #include <iostream> using std::ostream; using std::istream; class String { private: char * str; // pointer to string int len; // length of string static int num_strings; // number of objects static const int CINLIM = 80; // cin input limit public: // constructors and other methods String(const char * s); // constructor String(); // default constructor String(const String &); // copy constructor ~String(); // destructor int length () const { return len; } void stringlow(); //成员函数,转换为小写 void stringup(); //成员函数,转换为大写 int has(const char); //成员函数,统计字符次数 // overloaded operator methods String & operator=(const String &); String & operator=(const char *); char & operator[](int i); const char & operator[](int i) const; // overloaded operator friends friend String operator+(const String &st1, const String &st2); //重载+运算符 String + String friend String operator+(const char * s, const String &st); //重载+运算符 C字符串 + String friend String operator+(const String &st, const char * s) {return (s + st);} //重载+运算符 String + C字符串 friend bool operator<(const String &st, const String &st2); friend bool operator>(const String &st1, const String &st2); friend bool operator==(const String &st, const String &st2); friend ostream & operator<<(ostream & os, const String & st); friend istream & operator>>(istream & is, String & st); // static function static int HowMany(); }; #endif
[code]//string2.cpp // string2.cpp -- String class methods #include <cstring> // string.h for some #include <cctype> #include "string2.h" // includes <iostream> using std::cin; using std::cout; // initializing static class member int String::num_strings = 0; // static method int String::HowMany() { return num_strings; } // class methods String::String(const char * s) // construct String from C string { len = std::strlen(s); // set size str = new char[len + 1]; // allot storage std::strcpy(str, s); // initialize pointer num_strings++; // set object count } String::String() // default constructor { len = 4; str = new char[1]; str[0] = '\0'; // default string num_strings++; } String::String(const String & st) { num_strings++; // handle static member update len = st.len; // same length str = new char [len + 1]; // allot space std::strcpy(str, st.str); // copy string to new location } String::~String() // necessary destructor { --num_strings; // required delete [] str; // required } // overloaded operator methods // assign a String to a String String & String::operator=(const String & st) { if (this == &st) return *this; delete [] str; len = st.len; str = new char[len + 1]; std::strcpy(str, st.str); return *this; } // assign a C string to a String String & String::operator=(const char * s) { delete [] str; len = std::strlen(s); str = new char[len + 1]; std::strcpy(str, s); return *this; } // read-write char access for non-const String char & String::operator[](int i) { return str[i]; } // read-only char access for const String const char & String::operator[](int i) const { return str[i]; } // overloaded operator friends bool operator<(const String &st1, const String &st2) { return (std::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 (std::strcmp(st1.str, st2.str) == 0); } // simple String output ostream & operator<<(ostream & os, const String & st) { os << st.str; return os; } // quick and dirty String input 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; } 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(const char a) //成员函数,统计字符次数 { int num = 0; for (int i = 0; i < len; i++) { if(str[i] == a) num++; } return num; } String operator+(const String &st1, const String &st2) { String add; add.len = st1.len + st2.len; add.str = new char[add.len + 1]; strcpy(add.str, st1.str); strcat(add.str, st2.str); return add; } String operator+(const char * s, const String &st) { String add; add.len = std::strlen(s) + st.len; add.str = new char[add.len + 1]; strcpy(add.str, s); strcat(add.str, st.str); return add; }
2.3 再或者
[code]#ifndef STRING2_H_ #define STRING2_H_ #include <iostream> using std::ostream; using std::istream; class String { private: char * str; // pointer to string int len; // length of string static int num_strings; // number of objects static const int CINLIM = 80; // cin input limit public: // constructors and other methods String(const char * s); // constructor String(); // default constructor String(const String &); // copy constructor ~String(); // destructor int length() const { return len; } void stringlow(); //成员函数,转换为小写 void stringup(); //成员函数,转换为大写 int has(const char); //成员函数,统计字符次数 // overloaded operator methods String & operator=(const String &); String & operator=(const char *); char & operator[](int i); const char & operator[](int i) const; String operator+(const String &st) const; //重载+运算符 String + String String operator+(const char * s) const; //重载+运算符 C字符串 + String // overloaded operator friends friend String operator+(const char * s, const String &st) { return (st + s); } //重载+运算符 String + C字符串 friend bool operator<(const String &st, const String &st2); friend bool operator>(const String &st1, const String &st2); friend bool operator==(const String &st, const String &st2); friend ostream & operator<<(ostream & os, const String & st); friend istream & operator>>(istream & is, String & st); // static function static int HowMany(); }; #endif
[code]//string2.cpp #include <cstring> // string.h for some #include <cctype> #include "string2.h" // includes <iostream> using std::cin; using std::cout; // initializing static class member int String::num_strings = 0; // static method int String::HowMany() { return num_strings; } // class methods String::String(const char * s) // construct String from C string { len = std::strlen(s); // set size str = new char[len + 1]; // allot storage std::strcpy(str, s); // initialize pointer num_strings++; // set object count } String::String() // default constructor { len = 4; str = new char[1]; str[0] = '\0'; // default string num_strings++; } String::String(const String & st) { num_strings++; // handle static member update len = st.len; // same length str = new char[len + 1]; // allot space std::strcpy(str, st.str); // copy string to new location } String::~String() // necessary destructor { --num_strings; // required delete[] str; // required } // overloaded operator methods // assign a String to a String String & String::operator=(const String & st) { if (this == &st) return *this; delete[] str; len = st.len; str = new char[len + 1]; std::strcpy(str, st.str); return *this; } // assign a C string to a String String & String::operator=(const char * s) { delete[] str; len = std::strlen(s); str = new char[len + 1]; std::strcpy(str, s); return *this; } // read-write char access for non-const String char & String::operator[](int i) { return str[i]; } // read-only char access for const String const char & String::operator[](int i) const { return str[i]; } // overloaded operator friends bool operator<(const String &st1, const String &st2) { return (std::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 (std::strcmp(st1.str, st2.str) == 0); } // simple String output ostream & operator<<(ostream & os, const String & st) { os << st.str; return os; } // quick and dirty String input 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; } 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(const char a) //成员函数,统计字符次数 { int num = 0; for (int i = 0; i < len; i++) { if (str[i] == a) num++; } return num; } String String::operator+(const String &st) const { String add; add.len = len + st.len; add.str = new char[add.len + 1]; strcpy(add.str, str); strcat(add.str, st.str); return add; } String String::operator+(const char * s) const { String add; add.len = std::strlen(s) + len; add.str = new char[add.len + 1]; strcpy(add.str, s); strcat(add.str, str); return add; }
3. 新编写程序清单10.7 和程序清单10.8 描述的Stock类,使之使用动态分配的内存,而不是string类对象来存储股票名称。
另外,使用重载的operator<<()定义show()成员函数。再使用程序清单10.9 测试新的定义程序。
程序清单10.7
[code]// stock20.h -- augmented version #ifndef STOCK20_H_ #define STOCK20_H_ #include <string> class Stock { private: std::string company; int shares; double share_val; double total_val; void set_tot() { total_val = shares * share_val; } public: Stock(); // default constructor Stock(const std::string & co, long n = 0, double pr = 0.0); ~Stock(); // do-nothing destructor void buy(long num, double price); void sell(long num, double price); void update(double price); void show()const; const Stock & topval(const Stock & s) const; }; #endif
程序清单10.8
[code]// stock20.cpp -- augmented version #include <iostream> #include "stock20.h" using namespace std; // constructors Stock::Stock() // default constructor { company = "no name"; shares = 0; share_val = 0.0; total_val = 0.0; } Stock::Stock(const std::string & co, long n, double pr) { 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(); } // class destructor Stock::~Stock() // quiet class destructor { } // other methods void Stock::buy(long num, double price) { if (num < 0) { std::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) { 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 have! " << "Transaction is aborted.\n"; } else { shares -= num; share_val = price; set_tot(); } } void Stock::update(double price) { share_val = price; set_tot(); } void Stock::show() const { using std::cout; using std::ios_base; // set format to #.### ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield); std::streamsize prec = cout.precision(3); cout << "Company: " << company << " Shares: " << shares << '\n'; cout << " Share Price: $" << share_val; // set format to #.## cout.precision(2); cout << " Total Worth: $" << total_val << '\n'; // restore original format cout.setf(orig, ios_base::floatfield); cout.precision(prec); } const Stock & Stock::topval(const Stock & s) const { if (s.total_val > total_val) return s; else return *this; }
程序清单10.9
[code]// usestok2.cpp -- using the Stock class // compile with stock20.cpp #include <iostream> #include "stock20.h" const int STKS = 4; int main() {{ // create an array of initialized objects 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++) stocks[st].show(); // set pointer to first element const Stock * top = &stocks[0]; for (st = 1; st < STKS; st++) top = &top->topval(stocks[st]); // now top points to the most valuable holding std::cout << "\nMost valuable holding:\n"; top->show();} // std::cin.get(); return 0; }
修改后 程序清单10.7
[code]// stock20.h -- augmented version #ifndef STOCK20_H_ #define STOCK20_H_ class Stock { private: char * company; //改为char * int shares; double share_val; double total_val; void set_tot() { total_val = shares * share_val; } public: Stock(); //默认构造函数 Stock(const char * co, long n = 0, double pr = 0.0); //构造函数 Stock(const Stock &); //复制构造函数 ~Stock(); // 析构函数 void buy(long num, double price); void sell(long num, double price); void update(double price); // void show()const; const Stock & topval(const Stock & s) const; Stock & operator=(const Stock &); //重载赋值运算符 friend ostream & operator<<(ostream & os, const Stock & st); //重载<<运算符 }; #endif
修改后 程序清单10.8
[code]// stock20.cpp -- augmented version #include <iostream> #include <cstring> #include "stock20.h" using namespace std; // constructors Stock::Stock() // default constructor { 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) { 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(const Stock & st) //复制构造函数 { company = new char [strlen(st.company)+1]; strcpy(company, st.company); shares = st.shares; share_val = st.share_val; total_val = st.share_val; } // class destructor Stock::~Stock() // quiet class destructor { delete [] company; } // other methods void Stock::buy(long num, double price) { if (num < 0) { std::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) { 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 have! " << "Transaction is aborted.\n"; } else { shares -= num; share_val = price; set_tot(); } } void Stock::update(double price) { share_val = price; set_tot(); } // void Stock::show() const // { // using std::cout; // using std::ios_base; /*set format to #.### */ // ios_base::fmtflags orig = // cout.setf(ios_base::fixed, ios_base::floatfield); // std::streamsize prec = cout.precision(3); // cout << "Company: " << company // << " Shares: " << shares << '\n'; // cout << " Share Price: $" << share_val; /*set format to #.##*/ // cout.precision(2); // cout << " Total Worth: $" << total_val << '\n'; /*restore original format*/ // cout.setf(orig, ios_base::floatfield); // cout.precision(prec); // } const Stock & Stock::topval(const Stock & s) const { if (s.total_val > total_val) return s; else return *this; } Stock & Stock::operator=(const Stock & st) //重载赋值运算符 { if (this == &st) return *this; delete [] company; company = new char [strlen(st.company)+1]; strcpy(company, st.company); shares = st.shares; share_val = st.share_val; total_val = st.share_val; return *this; } ostream & operator<<(ostream & os, const Stock & st) { using std::ios_base; // set format to #.### 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; }
修改后 程序清单10.9
[code]// usestok2.cpp -- using the Stock class // compile with stock20.cpp #include <iostream> #include "stock20.h" const int STKS = 4; int main() { using namespace std; // create an array of initialized objects 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++) cout << stocks[st]; // set pointer to first element const Stock * top = &stocks[0]; for (st = 1; st < STKS; st++) top = &top->topval(stocks[st]); // now top points to the most valuable holding std::cout << "\nMost valuable holding:\n"; cout << *top; // std::cin.get(); return 0; }
4. 请看下面程序清单10.10 定义的Stack类的变量:
[code]// 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); };
正如私有成员表明的,这个类使用动态分配的数组来保存栈项。请重新编写方法,以适应这种新的表示法,
并编写一个程序来演示所有的方法。包括复制构造函数和赋值运算符。
[code]// stack.h -- class declaration for the stack ADT #include <iostream> 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); friend std::ostream & operator<<(std::ostream & os, const Stack & st); };
[code]// stack.cpp -- Stack member functions #include <iostream> #include "stack.h" using namespace std; Stack::Stack(int n) { size = n; pitems = new Item [size]; for (int i = 0; i < size; i++) pitems[i] = 0; top = 0; } Stack::Stack(const Stack & st) { size = st.size; pitems = new Item [size]; for (int i = 0; i < size; i++) pitems[i] = st.pitems[i]; top = st.top; } Stack::~Stack() { delete [] pitems; } bool Stack::isempty() const { return top == 0; } bool Stack::isfull() const { return top == MAX; } bool Stack::push(const Item & item) { if (top < MAX) { 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) { if (this == &st) return *this; size = st.size; pitems = new Item [size]; for (int i = 0; i < size; i++) pitems[i] = st.pitems[i]; top = st.top; return *this; } std::ostream & operator<<(std::ostream & os, const Stack & st) { for (int i = 0; i < st.top; i++) cout << st.pitems[i] << endl; return os; }
[code]// stacker.cpp -- testing the Stack class #include <iostream> #include <cctype> // or ctype.h #include "stack.h" int main() { using namespace std; Stack 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; } cout << "Please enter A to add a purchase order,\n" << "P to process a PO, or Q to quit.\n"; } cout << "So our stack is:\n" << st; Stack st2; st2 = st; cout << "stack2 = stack is:\n" << st2; Stack st3 = st; cout << "stack3 = stack is:\n" << st3; cout << "Bye\n"; return 0; }
5. Heather银行进行的研究表明,ATM客户不希望排队时间超过1分钟。使用程序清单12.10 中的模拟,
找出要使平均等候时间为1分钟,每小时到达的客户数应为多少(试验时间不短于100小时)?
程序清单12.10
[code]// queue.h -- interface for a queue #ifndef QUEUE_H_ #define QUEUE_H_ // This queue will contain Customer items class Customer { private: long arrive; // arrival time for customer int processtime; // processing time for customer public: Customer() : arrive(0), processtime (0){} void set(long when); long when() const { return arrive; } int ptime() const { return processtime; } }; typedef Customer Item; class Queue { private: // class scope definitions // Node is a nested structure definition local to this class struct Node { Item item; struct Node * next;}; enum {Q_SIZE = 10}; // private class members Node * front; // pointer to front of Queue Node * rear; // pointer to rear of Queue int items; // current number of items in Queue const int qsize; // maximum number of items in Queue // preemptive definitions to prevent public copying Queue(const Queue & q) : qsize(0) { } Queue & operator=(const Queue & q) { return *this;} public: Queue(int qs = Q_SIZE); // create queue with a qs limit ~Queue(); bool isempty() const; bool isfull() const; int queuecount() const; bool enqueue(const Item &item); // add item to end bool dequeue(Item &item); // remove item from front }; #endif
程序清单12.11
[code]// queue.cpp -- Queue and Customer methods #include "queue.h" #include <cstdlib> // (or stdlib.h) for rand() // Queue methods Queue::Queue(int qs) : qsize(qs) //构造函数 { front = rear = NULL; // or nullptr items = 0; } Queue::~Queue() //析构函数 { Node * temp; while (front != NULL) // while queue is not yet empty { temp = front; // save address of front item front = front->next;// reset pointer to next item delete temp; // delete former front } } bool Queue::isempty() const { return items == 0; } bool Queue::isfull() const { return items == qsize; } int Queue::queuecount() const { return items; } // Add item to queue bool Queue::enqueue(const Item & item) { if (isfull()) return false; Node * add = new Node; // create node // on failure, new throws std::bad_alloc exception add->item = item; // set node pointers add->next = NULL; // or nullptr; items++; if (front == NULL) // if queue is empty, front = add; // place item at front else rear->next = add; // else place at rear rear = add; // have rear point to new node return true; } // Place front item into item variable and remove from queue bool Queue::dequeue(Item & item) { if (front == NULL) return false; item = front->item; // set item to first item in queue items--; Node * temp = front; // save location of first item front = front->next; // reset front to next item delete temp; // delete former first item if (items == 0) rear = NULL; return true; } // customer method // when is the time at which the customer arrives // the arrival time is set to when and the processing // time set to a random value in the range 1 - 3 void Customer::set(long when) { processtime = std::rand() % 3 + 1; arrive = when; }
程序清单12.12
[code]// bank.cpp -- using the Queue interface // compile with queue.cpp #include <iostream> #include <cstdlib> // for rand() and srand() #include <ctime> // for time() #include "queue.h" const int MIN_PER_HR = 60; bool newcustomer(double x); // is there a new customer? int main() { using std::cin; using std::cout; using std::endl; using std::ios_base; // setting things up std::srand(std::time(0)); // random initializing of rand() cout << "Case Study: Bank of Heather Automatic Teller\n"; //请求输入队伍长度 cout << "Enter maximum size of queue: "; int qs; cin >> qs; Queue line(qs); // line queue holds up to qs people //请求输入模拟时间长度 cout << "Enter the number of simulation hours: "; int hours; // hours of simulation cin >> hours; // simulation will run 1 cycle per minute 转换为分钟 long cyclelimit = MIN_PER_HR * hours; // # of cycles //请求输入平均每小时的顾客数 cout << "Enter the average number of customers per hour: "; double perhour; // average # of arrival per hour cin >> perhour; double min_per_cust; // average time between arrivals min_per_cust = MIN_PER_HR / perhour; //计算平均每分钟的顾客数 Item temp; // new customer data long turnaways = 0; // turned away by full queue 被拒绝的顾客数 long customers = 0; // joined the queue 加入队列的顾客数 long served = 0; // served during the simulation 服务的顾客数 long sum_line = 0; // cumulative line length 累积的队列长度 int wait_time = 0; // time until autoteller is free 直到ATM空闲的时间 long line_wait = 0; // cumulative time in line 排队等候时间 // running the simulation for (int cycle = 0; cycle < cyclelimit; cycle++) { if (newcustomer(min_per_cust)) // have newcomer { if (line.isfull()) turnaways++; else { customers++; temp.set(cycle); // cycle = time of arrival line.enqueue(temp); // add newcomer to line } } if (wait_time <= 0 && !line.isempty()) { line.dequeue (temp); // attend next customer wait_time = temp.ptime(); // for wait_time minutes line_wait += cycle - temp.when(); served++; } if (wait_time > 0) wait_time--; sum_line += line.queuecount(); } // reporting results if (customers > 0) { cout << "customers accepted: " << customers << endl; cout << " customers served: " << served << endl; cout << " turnaways: " << turnaways << endl; cout << "average queue size: "; cout.precision(2); cout.setf(ios_base::fixed, ios_base::floatfield); cout << (double) sum_line / cyclelimit << endl; cout << " average wait time: " << (double) line_wait / served << " minutes\n"; } else cout << "No customers!\n"; cout << "Done!\n"; // cin.get(); // cin.get(); return 0; } // x = average time, in minutes, between customers // return value is true if customer shows up this minute bool newcustomer(double x) { return (std::rand() * x / RAND_MAX < 1); }
程序清单12.12 修改后
[code]// bank.cpp -- using the Queue interface // compile with queue.cpp #include <iostream> #include <cstdlib> #include <ctime> #include "queue.h" const int MIN_PER_HR = 60; bool newcustomer(double x); int main() { using std::cin; using std::cout; using std::endl; using std::ios_base; std::srand(std::time(0)); cout << "Case Study: Bank of Heather Automatic Teller\n"; cout << "Enter maximum size of queue: "; int qs; cin >> qs; Queue line(qs); cout << "The simulation hours: 100\n"; int hours = 100; long cyclelimit = MIN_PER_HR * hours; double perhour; double min_per_cust; perhour = 1; Item temp; long turnaways = 0; long customers = 0; long served = 0; long sum_line = 0; int wait_time = 0; long line_wait = 0; double avetime = 0; while (avetime <= 1) { while (!line.isempty()) { line.dequeue(temp); } min_per_cust = MIN_PER_HR / perhour; for (int cycle = 0; cycle < cyclelimit; cycle++) { if (newcustomer(min_per_cust)) { if (line.isfull()) turnaways++; else { customers++; temp.set(cycle); line.enqueue(temp); } } if (wait_time <= 0 && !line.isempty()) { line.dequeue(temp); wait_time = temp.ptime(); line_wait += cycle - temp.when(); served++; } if (wait_time > 0) wait_time--; sum_line += line.queuecount(); } if (customers > 0) { cout << "customers accepted: " << customers << endl; cout << " customers served: " << served << endl; cout << " turnaways: " << turnaways << endl; cout << "average queue size: "; cout.precision(2); cout.setf(ios_base::fixed, ios_base::floatfield); cout << (double)sum_line / cyclelimit << endl; cout << " average wait time: " << (double)line_wait / served << " minutes\n"; } else cout << "No customers!\n"; avetime = (double)line_wait / served; perhour++; } cout << "When there comes " << perhour << " people per hour, the average wait time will be about 1 minute.\n"; cout << "Done!\n"; system("pause"); return 0; } bool newcustomer(double x) { return (std::rand() * x / RAND_MAX < 1); }
6. Heather银行想知道,如果再开设一台ATM,情况将如何。请对模拟进行修改,以包含两个队列。
假设当第一台ATM前的排队人数少于第二台ATM时,客户将排在第一队,否则将排在第二队。
然后再找出要使平均等候时间为1分钟,每小时到达的客户数应该为多少?
(注意这是一个非线性问题,即将ATM数量加倍,并不能保证每小时处理客户等候的时间少于1分钟)
[code]// bank.cpp -- using the Queue interface // compile with queue.cpp #include <iostream> #include <cstdlib> #include <ctime> #include "queue.h" const int MIN_PER_HR = 60; bool newcustomer(double x); int main() { using std::cin; using std::cout; using std::endl; using std::ios_base; std::srand(std::time(0)); cout << "Case Study: Bank of Heather Automatic Teller\n"; cout << "Enter maximum size of queue: "; int qs; cin >> qs; Queue line1(qs); Queue line2(qs); cout << "The simulation hours: 100\n"; int hours = 100; long cyclelimit = MIN_PER_HR * hours; double perhour; double min_per_cust; perhour = 1; Item temp; long turnaways = 0; long customers = 0; long customers1 = 0; long customers2 = 0; long served = 0; long sum_line = 0; long sum_line1 = 0; long sum_line2 = 0; int wait_time = 0; int wait_time1 = 0; int wait_time2 = 0; long line_wait = 0; double avetime = 0; while (perhour++ && avetime <= 1) { while (!line1.isempty()) { line1.dequeue(temp); } while (!line2.isempty()) { line2.dequeue(temp); } min_per_cust = MIN_PER_HR / perhour; for (int cycle = 0; cycle < cyclelimit; cycle++) { if (newcustomer(min_per_cust)) { if (line1.isfull() && line2.isfull()) turnaways++; else { if(customers1 <= customers2) { customers++; customers1++; temp.set(cycle); line1.enqueue(temp); } else { customers++; customers2++; temp.set(cycle); line2.enqueue(temp); } } } if (wait_time1 <= 0 && !line1.isempty()) { line1.dequeue(temp); wait_time1 = temp.ptime(); line_wait += cycle - temp.when(); served++; } if (wait_time2 <= 0 && !line2.isempty()) { line2.dequeue(temp); wait_time2 = temp.ptime(); line_wait += cycle - temp.when(); served++; } if (wait_time1 > 0) wait_time1--; if (wait_time2 > 0) wait_time2--; sum_line1 += line1.queuecount(); sum_line2 += line1.queuecount(); sum_line = sum_line1 + sum_line2; } if (customers > 0) { cout << "customers accepted: " << customers << endl; cout << " customers served: " << served << endl; cout << " turnaways: " << turnaways << endl; cout << "average queue size: "; cout.precision(2); cout.setf(ios_base::fixed, ios_base::floatfield); cout << (double)sum_line / cyclelimit << endl; cout << " average wait time: " << (double)line_wait / served << " minutes\n"; } else cout << "No customers!\n"; avetime = (double)line_wait / served; } cout << "When there comes " << perhour << " people per hour, the average wait time will be about 1 minute.\n"; cout << "Done!\n"; system("pause"); return 0; } bool newcustomer(double x) { return (std::rand() * x / RAND_MAX < 1); }
- C++ PRIMER PLUS (第六版) 中文版 第七章编程练习答案
- 《C++ Primer Plus(第六版)》(24)(第十二章 类和动态内存分配 编程题和答案)
- C++ primer Plus(第六版)中文版 编程练习答案 目录(已更新完2~12章)
- c++ primer plus(第6版)中文版 第十二章编程练习答案
- C++ Primer Plus第六版 第十二章 编程练习答案
- 《C++ Primer Plus(第六版)》(23)(第十二章 类和动态内存分配 复习题和答案)
- c++ primer plus(第6版)中文版 第七章编程练习答案
- C++primer plus第六版课后编程练习答案4.4
- C++primer plus第六版课后编程练习答案5.7
- C++primer plus第六版课后编程练习答案6.6
- C++primer plus第六版课后编程练习答案7.1
- C++primer plus第六版课后编程练习答案8.4
- C++primer plus第六版课后编程练习答案10.2
- C++ primer plus第六版课后编程练习答案:6.8
- C++ primer plus第六版课后编程练习答案:8.1
- C++primer plus第六版课后编程练习答案2.3
- C++primer plus第六版课后编程练习答案4.5
- C++primer plus第六版课后编程练习答案4.9
- C++primer plus第六版课后编程练习答案6.7
- C++primer plus第六版课后编程练习答案7.7