我写的第一个C++.
Github/PathFind
作者归档:weskiller
C++ 练习
今天下午看书的时候发现一个很有趣的问题。
《C++ Primer Plus》
示例14.1(studentc.h)中,定义了两个非常奇怪的类成员函数
#ifndef STUDENTC_H_ #define STUDENTC_H_ #include <iostream> #include <string> #include <valarray> class Student { private: typedef std::valarray<double> ArrayDb; std::string name; ArrayDb scores; std::ostream & arr_out(std::ostream & os) const; public: Student() :name("Null Student"), scores() {} explicit Student(const std::string & s) :name(s), scores() {} explicit Student(int n) :name("Nully"), scores(n) {} Student(const std::string & s, int n) :name(s), scores(n) {} Student(const std::string & s, const ArrayDb & a) : name(s), scores(a) {} Student(const char * str, const double * pd, int n) :name(str), scores(pd,n) {} ~Student() {} double Average() const; const std::string & Name() const; //[]重载函数1,似乎能匹配所有的调用 double & operator[](int i); //[]重载函数2,在有上面的重载函数下,似乎永远匹配不到 double operator[](int i) const; friend std::istream & operator>>(std::istream & is, Student & stu); friend std::istream & getline(std::istream & is, Student & stu); friend std::ostream & operator<<(std::ostream & os,const Student & stu); }; #endif
在实现中分别添加两个重载函数的输出,查看调用的情况
#include "studentc.h" using std::ostream; using std::endl; using std::istream; using std::string; double Student::Average() const { if (scores.size() > 0) return scores.sum() / scores.size(); else return 0; } const string & Student::Name() const { return name; } double & Student::operator[](int i) { std::cout << "Use double & " << std::endl; return scores[i]; } double Student::operator[](int i) const { std::cout << "Use double " << std::endl; return scores[i]; } ostream & Student::arr_out(ostream & os) const { int i; int lim = scores.size(); if (lim > 0) { for(i = 0; i < lim; i++) { os << scores[i] << " "; if ( i % 5 == 4) os << endl; } if ( i % 5 != 0) os << endl; } else os << " empty array "; return os; } istream & operator>>(istream & is, Student & stu) { is >> stu.name; return is; } istream & getline(istream & is, Student & stu) { getline(is,stu.name); return is; } ostream & operator<<(ostream & os, const Student & stu) { os << "Scores for " << stu.name << ":\n"; stu.arr_out(os); return os; }
#include "studentc.h" #include <iostream> using std::cin; using std::cout; using std::endl; void set(Student & sa, int n); const int pupils = 3; const int quizzes = 5; int main(void) { Student ada[pupils] = { Student(quizzes), Student(quizzes), Student(quizzes) }; int i; for (i = 0; i < pupils; ++i) set(ada[i], quizzes); cout << "\nStudent List:\n"; for (i = 0; i < pupils; ++i) cout << ada[i].Name() << endl; cout << "\nResults:"; for (i = 0; i < pupils; ++i) { cout << endl << ada[i]; cout << "average: " << ada[i].Average() << endl; } cout << "Done.\n"; return 0; } void set(Student & sa, int n) { cout << "Please enter the student's name: "; getline(cin,sa); cout << "Please enter " << n << " quiz scores:\n"; for (int i = 0; i < n; i++) cin >> sa[i]; while (cin.get() != '\n') continue; } [code title="输出结果"] Please enter the student's name: Gil Bayts Please enter 5 quiz scores: Use double & 92 94 96 93 95 Use double & Use double & Use double & Use double & Please enter the student's name: Pat Roone Please enter 5 quiz scores: Use double & 83 89 72 78 95 Use double & Use double & Use double & Use double & Please enter the student's name: Fleur O'Day Please enter 5 quiz scores: Use double & 92 89 96 74 64 Use double & Use double & Use double & Use double & Student List: Gil Bayts Pat Roone Fleur O'Day Results: Scores for Gil Bayts: 92 94 96 93 95 average: 94 Scores for Pat Roone: 83 89 72 78 95 average: 83.4 Scores for Fleur O'Day: 92 89 96 74 64 average: 83 Done.
可以看到,const版本的operator[]完全没有匹配到。
C++ Class练习
《C++ Primer Plus》
第12章 课后练习2
#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; 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; void Stringlow(); void Stringup(); int has(const char c); String operator+(const String & st1); operator char *() 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 String operator+(const char *, const String & st1); friend ostream & operator<<(ostream & os, const String & st); friend istream & operator>>(istream & is, String & st); static int HowMany(); }; #endif
#include <cstring> #include <cctype> #include "String.h" #include <iostream> 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; } String & String::operator=(const String & st) { delete [] str; len = strlen(st.str); 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]; } 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; } 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]); } /* 错误的重载函数,问题是构造temp的时候,已经使用new 分配了固定长度的内存。使用strcat的时候实际上已经内存溢出了. String String::operator+(const String & st1) { String temp(str); strcat(temp.str,st1.str); temp.len = strlen(str) + strlen(st1.str) + 1; return temp; } */ String String::operator+(const String & st1) { int nlen = strlen(st1.str) + strlen(str) + 1; char * nstr = new char[nlen]; strcpy(nstr,str); strcat(nstr,st1.str); String temp; delete [] temp.str; temp.str = nstr; return temp; } String::operator char *() const { return str; } String operator+(const char * st1,const String & st2) { String temp; strcat(temp.str,st1); strcat(temp.str,st2.str); temp.len = strlen(st1) + st2.len; return temp; } int String::has(const char c) { int count = 0; for(int i = 0; i < len; i++) if (str[i] == c ) count++; return count; }
#include <iostream> using namespace std; #include "String2.h" int main() { String s1(" and I am C++ stdudent."); String s2 = "Pleas 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; }
第12章 课后练习6
#ifndef QUEUE_H_ #define QUEUE_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
#include "queue.h" #include <cstdlib> #include <stdio.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; else rear->next = add; rear = add; return true; } bool Queue::dequeue(Item & item) { if(front == NULL) return false; item = front->item; items--; Node * temp = front; front = front->next; delete temp; if(items == 0) rear = NULL; return true; } void Customer::set(long when) { processtime = std::rand() % 3 + 1; arrive = when; } [code lang="C" title="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 << "Enter the number of simulation hours: "; int hours; cin >> hours; long cyclelimit = MIN_PER_HR * hours; cout << "Enter the average number of customers per hours: "; double perhour; cin >> perhour; double min_per_cust; min_per_cust = MIN_PER_HR / perhour ; Item temp1,temp2; long turnaways = 0; long customers = 0; long served = 0; long sum_line = 0; int wait_time1,wait_time2; wait_time1 = wait_time2 = 0; long line_wait = 0; for(int cycle = 0;cycle < cyclelimit; cycle++) { if (newcustomer(min_per_cust)) { if ( line1.isfull() && line2.isfull() ) turnaways++; else { customers++; if ( line1.isfull() ) { temp2.set(cycle); line2.enqueue(temp2); } else { temp1.set(cycle); line1.enqueue(temp1); } } } if (wait_time1 <= 0 && !line1.isempty()) { line1.dequeue(temp1); wait_time1 = temp1.ptime(); line_wait += cycle - temp1.when(); served++; } if (wait_time2 <= 0 && !line2.isempty()) { line2.dequeue(temp2); wait_time2 = temp2.ptime(); line_wait += cycle - temp2.when(); served++; } if(wait_time1 > 0) wait_time1--; if(wait_time2 > 0) wait_time2--; sum_line += ( line1.queuecount() + line2.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"; cout << "Done!\n"; return 0; } bool newcustomer(double x) { return (std::rand() * x / RAND_MAX < 1); }
函数指针
今天看到了函数指针这一小结,发现自己对指针的认知还是不够深刻,特意贴下来,日后回顾。
《C++ Primer Plus》
第七章 7.19(arfupt.cpp)
#include <iostream> const double * f1(const double ar[], int n); const double * f2(const double [], int); const double * f3(const double *, int); int main() { using namespace std; double av[3] = { 1112.3, 1542.6, 2227.9 }; //p1 指向 f1 const double * (*p1)(const double * ,int) = f1; //自动声明类型 auto p2 = f2; cout << "Using pointers to functions:\n"; cout << " Address Value\n"; cout << (*p1)(av,3) << ": " << *(*p1)(av,3) << endl; cout << (*p2)(av,3) << ": " << *(*p2)(av,3) << endl; //注意()优先级大于*,*p2(av,3) == *(p2(av,3)) cout << p2(av,3) << ": " << *p2(av,3) << endl; //二级指针 const double * (*pa[3])(const double * , int) = { f1,f2,f3 }; auto pb = pa; cout << "\nUsing an array of pointers to functions:\n"; cout << " Address Value\n"; for (int i = 0;i < 3;i++) // (*(pa+i))(av,3) == pa[i](av,3) 似乎[]优先级高于() cout << (*(pa + i))(av,3) << ": " << *(*(pa+i))(av,3) << endl; cout << "\nUsing a pointer to a pointer to a function:\n"; cout << " Address Value\n"; for (int i = 0;i < 3; i++) cout << pb[i](av,3) << ": " << *pb[i](av,3) << endl; cout << "\nUsing pointers to an array of pointers:\n"; cout << " Address Value\n"; // 三级指针 const double *(*(*pd)[3])(const double *, int ) = & pa; auto pc = &pa; const double * pdb = (*pd)[1](av,3); cout << (*pc)[0](av,3) << ": " << *(*pc)[0](av,3) << endl; cout << pdb << ": " << *pdb << endl; cout << (*(*pd)[2])(av,3) << ": " << *(*(*pd)[2])(av,3) << endl; return 0; } const double * f1 (const double * ar, int n) { return ar; } const double * f2 (const double ar[] , int n) { return ar+1; } const double * f3 (const double * ar, int n) { return ar+2; }
第七章 复习题-13
#include <iostream> #include <cstring> //声明一个结构体 struct applicant { char name[30]; int credit_rating[3]; }; using namespace std; //声明一个show函数 void show(applicant *); //声明一个empty函数 void empty(const applicant *); //声明一个函数指针类型 typedef void (*tempty)(const applicant *); //声明一个指向empty函数的函数指针p1 tempty p1 = empty; //声明一个函数strscat const char * strscat(const applicant *, const applicant *); //声明一个函数指针p2,并指向strscat const char * (*p2)(const applicant *,const applicant *) = strscat; //声明一个包含5个函数指针的数组ap tempty ap [5]; //声明一个包含10个函数指针的数组pb const char * (*(pb[10]))(const applicant * ,const applicant *); //同上,声明一个包含10个函数指针的数组pc const char * (*pc[10])(const applicant * ,const applicant *); //声明一个指向包含10个函数指针的数组的指针pa char * (*(*pa[10]))(const applicant * ,const applicant *); int main() { struct applicant test = { "=-=.",{ 0,1,2 } }; cout << "Use show function." << endl; show(&test); cout << "Use strscat function." << endl; const char * pstr = strscat(&test,&test); cout << pstr << endl; //忘记添加的delete. =_=! delete [] pstr; return 0; } void show(struct applicant * app) { cout << app->name << endl; for (int i = 0; i < 3; i++) cout << app->credit_rating[i] << endl; return; } void empty(const applicant * a) { return; } const char * strscat(const applicant * chars1, const applicant * chars2) { char pstr [20]; strcpy(pstr,chars1->name); char * str = new char [40]; strcpy(str,strcat(pstr,chars2->name)); return str; }