复习题
//12.9 //1 a, 语法是正确的,但没有将str指针初始化,应该将指针设置成NULL或使用new来初始化它 b, 没有创建新的字符串,而只是复制了原有字符串的地址,应该使用new[]和strcpy() c, 复制了字符串但没有分配存储空间,应该使用new char[len + 1]分配内存 //2 首先,当这种类型的对象过期时,对象的成员指针指向的数据仍然保留在内存中,导致占用 空间但是又不可访问,因为指针已经丢失。解决方法是让类的析构函数删除构造函数中new 分配的内存。其次,析构函数释放这种内存后,如果程序将这样的对象初始化为另一个对象, 析构函数会试图释放这些内存两次,这是因为将一个对象初始化为另一个对象的默认初始化 将复制指针值但不复制指向指针的数据,这样两个指针就指向同一个数据。解决方法是定义 一个复制构造函数,使初始化复制指向的数据。第三,将一个对象赋给另一个对象也会导致 两个指针指向相同的数据,解决方法是重载赋值运算符,使它复制数据而不是指针。 //3 C++自动提供下面的成员函数: 如果没有定义,将自动提供 默认构造函数,复制构造函数,赋值运算符,默认析构函数,地址运算符 默认构造函数不完成任何工作,但使得可以声明数组和未初始化的对象。 默认复制构造函数和默认赋值运算符使用成员赋值。 默认析构函数也不完成任何工作。 隐式地址运算符返回调用对象的人地址。(即this指针的值) //4 #include<iostream> #include<cstring> using namespace std; class nifty { private: char* personality; int talents; public: nifty(); nifty(const char* s); nifty(const nifty& n); ~nifty() { delete[]personality; }; nifty& operator=(const nifty& n); friend ostream& operator<<(ostream& os, const nifty& n); }; nifty::nifty() { personality = nullptr; talents = 0; } nifty::nifty(const char* s) { personality = new char[strlen(s) + 1]; strcpy(personality, s); talents = 0; } nifty::nifty(const nifty& n) { char* personality = new char[strlen(n.personality)]; strcpy(personality, n.personality); } nifty& nifty::operator=(const nifty& n) { if (this == &n) return *this; delete[]personality; char* personality = new char[strlen(n.personality)]; strcpy(personality, n.personality); return *this; } ostream& operator<<(ostream& os, const nifty& n) { os << n.personality << endl; os << n.talents << endl; return os; } //5 #1 默认构造函数 #2 构造函数,使用一个默认参数 #3 构造函数 #4 默认构造函数 #5 复制构造函数 #6 构造函数 #7 默认赋值运算符 #8 构造函数,默认赋值运算符 对于#5和#6有的编译器还会调用默认赋值运算符 应该定义一个复制数据(而不是地址)的赋值运算符
practice1
使用strcpy总是有很多麻烦,换成strcpy_s可能麻烦更多
参考C++中strcpy()函数和strcpy_s()函数的使用及注意事项_strcpy_s函数_Leonardo Liu的博客-CSDN博客
#pragma once //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() { delete[]hobby; } Cow& operator=(const Cow& c); void ShowCow()const; char* f() { return hobby; }//显示地址作为观察 }; #endif //cow.cpp #include"cow.h" #include<iostream> #include<cstring> #pragma warning( disable : 4996) using namespace std; Cow::Cow() { strcpy(name, ""); hobby = nullptr; 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::operator=(const Cow& c) { 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 << "Information of cow named " << name << endl; if (hobby == 0) cout << "Hobby is NULL" << endl; else cout << "Hobby: " << hobby << endl; cout << "Weight: " << weight << endl; } //main.cpp #include<iostream> #include"cow.h" int main() { using namespace std; Cow cow1; cow1.ShowCow(); cout << "Hobby address: " << (void*)cow1.f() << endl; cout << endl; char name[] = "cow one"; Cow cow2(name, "drink", 180.5); cow2.ShowCow(); cout << "Hobby address: " << (void*)cow2.f() << endl; cout << endl; Cow cow3 = cow2; cow3.ShowCow(); cout << "Hobby address: " << (void*)cow3.f() << endl; cout << endl; Cow cow4; cow4 = cow3; cow4.ShowCow(); cout << "Hobby address: " << (void*)cow4.f() << endl; cout << endl; return 0; }
practice2
唉,又要抄程序清单
//string2.h #ifndef STRING2_H_ #define STRING2_H_ #include<iostream> using namespace std; class String { char* str; int len; static int num_strings; static const int CINLIM = 80; public: String(const char* s); String(); String(const String& s); ~String(); int length()const { return len; } String& operator=(const String& s); String& operator=(const char* s); char& operator[](int i); const char& operator[](int i)const; friend bool operator<(const String& s1, const String& s2); friend bool operator>(const String& s1, const String& s2); friend bool operator==(const String& s1, const String& s2); friend ostream& operator<<(ostream& os, const String& s); friend istream& operator>>(istream& is, String& s); static int HowMany(); friend String operator+(const String& s1, const String& s2); void stringlow(); void stringup(); int has(char c); }; #endif //string2.cpp #include"string2.h" #include<cstring> #include<cctype> #pragma warning( disable : 4996) 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 = 4; str = nullptr; num_strings++; } String::String(const String& s) { len = s.len; str = new char[len + 1]; strcpy(str, s.str); num_strings++; } String::~String() { delete[]str; num_strings--; } String& String::operator=(const String& s) { if (this == &s) return *this; delete[]str; len = s.len; str = new char[len + 1]; strcpy(str, s.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& s1, const String& s2) { return (strcmp(s1.str, s2.str) < 0); } bool operator>(const String& s1, const String& s2) { return s2 < s1; } bool operator==(const String& s1, const String& s2) { return (strcmp(s1.str, s2.str) == 0); } ostream& operator<<(ostream& os, const String& s) { os << s.str; return os; } istream& operator>>(istream& is, String& s) { char temp[String::CINLIM]; is.get(temp, String::CINLIM); if (is) s = temp; while (is && is.get() != '\n') continue; return is; } String operator+(const String& s1, const String& s2) { String temp; temp.len = s1.len + s2.len; temp.str = new char[temp.len + 1]; strcpy(temp.str, s1.str); strcat(temp.str, s2.str); return temp; } 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) { int sum = 0; for (int i = 0; i < len; i++) if (str[i] == c) sum++; return sum; } //main.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; 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; }
practice3
//stock.h #pragma once #ifndef STOCK3_H_ #define STOCK3_H_ #include<iostream> class Stock { char* company; int shares; double share_val; double total_val; void set_tot() { total_val = shares * share_val; } public: Stock(); Stock(const char* c, long n = 0, double pr = 0.0); ~Stock(); void buy(long num, double price); void sell(long num, double price); void updata(double price); const Stock& topval(const Stock& s)const; friend std::ostream& operator<<(std::ostream& os, const Stock& s); }; #endif //stock.cpp #include"stock3.h" #include<cstring> #pragma warning(disable:4996) using namespace std; Stock::Stock() { company = nullptr; shares = 0; share_val = 0.0; total_val = 0.0; } Stock::Stock(const char* c, long n, double pr) { company = new char[strlen(c) + 1]; strcpy(company, c); 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."; else if (num > shares) cout << "You can't sell more than you have!" << "Transaction is aborted!"; else { shares -= num; share_val = price; set_tot(); } } void Stock::updata(double price) { share_val = price; set_tot(); } const Stock& Stock::topval(const Stock& s)const { if (s.total_val > total_val) return s; else return *this; } std::ostream& operator<<(std::ostream& os, const Stock& s) { ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield); streamsize prec = cout.precision(3); cout << "Company: " << s.company << " Shares: " << s.shares << endl; cout << " Shares Price: $" << s.share_val; cout.precision(2); cout << " Total Worth: $" << s.total_val << endl; cout.setf(orig, ios_base::floatfield); cout.precision(prec); return os; } //main.cpp #include"stock3.h" #include<iostream> const int STKS = 4; int main() { using namespace std; 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) }; cout << "Stock holding:\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 << endl; return 0; }
practice4
#pragma once //stack11.h #ifndef STACK11_H_ #define STACK11_H_ typedef unsigned long Item; class Stack { enum{MAX=10}; Item* pitems; int size; int top; public: Stack(int n = MAX); Stack(const Stack& s); ~Stack(); bool isempty()const; bool isfull()const; bool push(const Item& item); bool pop(Item& item); Stack& operator=(const Stack& s); }; #endif //stack11.cpp #include"stack11.h" Stack::Stack(int n) { size = n; top = 0; pitems = new Item [size]; } Stack::Stack(const Stack& s) { size = s.size; top = s.top; delete[]pitems; pitems = new Item[size]; for (int i = 0; i < size; i++) pitems[i] = s.pitems[i]; } 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) return false; else { pitems[top++] = item; return true; } } bool Stack::pop(Item& item) { if (top == 0) return false; else { item = pitems[--top]; return true; } } Stack& Stack::operator=(const Stack& s) { if (this == &s) return *this; else { size = s.size; top = s.top; delete[]pitems; pitems = new Item[size]; for (int i = 0; i < size; i++) pitems[i] = s.pitems[i]; } } //stacker.cpp #include<iostream> #include"stack11.h" #include<cctype> void action(Stack& s); //把对一个栈的操作分为三部分分别对三个栈完成,来检验复制构造函数和赋值运算符 //分开的部分,每一部分的操作要以q退出 int main() { using namespace std; Stack s1; action(s1); Stack s2 = s1; action(s2); Stack s3; s3 = s2; action(s3); cout << "Bye!\n"; return 0; } void action(Stack& s) { using namespace std; char c; 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 >> c && toupper(c) != 'Q') { while (cin.get() != '\n') continue; if (!isalpha(c)) { cout << '\a'; continue; } switch (c) { case'A': case'a':cout << "Enter a PO number to add: "; cin >> po; if (s.isfull()) cout << "Stack already full.\n"; else s.push(po); break; case'P': case'p':if (s.isempty()) cout << "Stack already empty.\n"; else { s.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"; } }
practice5
//queue.h #pragma once class Customer { 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 { struct Node { Item item; Node* next; }; enum { Q_SIZE = 0 }; 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); }; //queue.cpp #include<cstdlib> #include"queue.h" using namespace std; void Customer::set(long when) { arrive = when; processtime = rand() % 3 + 1; } Queue::Queue(int qs) :qsize(qs) { front = rear = nullptr; items = 0; } Queue::~Queue() { Node* temp; while (front != nullptr) { 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 = nullptr; items++; if (front == nullptr) front = add; else rear->next = add; rear = add; return true; } bool Queue::dequeue(Item& item) { if (isempty()) return false; item = front->item; items--; Node* temp = front; front = front->next; delete temp; if (items == 0) rear = nullptr; return true; } //bank.cpp #include<iostream> #include<ctime> #include<cstdlib> #include"queue.h" using namespace std; const int MIN_PER_HR = 60; bool newcustomer(double x) { return(rand() * x / RAND_MAX < 1); } int main() { srand(time(0)); int hours[5] = { 100,150,200,250,300 }; for (int i = 0; i < 2; i++) { long cyclelimit = hours[i] * MIN_PER_HR; cout << "Hours: " << hours[i] << endl; for (int perhour = 10; perhour < 31; perhour++) { Queue line(10);//line不能在外面定义,因为凡是循环里面用到的变量都需要重置 //否则当turnaways出现后,line没有自动销毁,慢慢的就会累计错误 //结果会出现负数,我找了半天才发现是因为在外面定义了line double min_per_cust = MIN_PER_HR / (double)perhour; Item temp; long turnaways = 0; long customers = 0; long served = 0; long sum_line = 0; int wait = 0; long line_wait = 0; 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 <= 0 && !line.isempty()) { line.dequeue(temp); wait = temp.ptime(); line_wait += (cycle - temp.when()); served++; } if (wait > 0) wait--; sum_line += line.queuecount(); } cout << "The average wait time by " << perhour << " customers every hours: " << double(line_wait) / served << " minuties\n"; } } cout << "答案为18" << endl; cout << "Done!\n"; return 0; }
practice 6
前两个文件不变
//bank.cpp #include<iostream> #include<ctime> #include<cstdlib> #include"queue.h" using namespace std; const int MIN_PER_HR = 60; bool newcustomer(double x) { return(rand() * x / RAND_MAX < 1); } int main() { srand(time(0)); int hours[5] = { 100,150,200,250,300 }; for (int i = 0; i < 4; i++) { long cyclelimit = hours[i] * MIN_PER_HR * 6; //需要增加精度,cycle为10s cout << "Hours: " << hours[i] << endl; for (int perhour = 30; perhour < 41; perhour++) { Queue line1(10); Queue line2(10); double sec10_per_cust = MIN_PER_HR / (double)perhour * 6; Item temp1, temp2; long turnaways = 0; long customers = 0; long served = 0; long sum_line = 0; int wait1 = 0; int wait2 = 0; long line_wait = 0; for (int cycle = 0; cycle < cyclelimit; cycle++) { if (newcustomer(sec10_per_cust)) { if (line1.queuecount() <= line2.queuecount()) { if (line1.isfull()); else { temp1.set(cycle); line1.enqueue(temp1); } } else { if (line2.isfull()); else { temp2.set(cycle); line2.enqueue(temp2); } } } if (wait1 == 0 && !line1.isempty()) { line1.dequeue(temp1); wait1 = temp1.ptime() * 6; line_wait += cycle - temp1.when(); served++; } if (wait1 > 0) wait1--; if (wait2 == 0 && !line2.isempty()) { line2.dequeue(temp2); wait2 = temp2.ptime() * 6; line_wait += cycle - temp2.when(); served++; } if (wait2 > 0) wait2--; } cout << "The average wait time by " << perhour << " customers every hours: " << double(line_wait) / served / 6 << " minuties\n"; } } cout << "答案为34" << endl; cout << "Done!\n"; return 0; }