1 / 57

程序设计实习 第二十一讲 习题课

程序设计实习 第二十一讲 习题课. 类和对象基本概念 (1). 写出下面程序的运行结果 class Apple { private : static int nTotalNumber; public: Apple() { nTotalNumber ++; } ~Apple( ) { nTotalNumber --; } static void PrintTotal() { cout << nTotalNumber << endl; } }; int Apple::nTotalNumber = 0;

Télécharger la présentation

程序设计实习 第二十一讲 习题课

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 程序设计实习第二十一讲 习题课

  2. 类和对象基本概念(1) 写出下面程序的运行结果 class Apple { private : static int nTotalNumber; public: Apple() { nTotalNumber ++; } ~Apple( ) { nTotalNumber --; } static void PrintTotal() { cout << nTotalNumber << endl; } }; int Apple::nTotalNumber = 0; Apple Fun( const Apple & a ) { a.PrintTotal(); return a ; } int main () { Apple * p = new Apple[4]; Fun( p[2]); Apple p1, p2; delete [] p; p1.PrintTotal(); } 解析:return返回时,产生临时变量,Total Number析构时会减小 4 1

  3. 类和对象基本概念(2) *写出下面程序的运行结果 class Sample{ public: int v; Sample() { }; Sample(int n):v(n) { }; Sample( Sample & x) { v = 2 + x.v ; } }; Sample PrintAndDouble( Sample o){ cout << o.v <<endl; o.v = 2 * o.v; return o; } int main(){ Sample a(5); Sample b = a; Sample c = PrintAndDouble( b ); cout << c.v << endl; Sample d; d = a; cout << d.v ; } 解析:构造函数和复制构造函数的调用 9 22 5  注意区分: Sample b=a;  d=a; (vc2008实际运行结果为20)

  4. 类和对象基本概念(3) 程序输出结果如下,请填空 0 5 class A { public: int val; A(____________ ){ val = n; }; ___________ GetObj() { return ________; } }; main() { A a; cout <<a.val << endl; a.GetObj() = 5; cout << a.val << endl; } A(int n=0) A& GetObj(){ return *this; } 或者 int& GetObj(){ return val; }

  5. 类和对象基本概念(4) 程序输出结果如下,请填空 3+4i 5+6i 补足Complex类的成员函数,不能增加成员变量 class Complex { private: double r,i; public: void Print() {cout << r << "+" << i << "i" << endl;} }; int main() { Complex a; a = "3+4i"; a.Print(); a = "5+6i"; a.Print(); }

  6. 类和对象基本概念(4) 构造函数 Complex() {}; Complex (const char t[]) { if(!t) { r=0.0; i=0.0; } else { r = t[0] - '0'; i = t[2] - '0'; } } • 另一种思路 重载赋值操作符 Complex &operator=(const char t[]) { if(!t) { r=0.0; i=0.0; } else { r = t[0] - '0'; i = t[2] - '0'; } return *this; }

  7. 类和对象基本概念(5) 程序输出结果如下,请填空 10 补足Sample类的成员函数,不能增加成员变量 class Sample{ public: int v; Sample(int n):v(n) { }; }; main() { Sample a(5); Sample b = a; cout << b.v ; } Sample( Sample & x) { v = 2 * x.v ; }

  8. 类和对象基本概念(6) 程序输出结果如下,请填空 This Hello 补足MyString类的成员函数,不能增加成员变量 class MyString{ char * p; public: MyString( char * s ) { p = new char[strlen(s)+1]; strcpy(p,s); } ~MyString() { delete [] p;} const char * c_str() { return p;} }; • main(){ • MyString s1("This"), s2 =s1; • s2.Copy ( "Hello"); • cout << s1.c_str () • << endl << s2.c_str () ; • }

  9. 类和对象基本概念(6) 补足成员函数 void Copy( char * s) { delete [] p; p = new char[strlen(s)+1]; strcpy(p,s); } MyString( MyString & o ) { p = new char[strlen(o.p ) + 1 ]; strcpy( p, o.p); }

  10. 类和对象基本概念(7) 程序输出结果如下,请填空 5,5 5,5 class Base { public: int k; Base (int n) : k(n) { } }; class Big{ public: int v; Base b; Big _____________ { } Big _____________ { } }; Big(int n):v(n),b(n){ } Big(Big & x):v(x.v),b(x.b.k){ } • main(){ • Big a1(5); • Big a2 = a1; • cout << a1.v << "," • << a1.b.k << endl; • cout << a2.v << "," • << a2.b.k << endl; • }

  11. 运算符重载(1) 程序输出结果如下,请填空 4,1 请写出被隐藏的部分,MyInt的成员函数里不允许使用静态变量 class MyInt { int nVal; public: MyInt( int n) { nVal = n ;} int ReturnVal() { return nVal;} …………………. }; main () { MyInt objInt(10); objInt-2-1-3; cout << objInt.ReturnVal(); cout <<","; objInt-2-1; cout << objInt.ReturnVal(); } MyInt & operator -( int x) { nVal -= x; return * this; }

  12. 运算符重载(2) *程序输出结果如下,请填空 (4,5) (7,8) class Point { private: int x; int y; public: Point(int x_,int y_ ):x(x_),y(y_) { }; _____; }; _____ operator << (_____, const Point & p) { _____; return ______; } main(){ cout << Point(4,5) << Point(7,8); }

  13. 运算符重载(2) class Point { private: int x; int y; public: Point(int x_,int y_ ):x(x_),y(y_) { }; _____; }; _____ operator << (_____, const Point & p) { _____; return ______; } friend ostream & operator<< ( ostream & o, const Point & p); ostream & operator << ( ostream & o, const Point & p) o << "(" << p.x << "," << p.y << ")"<< endl; o

  14. 运算符重载(3) *程序输出结果如下,写一个二维数组类 Array2 0,1,2,3, 4,5,6,7, 8,9,10,11 next 0,1,2,3, 4,5,6,7, 8,9,10,11

  15. 运算符重载(3) using std::cout; using std::endl; int main(){ Array2 a(3,4); int i,j; for( i = 0;i < 3; i ++ ) for( j = 0; j < 4; j ++ ) a[i][j] = i * 4 + j; for( i = 0;i < 3; i ++ ) { for( j = 0; j < 4; j ++ ) { cout << a(i,j) << ","; } cout << endl; } cout << "next" << endl; Array2 b; b = a; for( i = 0;i < 3; i ++ ) { for( j = 0; j < 4; j ++ ) { cout << b[i][j] << ","; } cout << endl; } return 0; }

  16. 运算符重载(3) class Array2 { private: int * p; int r,c; public: Array2() { p = NULL ; } Array2( int r_, int c_ ):r(r_),c(c_) { p = new int [ r * c]; } Array2( Array2 & a ):r(a.r),c(a.c) { p = new int [r * c]; memcpy( p, a.p, sizeof(int )*r*c); } Array2 & operator=(const Array2 & a) { if( p ) delete [] p; r = a.r; c = a.c;p = new int [r * c]; memcpy( p, a.p, sizeof(int ) * r * c); return * this; } ~Array2() { if( p) delete [] p; } int * operator [] ( int i ) { return p + i * c; } int & operator() ( int i,int j ) { return p[ i * c + j]; } 注:重载的实际上是第二维的[],第一维的[]直接调用int型一维数组的定义

  17. 运算符重载(3):第二种解法 class CWordArr{ private: int *m_pdat; long m_size; public: CWordArr(long size) { m_pdat= new int[size]; m_size = size; }; ~CWordArr() { delete[] m_pdat; }; int& operator[](long idx) { return m_pdat[idx]; } };

  18. 运算符重载(3):第二种解法 • ~ Array2() { • for (long i=0;i<m_col;i++) { • delete m_p[i]; • m_p[i]=NULL; • } • delete[] m_p; • } • CWordArr& operator[](long idx) { • return *m_p[idx]; • } • int & operator() ( int i,int j ) { • return (*m_p[i])[j]; • }} class Array2{ private: CWordArr **m_p; long m_col,m_row; public: Array2(long col,long row) { m_p=new CWordArr*[col]; for (long i=0;i<col;i++) m_p[i]= new CWordArr(row); m_col=col; m_row=row; } • 通过两次[]重载的叠加,就可以用a[x][y]的方式来访问数组元素 • C++不可能在一个类里面实现[][]的重载(若这种相当于三元算符),因此有两个类:一个是一维数组类,实现[]的重载;另一个类是二维数组类,必须持有一组一维数组类的实例,存放二维数组的各个行的数组,二维数组类也要重载[]运算符

  19. 运算符重载(4) 程序输出结果如下,写一个HugeInt类 1)100000089000000 2)100000089000000 3)10000 4)10000 5)10001 6)10006 7)100000089010006

  20. 运算符重载(4) void main(){ CHugeInt a("1234545436342424354354365289899834234235"); CHugeInt d(9999); CHugeInt temp = CHugeInt("100000088888888") + 111112; CHugeInt temp2 = 111112+CHugeInt("100000088888888"); cout << "1)" << temp << endl; cout << "2)" << temp2 << endl; cout << "3)" << ++d << endl; cout << "4)" << d++ << endl; cout << "5)" << d << endl; d += 5; cout << "6)" << d << endl; cout << "7)" << d + temp; }

  21. 运算符重载(4) //重载运算符+ CHugeInt operator +(const CHugeInt & n) const { CHugeInt tmp( * this); for( int i = 0;i < MAX ; i ++ ) { tmp.Number[i] += n.Number[i];//逐位相加if( tmp.Number[i] >= 10 ) {//看是否要进位 tmp.Number[i] -= 10; tmp.Number[i+1] ++;//进位 } } return tmp; } const CHugeInt & operator++() { * this = ( * this ) + 1; return * this; }// ++n const CHugeInt operator++(int n) { CHugeInt tmp = * this; * this = ( * this ) + 1; return tmp; }//n++ const CHugeInt operator +=( const CHugeInt & n){ * this = ( * this ) + n; return * this; } 代码过多,只截取部分

  22. 运算符重载(4) friend ostream & operator << (ostream & o, const CHugeInt & n); friend CHugeInt operator+ ( int n1 , const CHugeInt & n2); CHugeInt operator + ( int n1 ,const CHugeInt & n2) { return n2 + n1; } ostream & operator << ( ostream & o, const CHugeInt & n){ bool bStart = false; for( int i = MAX -1; i >= 0 ; i -- ) { if( n.Number[i] ) { bStart = true; } if( bStart ) cout << n.Number[i]; } if( !bStart )//没有数字时,输出0 cout << 0; return o; }

  23. 继承和多态(1) 程序输出结果如下,写一个Mystring类 1. abcd-efgh-abcd-2. abcd-3.4. abcd-efgh-5. efgh-6. c7. abcd-8. ijAl-9. ijAl-mnop10. qrst-abcd-11. abcd-qrst-abcd- uvw xyz aboutbigmetakeabcdqrst-abcd-

  24. Mystring类(1) #include<iostream> #include<cstring> using namespace std; class MyString { public: char *p; MyString() // 构造函数 { p = NULL; } MyString(char *t) // 构造函数 { p = new char[strlen(t) + 1]; strcpy(p,t); } MyString(const MyString &s) // 复制构造函数 { p = new char[strlen(s.p) + 1]; strcpy(p, s.p); }

  25. Mystring类(2) ~MyString() // 析构函数 { if(p) delete[]p; } MyString operator+(const MyString &s) // +号重载,这里表示 //两个MyString类型相加的情况 { char *q; q = new char[strlen(p) + strlen(s.p)+1]; strcpy(q, p); strcat(q, s.p); MyString temp(q); delete []q; return temp; }

  26. Mystring类(3) MyString operator+(const char *s) // +号重载,这里表示 //MyString类型+字符串的情形 { char *q; q = new char[strlen(p) + strlen(s) + 1]; strcpy(q, p); strcat(q, s); MyString temp(q); delete []q; return temp; } MyString& operator=(const MyString &s) // 赋值号重载 { if(p!=NULL) { delete[]p; } p = new char[strlen(s.p)+1]; strcpy(p, s.p); return *this; }0

  27. Mystring类(4) char &operator[](int n) // []号重载 { return p[n]; } MyString& operator+=(char *s) // +=号重载 { char *q; q = new char[strlen(p)+1]; strcpy(q, p); if(p != NULL) { delete []p; } p = new char[strlen(p) + strlen(s) + 1]; strcpy(p,q); strcat(p,s); delete []q; return *this; }

  28. Mystring类(5) MyString operator()(int i, int n) { // ()重载 char *q; q = new char[n+1]; strncpy(q, p+i, n); q[n] = '\0'; MyString temp(q); delete []q; return temp; } }; ostream &operator<< (ostream &o, const MyString &s) // <<号重载 { o << s.p; return o; } MyString operator+(char *s, const MyString &t) // +号重载,这里是字符串+MyString的情形 { char q[100]; strcpy(q, s); strcat(q, t.p); return MyString(q); }

  29. Mystring类(6) // <,==,> 号的重载 int operator<(const MyString &s1, const MyString &s2) { if(strcmp(s1.p,s2.p) < 0) { return 1; } else { return 0; } } int operator==(const MyString &s1, const MyString &s2) { if(!strcmp(s1.p, s2.p)) { return 1; } else { return 0; } } int operator>(const MyString &s1, const MyString &s2) { if(strcmp(s1.p, s2.p) > 0) { return 1; } else { return 0; } }

  30. Mystring类(8) 从string类派生的写法 class MyString : public string{ public: MyString():string() {}; MyString( const char * s):string(s){}; MyString( const string & s ): string(s){}; MyString operator() ( int s, int l) { return this->substr(s,l); }; };

  31. 继承和多态(2) 写出下面程序的运行结果 class D:public B { private : int nDVal; public: void Print() { B::Print(); cout << "nDVal="<<nDVal <<endl; } D( int n) : B(3*n) {nDVal = n;} void Fun() { cout << "D::Fun" << endl; } }; class B { private: int nBVal; public: void Print() { cout << "nBVal="<< nBVal << endl; } void Fun() {cout << "B::Fun" << endl; } B ( int n ) { nBVal = n;} };

  32. 继承和多态(2) main() { B * pb; D * pd; D d(4); d.Fun(); pb = new B(2); pd = new D(8); pb -> Fun(); pd->Fun(); pb->Print (); pd->Print (); pb = & d; pb->Fun(); pb->Print(); } D::Fun B::Fun D::Fun nBVal=2 nBVal=24 nDVal=8 B::Fun nBVal=12

  33. 继承和多态(3) 程序输出结果如下,请填空 A::Fun A::Do A::Fun C::Do class B:public A { public: virtual void Do() { cout << "B::Do" << endl;} }; class C:public B { public: void Do( ) { cout <<"C::Do"<<endl; } void Fun() { cout << "C::Fun" << endl; } }; class A { private: int nVal; public: void Fun() { cout << "A::Fun" << endl; }; virtual void Do() { cout << "A::Do" << endl; } };

  34. 继承和多态(3) void Call(____________) { p->Fun(); p->Do(); } main() { Call( new A()); Call( new C()); } A & p A * p void Call(____________) { p.Fun(); p.Do(); } main() { Call(A()); Call(C()); }

  35. 模板(1) *设计CLinkList类模板中AppendNode 和PrintList成员函数,得到如下结果 0,1,2,3, 0,1,2,3,9,10,11, 注意: 1)不得调用任何库函数,库模板,不得使用static关键字,不得使用除 NULL 以外的任何常量 2)不得为Node和CLinkList模板添加任何成员 3)不得添加任何全局变量,不得添加其他函数

  36. 模板(1) template <class D> class Node { public: D data; Node * next; }; template<class D> class CLinkList { private: Node<D> * pHead; public: CLinkList(); void AppendNode( D data); void PrintList(); }; template<class D> CLinkList<D>::CLinkList() { pHead = new Node<D>; pHead->next = NULL; }; main() { CLinkList<int> l; for( int i = 0;i < 4;i ++) l.AppendNode(i); l.PrintList(); cout << endl; for( i = 9;i < 12;i ++) l.AppendNode(i); l.PrintList(); }

  37. 模板(1) template<class D> void CLinkList<D>::AppendNode( D data) { Node<D> * p = pHead; while( p->next ) p = p->next; p->next = new Node<D>; p = p->next; p->data = data; p->next = NULL; } template<class D> void CLinkList<D>::PrintList() { Node<D> * p = pHead; while( p->next ) { cout << p->next->data << ","; p = p->next; } }

  38. 模板(2) 填空使程序能编译通过,并写出运行的输出结果 #include <iostream> template <_____________> class myclass { T i; public: myclass (T a) { i = a; } void show( ) { cout << i << endl; } }; void main() { myclass<________> obj("This"); obj.show(); } class T This 该程序输出结果为:_____ char *

  39. 模板(2) 填空得到以下结果 TomHanks 注意,不允许使用任何常量 ~myclass( ) { delete [] p; } void Show() { for( int i = 0;i < nSize;i ++ ) { cout << p[i]; } } }; main() { char * szName = "TomHanks"; myclass<char > obj (____________________); obj.Show(); } template <class T> class myclass { _________; int nSize; public: myclass ( ______________, int n) { p = new T[n]; for( int i = 0;i < n;i ++ ) p[i] = a[i]; nSize = n; } T * p T * a szName,strlen(szName)

  40. STL(1) 看程序写结果 main() { vector<A*> vp; vp.push_back(new A(1)); vp.push_back(new A(2)); vector<A> v; v.push_back (3); } class A { private : int nId; public: A(int n) { nId = n; cout << nId << " contructor" << endl; }; A( const A & a ) { nId = a.nId ; cout << nId << " copy constructor" << endl; } ~A( ) { cout << nId << " destructor" << endl; } }; 1 contructor 2 contructor 3 contructor 3 copy constructor 3 destructor 3 destructor

  41. STL(2) 程序输出结果如下,请填空 Tom,Jack,Mary,John, template <_______ , _______> class MyClass { T array[T2]; public: MyClass( T * begin ) { copy( begin, begin + T2, array); } void List() { T * i; for( i = array; i != array + T2;i ++) cout << * i << "," ; } }; class T int T2 main() { string array[4] = { "Tom","Jack","Mary","John"}; _____________________ ; obj.List(); } MyClass<string,4> obj(array)

  42. STL(3) 程序输出结果如下,请填空 Tom,Jack,Mary,John, main() { string array[4] = { "Tom","Jack","Mary","John"}; _________________________; obj.List(); } template <class T> class MyClass { vector<T> array; public: MyClass ( T * begin,int n ):array(n) { copy( begin, begin + n, array.begin()); } void List() { ________________________; for( i = array.begin(); i != array.end();i ++) cout << * i << "," ; } }; MyClass<string> obj( array,4) vector<T>::iterator i;

  43. STL(4) 程序输出结果如下,请填空 1 2 6 7 8 9 main() { int a[] = {8,7,8,9,6,2,1}; ___________________; for( int i = 0;i < 7;i ++ ) ___________________; ostream_iterator<int> o(cout," "); copy( v.begin(),v.end(),o); } set<int >v v.insert(a[i])

  44. STL(5) 程序输出结果如下,请填空 A::Print: 1 B::Print: 2 B::Print: 3 template <class T> void PrintAll( const T & c ){ T::const_iterator i; for( i = c.begin(); i != c.end(); i ++ ) _______________________; }; class A { protected: int nVal; public: A(int i):nVal(i) { } virtual void Print() { cout << "A::Print: " << nVal << endl; } }; (*i)->Print()

  45. STL(5) class B:public A { public: B(int i):A(i) { } void Print() { cout << "B::Print: " << nVal << endl; } }; main() { __________________; v.push_back( new A(1)); v.push_back (new B(2)); v.push_back (new B(3)); PrintAll( v); } vector<A*> v

  46. STL(6) *写一个自己的 CMyostream_iterator 模板,使之能和 ostream_iterator 模板达到一样的效果 using namespace std; main() { int a[5] = {1,2,3,4,5}; CMyostream_iterator<int> output(cout,"*"); vector<int> v(a,a+5); copy(v.begin(),v.end(),output); }

  47. 提示 要支持copy函数必须重载三个运算符:*,=,++ 参考 copy 的help template<class InIt, class OutIt> OutIt copy(InIt first, InIt last, OutIt x); The template function evaluates *(x + N) = *(first + N)) once for each N in the range [0, last - first), for strictly increasing values of N beginning with the lowest value. It then returns x + N. If x and first designate regions of storage, x must not be in the range [first, last) copy 的源代码: template<class _II, class _OI> inline _OI copy(_II _F, _II _L, _OI _X) {for (; _F != _L; ++_X, ++_F) *_X = *_F; return (_X); } 47

  48. STL(6) template <class T> class CMyostream_iterator { private: ostream & o; string s; public: CMyostream_iterator( ostream & output, const char * sz): o(output),s(sz) {} void operator++() { }; void operator=(const T & val ) { o << val << s; } CMyostream_iterator & operator * ( ) { return * this; } };

  49. STL(7) 程序输出结果如下,请填空 5*3*4*2*1* 1*2*3*4*5* 1*2*9*4*5* main() { MyClass<int> obj(5); int a[] = { 5, 3, 4, 2,1 }; copy( a, a + 5, obj.begin()); ostream_iterator<int> output (cout,"*"); copy( obj.begin(),obj.end(),output); cout << endl; obj.sort(); copy( obj.begin(),obj.end(),output); cout << endl; obj[2] = 9; copy( obj.begin(),obj.end(),output); } template <class T> class MyClass: public list<T> { public: ____________________ (int n) { iterator i; int k = 0; for( ____________________________) { if( k == n) return _______________; k ++; } } MyClass(int n):___________________ {} }; T& operator[] i=begin();i != end(); i ++ * i list<T>(n) 注意:list容器类派生类的初始化

  50. STL(8) 标准矩形问题 其边平行于坐标轴 给定不重复的 n 个整点(横、纵坐标都是整数的点),求从这n个点中任取4点作为顶点所构成的四边形中,有多少个是标准矩形。 输入数据: 第一行是点的数目 其后每一行都代表一个点,由两个整数表示,第一个是x坐标,第二个是y坐标 输出要求: 输出标准矩形的数目

More Related