类和动态内存分配的课后习题(C++ prime 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 new data
};
给这个类提供实现,并编写一个使用所有成员函数的小程序。
Cow.h
#ifndef COW_H_ #define COW_H_ class Cow { private: char name[20]; char * hobby; double weght; public: Cow(); Cow(const char * nm,const char *ho,double wt); Cow(const Cow &c); ~Cow(); Cow &operator=(const Cow & c); void ShowCow()const; }; #endif
Cow.cpp
#include <iostream> #include <cstring> #include "Cow.h" using namespace std; Cow::Cow() { strcpy(name,"whp"); hobby=new char [4]; strcpy(hobby,"math"); weght=0.0; } Cow::Cow(const char * nm,const char * ho,double wt) { strcpy(name,nm); hobby=new char [strlen(ho)+1]; strcpy(hobby,ho); weght=wt; } Cow::Cow(const Cow & c) { hobby=new char [strlen(c.hobby)+1]; strcpy(hobby,c.hobby); strcpy(name,c.name); weght=c.weght; } Cow::~Cow() { delete [] hobby; } Cow & Cow::operator=(const Cow & c) { delete [] hobby; hobby=new char [strlen(c.hobby)+1]; strcpy(hobby,c.hobby); weght=c.weght; strcpy(name,c.name); return *this; } void Cow::ShowCow()const { cout<<"name: "<<name<<endl; cout<<"hobby: "<<hobby<<endl; cout<<"weght: "<<weght<<endl; cout<<"end"<<endl; }
UserCow.cpp
#include <iostream> #include "Cow.h" using namespace std; int main() { Cow mycow; mycow.ShowCow(); Cow mycow1("wer","china",20); mycow1.ShowCow(); Cow mycow2; mycow2=mycow; mycow2.ShowCow(); cout<<"结束"<<endl; return 0; }
第二题
通过完成下面的工作来改进String类声明(即将String1.h升级为String2.h)。
a. 对+运算符进行重载,使之可将两个字符串合并成1个。
b. 提供一个Stringlow()成员函数,将字符串中所有的字母字符转换为小写(别忘了cctype系列字符函数)。
c. 提供String()成员函数,将字符串中所有字母字符转换成大写。
d. 提供一个这样的成员函数,它接受一个char参数,返回该字符在字符串中出现的次数
string.h
#ifndef STRING1_H_ #define STRING1_H_ #include <iostream> using std::ostream; using std::istream; 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; } void string_change_low(); void string_change_up(); int has(char c); String & operator=(const String &); String & operator=(const char *); String operator+(const String & st)const; String operator+(const char * str1)const; char & operator[](int i); const char & operator[](int i) const; 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 String operator+(const char * str1,const String & st); friend ostream & operator<<(ostream & os, const String & st); friend istream & operator>>(istream & is, String & st); static int HowMany(); }; #endif
string.cpp
#include <cstring> #include "string1.h" using std::cin; using std::cout; #include <cstdlib> int String::num_strings = 0; int String::HowMany() { return num_strings; } String::String(const char * s) { len = std::strlen(s); str = new char[len + 1]; std::strcpy(str, s); num_strings++; } String::String() { len = 4; str = new char[1]; str[0] = '\0'; num_strings++; } String::String(const String & st) { num_strings++; len = st.len; str = new char [len + 1]; std::strcpy(str, st.str); } String::~String() { --num_strings; delete [] str; } void String::string_change_low() { for(int i=0;i<this->len+1;i++) { this->str[i]=towlower(this->str[i]); } } void String::string_change_up() { for(int i=0;i<this->len+1;i++) { this->str[i]=toupper(this->str[i]); } } int String::has(char c) { int count=0; for(int i=0;i<this->len+1;i++) { if(this->str[i]==c) { count++; } } return count; } String String::operator+(const String & st)const { int new_len=0; new_len=len+st.len; char * temp=new char [new_len+1]; strcpy(temp,str); strcpy(temp+len,st.str); temp[new_len]='\0'; return String(temp); } String String::operator+(const char * str1)const { int new_len=0; new_len=len+strlen(str); char *temp=new char [new_len+1]; strcpy(temp,str); strcpy(temp,str1); return String(temp); } String operator+(const char * str1,const String & st) { return String(str1)+st; } 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; } String & String::operator=(const char * s) { delete [] str; len = std::strlen(s); str = new char[len + 1]; std::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 (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); } 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; }
UserString.cpp
#include <iostream> using namespace std; #include "string1.h" 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.string_change_up(); 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.string_change_low(); 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; }
第三题
新编写程序清单10.7和程序清单10.8描述的Stock类,使之使用动态内存分配的内存,而不是string类对象来存储股票名称。另外,使用重载的operator<<()定义代替show()成员函数。再使用程序清单10.9测试新的定义程序。
Stock20.h
#ifndef STOCK20_H_ #define STOCK20_H_ #include <string> #include <cstdlib> #include <cstring> #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(); Stock(const char * strs, 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 ostream & operator<<(ostream & os,const Stock & st); const Stock & topval(const Stock & s) const; }; #endif
Stcok20.cpp
#include <iostream> #include "stock20.h" Stock::Stock() { company=new char [strlen("whp")+1]; strcpy(company,"whp"); shares = 0; share_val = 0.0; total_val = 0.0; } Stock::Stock(const char * strs, long n, double pr) { int len=strlen(strs); company=new char [len+1]; strcpy(company,strs); 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() { } 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(); } ostream & operator<<(ostream & os,const Stock & st) { using std::ios_base; 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; os.precision(2); os << " Total Worth: $" <<st.total_val <<'\n'; return os; } const Stock & Stock::topval(const Stock & s) const { if (s.total_val > total_val) return s; else return *this; }
UserStcok.cpp
#include <iostream> #include "stock20.h" 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++) cout<<stocks[st]; const Stock * top = &stocks[0]; for (st = 1; st < STKS; st++) top = &top->topval(stocks[st]); std::cout << "\nMost valuable holding:\n"; cout<<*top; return 0; }
第四题
Stack.h
#ifndef STOCK_H_ #define STOCK_H_ using namespace std; #include <iostream> 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); friend ostream & operator<<(ostream & os,const Stack & st); }; #endif
Stack.cpp
#include <iostream> #include "Stack.h" Stack::Stack(int n=MAX) { pitems=new Item[n];//分配空间 for(int i=0;i<n;i++)//初始化数组 { pitems[i]=0; } top=0; size=n; } Stack::Stack(const Stack & st) { pitems=new Item[st.size]; for(int i=0;i<st.size;i++) { pitems[i]=st.pitems[i]; } top=st.top; size=st.size; } 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; delete [] pitems; top=st.top; size=st.size; pitems=new Item[st.size]; for(int i=0;i<st.size;i++) { pitems[i]=st.pitems[i]; } return *this; } ostream & operator<<(ostream & os,const Stack & st) { for(int i=0;i<st.top;i++) { os<<st.pitems[i]<<endl; } return os; }
UserStack.cpp
#include <iostream> #include <cctype> #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"; } Stack st2; st2=st; cout<<"st2"<<st2<<endl; cout << "Bye\n"; return 0; }
第五题
Heather银行进行的研究表明,ATM客户不希望排队时间不超过1分钟。使用程序清单12.10中的模拟,找出要使平均等候时间为1分钟,每小时到达的客户数应为多少(试验时间不短于100小时)?
Queue.h
#ifndef STACK_H_ #define STACK_H_ class Customer { private: long arrive; int processtime; public: Customer(){arrive=processtime=0;} void set(long when); long when() const {return arrive;} int ptime()const {return processtime;} }; typedef Customer Item; class Queue { private: struct Node{Item item;struct Node * next;}; enum {Q_SIZE=10}; Node * front; Node * rear; int items; const int qsize; Queue(const Queue & q):qsize(0){} Queue & operator=(const Queue & q){return * this;} public: Queue(int qs=Q_SIZE); ~Queue(); bool isempty()const; bool isfull()const; int queuecount()const; bool enqueue(const Item & item); bool dequeue(Item & item); }; #endif
customer.cpp
#include <iostream> #include "Queue.h" Queue::Queue(int qs):qsize(qs) { front=rear=NULL; items=0; } Queue::~Queue() { Node * temp; while(front!=NULL) { temp=front; front==front->next; delete temp; } } bool Queue::isempty()const { return items==0; } bool Queue::isfull()const { return items==qsize; } int Queue::queuecount()const { return items; } bool Queue::enqueue(const Item & item) { if(isfull()) return false; Node *add=new Node; add->item=item; add->next=NULL; items++; if(front==NULL) front=add; rear->next=add; rear=add; return true; } bool Queue::dequeue(Item & item) { if(isempty()) return false; Node * temp=new Node; item=front->item; temp=front; front=front->next; delete temp; if(items==0) { rear=NULL; } return true; }
bank.cpp
#include <iostream> #include "Queue.h" #include <cstdlib> #include <ctime> 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:Band of Heather Automatic Teller\n"; cout<<"Enter maximum size of queue:"; int qs; cin>>qs; Queue line(qs); cout<<"Enter the number of simulation hours:"; int hours; cin>>hours; long cyclelimit=MIN_PER_HR*hours; cout<<"Enter the average number of customer per hour:"; double perhour; cin>>perhour; double min_per_cust; min_per_cust=MIN_PER_HR/perhour; Item temp; long turnaways=0; long customers=0; long served=0; long sum_line=0; long wait_time=0; long line_wait=0; double avetime=0; while(perhour++&&avetime<=1) { while(!line.isempty()) { line.dequeue(temp); } 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; } cout<<"When there comes"<<perhour<<"people per hour,the average wait time will be about 1 inutes.\n"<<endl; cout<<"Done"; return 0; } bool newcustomer(double x) { return (std::rand() * x / RAND_MAX < 1); }