480 likes | 784 Views
程序设计实习 作业解答. 2012-3. 作业二:魔 兽世界 之一. 描述 : 魔 兽世界的西面是红魔军的司令部,东面是蓝魔军的司令部 。 两 军的司令部都会制造武士。武士一共有 dragon 、 ninja 、 iceman 、 lion 、 wolf 五种。每种武士都有编号、生命值、攻击力这三种属性。 双方的武士编号都是从 1 开始计算。红方制造出来的第 n 个武士,编号就是 n 。同样,蓝方制造出来的第 n 个武士,编号也是 n 。 武士 在刚降生的时候有一个生命值 。 在 每个整点,双方的司令部中各有一个武士降生 。
E N D
程序设计实习作业解答 2012-3
作业二:魔兽世界之一 • 描述: • 魔兽世界的西面是红魔军的司令部,东面是蓝魔军的司令部。 • 两军的司令部都会制造武士。武士一共有 dragon 、ninja、iceman、lion、wolf 五种。每种武士都有编号、生命值、攻击力这三种属性。 • 双方的武士编号都是从1开始计算。红方制造出来的第n个武士,编号就是n。同样,蓝方制造出来的第n个武士,编号也是n。 • 武士在刚降生的时候有一个生命值。 • 在每个整点,双方的司令部中各有一个武士降生。 • 红方司令部按照iceman、lion、wolf、ninja、dragon的顺序循环制造武士。 • 蓝方司令部按照lion、dragon、ninja、iceman、wolf的顺序循环制造武士。 • 制造武士需要生命元。 • 制造一个初始生命值为m的武士,司令部中的生命元就要减少m个。 • 如果司令部中的生命元不足以制造某个按顺序应该制造的武士,那么司令部就试图制造下一个。如果所有武士都不能制造了,则司令部停止制造武士。 • 给定一个时间,和双方司令部的初始生命元数目,要求你将从0点0分开始到双方司令部停止制造武士为止的所有事件按顺序输出。
作业二:魔兽世界之一 • 描述: • 魔兽世界的西面是红魔军的司令部,东面是蓝魔军的司令部。 • 两军的司令部都会制造武士。武士一共有 dragon 、ninja、iceman、lion、wolf 五种。每种武士都有编号、生命值、攻击力这三种属性。 • 双方的武士编号都是从1开始计算。红方制造出来的第n个武士,编号就是n。同样,蓝方制造出来的第n个武士,编号也是n。 • 武士在刚降生的时候有一个生命值。 • 在每个整点,双方的司令部中各有一个武士降生。 • 红方司令部按照iceman、lion、wolf、ninja、dragon的顺序循环制造武士。 • 蓝方司令部按照lion、dragon、ninja、iceman、wolf的顺序循环制造武士。 • 制造武士需要生命元。 • 制造一个初始生命值为m的武士,司令部中的生命元就要减少m个。 • 如果司令部中的生命元不足以制造某个按顺序应该制造的武士,那么司令部就试图制造下一个。如果所有武士都不能制造了,则司令部停止制造武士。 • 给定一个时间,和双方司令部的初始生命元数目,要求你将从0点0分开始到双方司令部停止制造武士为止的所有事件按顺序输出。
1 写出下面程序的运行结果 类和对象的基本概念 — 作业三 解析: return返回时,产生临时变量,调用拷贝构造函数,函数完全返回后,临时变量销毁,n 减小 4 1 验证: 插入print语句
类和对象的基本概念 — 作业三 2 写出下面程序的运行结果 解析:构造函数和复制构造函数的调用 注意区分: Sample b=a; d=a; 切记:不同的编译选项可能会影响程序结果 eg. Realse vs. Debug 建议:赋值构造函数参数使用const . 9 不优化:22 优化:20 5
Return value optimization 原始版本 原始版本 实现伪码 优化版本 实现伪码
Return value optimization • Options • gcc -fno-elide-constructors • Visual C++ /Od /O2 • 扩展阅读: • Named Return Value Optimization in Visual C++ 2005 • Return value optimization (wikipedia)
类和对象的基本概念 — 作业三 2 写出下面程序的运行结果 解析:构造函数和复制构造函数的调用 注意区分: Sample b=a; d=a; 切记:不同的编译选项可能会影响程序结果 eg. Realse vs. Debug 建议:赋值构造函数参数使用const . 9 不优化:22 优化:20 5
3 程序输出结果如下, 请填空 class A { public: int val; A(____________ ){ val = n; }; ___________ GetObj() { return ________; } }; main() { A a; cout <<a.val << endl; 0 a.GetObj() = 5; cout << a.val << endl; //修改了val 5 } 类和对象的基本概念 — 作业三 (int n=0) int& GetObj(){ return val; } 或者 A& GetObj(){ return *this; }
自动类型转换之构造函数转换 自动类型转换:如果编译器看到一个表达式或函数调用了一个不合适的类型,它经常会将当前类型转到所需要的类型。 构造函数转换:如果一个构造函数函数能把另一类型对象(或引用)作为它的单个参数,那么这个构造函数允许编译器执行自动类型转换。
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(); } 类和对象的基本概念 — 作业三
构造函数 Complex() {}; Complex (const char * a) { … } 另一种思路 重载赋值操作符 Complex &operator=(const char * a) { … } 演示 类和对象的基本概念 — 作业三 • Print( )函数限制了只做正数 • 答案只是参考 • 完整的Complex类还需要完善
5 程序输出结果如下, 请填空 10 补足Sample类的成员函数,不能增加成员变量 class Sample{ public: int v; Sample(int n):v(n) { }; }; main() { Sample a(5); Sample b = a; cout << b.v ; } 类和对象的基本概念 — 作业三 Sample( const Sample & x) { v = 2 * x.v ; }
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 () ; • }
补足成员函数 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); } 类和对象的基本概念 — 作业三
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(const 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; • }
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; }
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); }
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
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 运算符重载— 作业三
运算符重载— 作业三 using std::cout; using std::endl; int main(){ Array2 a(3,4); inti,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; } 有哪些操作? 内部如何实现?
运算符重载— 作业三 注:重载的实际上是第二维的[],第一维的[]直接调用int型一维数组的定义
运算符重载— 作业三 第二种解法:
4 程序输出结果如下, 写一个HugeInt类 1)100000089000000 2)100000089000000 3)10000 4)10000 5)10001 6)10006 7)100000089010006 运算符重载— 作业三 有多少人没有把代码编译运行就提交了? 我是编译器?
运算符重载— 作业三 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; }
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-
继承和多态— 作业四 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); }
继承和多态— 作业四 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; }
继承和多态— 作业四 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
继承和多态— 作业四 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; }
继承和多态— 作业四 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); }
继承和多态— 作业四 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; } }
继承和多态— 作业四 Mystring类(7) 2 从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); } };
作业六:魔兽世界之二 • 两军的司令部都会制造武士。武士一共有 dragon 、ninja、iceman、lion、wolf 五种。每种武士都有编号、生命值这两种属性。 • 有的武士可以拥有武器。武器有三种,sword, bomb,和arrow,编号分别为0,1,2。 • 不同的武士有不同的特点。 • dragon 可以拥有一件武器。编号为n的dragon降生时即获得编号为 n%3 的武器。dragon还有“士气”这个属性,是个浮点数,其值为它降生后其司令部剩余生命元的数量除以造dragon所需的生命元数量。 • ninjia可以拥有两件武器。编号为n的ninjia降生时即获得编号为 n%3 和 (n+1)%3的武器。 • iceman有一件武器。编号为n的iceman降生时即获得编号为 n%3 的武器。 • lion 有“忠诚度”这个属性,其值等于它降生后其司令部剩余生命元的数目。 • wolf没特点。 • 请注意,在以后的题目里,武士的士气,生命值,忠诚度在其生存期间都可能发生变化,都有作用,武士手中的武器随着使用攻击力也会发生变化。
问题 • 没使用类 • 把类当全局变量,只用来保存数据 • 类设计得不好,结构层次不清晰 • 只有很少几位同学的作业达到要求 • 希望找点时间对照参考答案多思考
1 写出下面程序的运行结果 继承和多态— 作业六 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;} };
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
2 写出下面程序的运行结果 继承和多态— 作业六 class A { public: A( ) { } virtual void func() { cout << "A::func" << endl; } ~A( ) { } virtual void fund( ) { cout << "A::fund" << endl; } }; class B:public A { public: B ( ) { func( ) ; } void fun( ) { func( ) ; } ~B ( ) { fund( ); } }; class C : public B { public : C( ) { } void func( ) {cout << "C::func" << endl; } ~C() { fund( ); } void fund() { cout << "C::fund" << endl;} }; main() { C c; } A::func C::fund A::fund
3 程序输出结果如下, 请填空 继承和多态— 作业六 A::Fun C::Do 请补足横线上丢失的部分 #include <iostream.h> class A { private: int nVal; public: void Fun() { cout << "A::Fun" << endl; }; void Do() { cout << "A::Do" << endl; } }; 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; } }; void Call( ___________ ) { p.Fun(); p.Do(); } main() { C c; Call( c); } B & p
4 程序输出结果如下, 请填空 继承和多态— 作业六 destructor B destructor A 请完整写出 class A. 限制条件:不得为 class A 编写构造函数 #include <iostream.h> class A { ……… }; class B:public A { public: ~B() { cout << "destructor B" << endl; } }; main() { A * pa; pa = new B; delete pa; } class A { public: virtual ~A() { cout << "destructor A" << endl; } };
5 程序输出结果如下, 请填空 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; } };
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()); }