一.选择题
1.下面有关类和对象的说法中,不正确的是【 】。
A) 类是系统提供的一种数据类型 B) 对象是类的实例
C) 类和对象的关系是抽象和具体的关系 D) 任何一个对象只能属于一个具体的类
2.面向对象的特点主要概括为【 】。
A) 可分解性、可组合型性和可分类性 B) 继承性、封装性和多态性
C) 封装性、易维护性、可扩展性和可通用性 D) 抽象性、继承性和封装性
3.要使一个类能被同一命名空间中的其他类访问,但不能被这个命名空间以外的类访问,该类可以【 】。
A) 不使用任何修饰符 B) 使用private修饰符
C) 使用public修饰符 D) 使用internal修饰符
4.在C#中,【 】访问修饰符修饰的字段只能由当前程序集访问。
A) private B) public C) protected D) internal
5.类的字段和方法的默认访问修饰符是【 】。
A) public B) private C) protected D) internal
6.下列关于构造函数的描述中,不正确的是【 】。
A) 构造函数中,不可以包含return语句 B) 一个类只能有一个构造函数
C) 实例构造函数在生成类实例时被自动调用 D) 用户可以定义无参构造函数
7.下列关于构造函数的描述中,【 】是正确的。
A) 构造函数名必须与类名相同 B) 构造函数不可以重载
C) 构造函数不能带参数 D) 构造函数可以声明返回类型
8.下列的【 】不是构造函数的特征。
A) 构造函数的函数名与类名相同 B) 构造函数可以重载
C) 构造函数可以带有参数 D) 可以指定构造函数的返回值类型
9.类ClassA有一个名为M1的方法,在程序中有如下一段代码,假设该段代码是可以执行的,则声明M1方法时一定使用了【 】修饰符。
ClassA Aobj=new ClassA();
ClassA.M1();
A) public B) public static C) private D) virtual
10.在C#中,从属性的读写特性上来进行分类,可以划分为以下3种,除了【 】。
A) 只读属性 B) 只写属性 C) 读写属性 D) 不可读不可写属性
11.在C#中,以下关于属性的描述中正确的是【 】。
A) 属性是以public关键字修饰的字段,以public关键字修饰的字段也可称为属性
B) 属性是访问字段值的一种灵活机制,属性更好地实现了数据的封装和隐藏
C) 要定义只读属性只需在属性名前加上readonly关键字
D) C#的类中不能自定义属性
12.以下类MyClass的属性count属于【 】属性。
class MyClass
{ int i;
int count { get { return i; } }
}
A) 只读 B) 只写属性 C) 读写 D) 不可读不可写
13.C#中的TestClass为一自定义类,其中有如下属性定义:
public int Property{ …… }
使用以下语句创建了该类的对象,并让变量obj引用该对象。
TestClass obj=new TestClass();
那么,可通过【 】方式访问类TestClass的Property属性。
A) MyClass. Property B) obj. Property
C) TestClass. Property D) obj. Property()
14.关于C#语言的方法,下列叙述正确的是【 】。
A) 方法的定义不能嵌套,但方法的调用可以嵌套
B) 方法的定义可以嵌套,但方法的调用不能嵌套
C) 方法的定义和调用都不能嵌套
D) 方法的定义和调用都可以嵌套
15.以下所列的各方法头部中,正确的是【 】。
A) void play(var a:Integer, var b:Integer) B) void play(int a, b)
C) void play(int a, int b) D) Sub play(a as integer, b as integer)
16.在类A中定义了属性y:
class A
{ public int y
{ get { return 1; }
set { }
}
}
并试图通过下列代码来实现对属性y的访问:
A b=new A();
b.y=2;
int x=b.y;
对此,下列说法正确的是【 】。
A) 属性y可读可写,因此变量x的值为2
B) 属性y可读,但不可写,因此语句“b.y=2;”是错误的
C) 属性y可写,但不可读,因此语句“int x=b.y;”是错误的
D) 属性y可读可写,变量x的值为1
17.有以下类声明:
public class Class1
{ private string _sData="OK!";
privare string sData
{ set { _sData = value;} }
}
在Main函数中,在成功创建该类的对象obj后,以下【 】语句是合法的。
A) obj. _sData="Hello!" B) obj. set(obj.sData);
C) obj. sData="Hello!" D) Console.WriteLine(obj. sData);
18.在类的定义中,类的【 】描述了该类的对象的行为特征。
A) 字段 B) 方法 C) 属性 D) 类名
19.调用重载方法时,系统根据【 】来选择具体的方法。
A) 参数的类型 B) 参数的个数和类型
C) 参数个数 D) 方法的返回值类型
20.下列关于方法重载的说法中,完全正确的是【 】。
A) 重载方法的参数个数必须不同 B) 重载方法必须具有不同的形参列表
C) 重载方法必须具有不同的返回值类型 D) 重载方法的参数类型必须不同
21.关于静态成员,下列说法正确的是【 】。
A) 同一个类中的静态成员,类实例化后,在不同的对象中形成不同的静态成员
B) 在类实例化后,同类型的对象都共享类的静态成员,静态成员只有一个版本
C) 在类定义时静态成员属于类,在类实例化后静态成员属于对象
D) 在类实例化后静态成员已被实例化,因此不同的对象有不同的静态成员
22.下列关于静态方法的说法,错误的是【 】。
A) 静态方法不对特定实例进行操作,不与实例相关联
B) 使用静态方法的语法格式:类名.静态方法(实参列表)
C) 静态方法只能访问类中的静态成员,不能访问非静态成员
D) 静态方法不能访问类中的静态成员
23.已知: int a=100;
void Func(ref int b) { …… }
则下列函数调用正确的是【 】。
A) Func(ref(10*a)) B) Func(ref 10*a) C) Func(ref(a) ) D) Func(ref a)
24.下面对方法中的ref和out参数说明错误的是【 】。
A) ref和out参数传递方法相同,都是把实参的内存地址传递给形参,实参与形参指向同一个内存存储区域,但ref要求实参必须在调用之前明确赋过值
B) ref是将实参传入形参,out只能用于从方法中传出值,而不能从方法调用处接受实参数据。
C) ref和out参数因为传递的是实参的地址,所以要求实参和形参的数据类型必须一致
D) ref和out参数要求实参和形参的数据类型或者一致,或者实参能被隐式地转化为形参的类型
25.设方法Max的签名为:public void Max(out int max, params int[] a),maxval是一个int型的值类型变量,arrayA是一个int型的数组对象,则下列调用该方法的语句中有错的是【 】。
A) Max(maxval,4,5,3) B) Max(out maxval, 4, 5, 3)
C) Max(out maxval, arrayA) D) Max(out maxval, 4, 5)
26. 有以下类声明:
class Class1
{ public static int Count = 0;
public Class1()
{ Count++; }
}
在执行以下语句后,Class1.Count的值是【 】。
Class1 o1 = new Class1();
Class1 o2 = new Class1();
A) 1 B) 2 C) 3 D) 0
27.在类MyClass中有下列方法定义:
public void test(params int[] arr) { Console.Write("使用params参数!"); }
public void test(int x, int y) { Console.Write("使用两个整形参数!"); }
请问上述方法重载有无二义性?若没有,则下列语句的输出为【 】。
Myclass x=new MyClass();
x.test(0); x.test(0,1); x.test(0,1,2);
A) 有语义二义性
B) 使用params参数!使用params参数!使用params参数!
C) 使用params参数!使用两个整形参数!使用params参数!
D) 使用params参数!使用两个整形参数!使用两个整形参数!
28.分析以下C#语句,注意类MyClass没有访问修饰符。若必须为类MyClass添加访问修饰符,并使MyClass的可访问域保持不变,则应选择【 】。
namespace test
{ class MyClass
{ int i; }
}
A) private B) public C) protected D) internal
29.C#中MyClass为一个自定义类,其中有以下方法定义:
public void Hello() { …… }
并使用以下语句创建了该类的对象obj,则可以访问类MyClass的Hello方法的语句是【 】。
MyClass obj=new MyClass()
A) obj.Hello() B) obj:Hello() C) MyClass.Hello D) MyClass:Hello
30.下列的关键字中可用于引用类的当前实例的是【 】。
A) base B) this C) new D) override
31.在C#中,以下有关索引器的参数个数的说法中正确的是【 】。
A) 索引器只能有一个参数 B) 索引器可以有多个参数
C) 索引器可以没有参数 D) 索引器至少要有两个参数
32.委托声明的关键字是【 】。
A) delegate B) sealed C) operator D) event
33.以下语句的作用是【 】。
public delegate void Hello(string s);
A) 声明了一个名称为Hello的全局方法 B) 声明了一个名称为Hello的函数原型
C) 声明了一个名称为Hello的函数指针 D) 声明了一个名称为Hello的委托类型
34.有声明语句:delegate void TimeDelegate(string s),则以下可以和委托TimeDelegate绑定的方法是【 】。
A) void f(){ } B) string f(){ }
C) void f(string a){ } D) string f(string a){ }
35.声明一个委托类型:public delegate int myCallBack(int x); 则以下可以和委托myCallBack绑定的方法是【 】
A) void myCallBack(int x); B) int receive(int num);
C) string receive(int x); D) 不确定的
36.有以下部分C#代码,其中MyDelegate是一个【 】。
static void fun(string s) { Console.WriteLine(s); }
public static void Main()
{ MyDelegate p=new MyDelegate(fun);
p("Hello!");
}
A) 结构类型; B) 委托类型 C) 函数 D) 类名
37.对于下面声明的委托和定义的类:
delegate int Mydelegate(int n);
class A
{ public int f(int i) { return 0; }
public void g(int j) { }
public static int h(int k) { return 0; }
}
下面语句中哪些是正确的【 】。
Mydelegate d1=new Mydelegate(A.h); //语句1
A a=new A();
Mydelegate d2=new Mydelegate(a.f); //语句2
Mydelegate d3=new Mydelegate(a.g); //语句3
Mydelegate d4=new Mydelegate(a.h); //语句4
A) 语句1、语句2、语句3、语句4 B) 语句1、语句2
C) 语句3、语句4 D) 语句2、语句3
38.以下用于定义事件的关键字是【 】。
A) delegate B) event C) this D) value
39.将发生的事件通知其他对象(订阅者)的对象称为事件的【 】。
A) 广播者 B) 发行者 C) 通知者 D) 订阅者
40.已知类MyClass中事件MouseClicked定义如下:
public delegate void mydelegate();
public event mydelegate MouseClicked();
执行下列语句:
Method obj=new Method();
MyClass e=new MyClass();
e. MouseClicked +=obj.fun;
e. MouseClicked +=obj.fun;
其中Method类中包含事件处理方法fun,然后引发该MouseClicked 事件,其结果为【 】。
A) obj.fun方法被调用一次 B) obj.fun方法被调用二次
C) obj.fun方法不会被调用 D) obj.fun方法被调用四次
二.填空题
1.【 类 】是面向对象编程的基础模块,在C#中,所有的内容都被封装在其中。
2.声明类之后,通过new创建【 类对象 】,它是一个引用类型的变量。
3.静态字段是用【 static 】修饰符声明的字段,无论存在多少个类实例,它们都共享一个字段副本。
4.定义方法时使用的参数是【形参】,调用方法时使用的参数是【 实参 】。
5.数据类型说明符用来说明方法返回值的类型,如果没有返回值,则类型说明符应为【 void 】。
6.下列方法的作用是求两个数的较大数,并把较大数作为返回值,请填空。
float max_v(【 (1)】)
{ float max;
max=a;
if(max<b) max=b;
【(2)】;
}
(1) int a, int b (2) return(max)
7.在调用方法时,要使参数按引用方式进行传递,需要使用关键字【 ref 】。
8. 在调用方法时,要使参数按输出方式进行传递,需要使用关键字【 out 】,此时并不要求实参变量已经初始化。
9.在类的成员声明时,若使用了【protected】修饰符,则该成员只能在该类或其派生类中进行访问。
10.类的静态成员属于【 类 】所有,非静态成员属于类的实例所有。
11.已知某类的类名为ClassA,则该类的析构函数名为【~ClassA 】。
12.C#方法的参数有四种,分别是:值参数(对应值传递)、引用参数(对应地址传递)、输出参数和参数数组,在形参中声明参数数组时应使用【params】关键字。
13.要给属性对应的数据成员赋值,通常要使用set访问器,set访问器始终使用【 value】来设置属性的值。
14.声明一个公有委托类型MyFun1,该委托类型可以与无参且返回值为int类型的方法相关联,则该声明语句应为【 public delegate int MyFun1(); 】。
15.下列程序的输出结果是【 30 】。
class Program
{ static void sub(int x, int y, int z)
{ z=x*x+y*y; }
public static void Main(string[] args)
{ int a=30;
sub(5, 2, a);
Console.WriteLine("{0}",a);
}
}
16.下列程序的运行结果是【3,5 】。
class program
{ static void Func(int a, out int x,out int y)
{ x=a/10; y=a%10; }
static void Main()
{ int m=35; int a, b;
Func(m, out a,out b);
Console.WriteLine("{0},{1}",a,b);
}
}
17.下列程序的运行结果是【 18 】。
class A
{ private int x;
public static A operator -(A b, A c)
{ A a=new A();
a.x=b.x * c.x;
return a;
}
public void setx(int x) { this.x=x; }
public int getx(){ return x; }
}
class Program
{ static void Main()
{ A a=new A(); a.setx(3);
A b=new A(); b.setx(6);
A c = a - b;
Console .WriteLine ("{0}",c.getx());
}
}
18. 下列程序的运行结果是【中国地质大学 】。
public class University
{ const int MAX = 10;
private string[] name = new string[MAX];
public string this[ int index ]
{ get
{ if (index >= 0 && index < MAX) return name[index];
else return name[0];
}
set
{ if (index >= 0 && index < MAX) name[index] = value; }
}
}
class Program
{ static void Main()
{ University un=new University();
un[0] = "清华大学";
un[1] = "北京大学";
un[2] = "中国地质大学";
Console.WriteLine(un[2]);
}
}
三.改错题
(说明:下列程序中部分下划线的代码有错误,请将有错误的部分改正过来,并说明原因)
1. class A
{ A(){ } }
A a=new A();
答:“A(){ }”应改为“public A(){ }”。因为在默认修饰符的情况下,类中的成员被默认为私有成员,因此在用A创建a时试图调用此构造函数,会因此构造函数为私有成员而拒绝访问。
2. class A
{ public static int x=100;
public int y=200;
}
class Program
{ static void Main(string[] args)
{ A a=new A();
a.x=10;
a.y=20;
}
}
答:“a.x=10;”应改为“A.x=10;”。因为x是类A中的静态成员。
3. class A
{ A(){ }
void A(){ }
private A(int x){ }
private A(int y){ }
}
答:“void A(){ }”应改为“A(){}”,因为构造函数不能带任何返回类型修饰符。“private A(int x){ }”和“private A(int y){ }”实际上是同一个构造函数,应删除其中一个。
4. class A
{ int f(){ return 1; }
void f(){ }
void g(int x){ }
void g(int y){ }
}
答:类A中试图重载函数f()和函数g(),但函数的重载是通过定义不同的参数个数和类型来实现的,其返回类型不能说明函数的重载特性,因此应删除其中的一个f()函数;类似的原因,函数g()中的形参名不同也不能说明函数的重载特性,实际上这两个g()函数是一样的,因此也需去掉其中之一。
四.问答题
1.简述类和对象的关系。
2.简述面向对象的基本特征。
3.类的声明格式中包含哪些部分?各有什么意义?
4.什么是实例方法?什么是静态方法?
5.类可以使用哪些修饰符?各代表什么含义?
6.简述构造函数和析构函数的作用。
7.什么是属性?
答:属性是C#中的一种语法结构。如下:
private int _年龄;
public int年龄
{ set { if (value > 0){ _年龄= value;} }
get{ return _年龄; }
}
8.为什么使用属性?
答:属性是实现封装的一种方式,起到保护类成员变量的作用。调用简洁方便。而且,通过属性可以访问私有成员变量。
9.属性的类型有什么?
答:属性类型有:读写属性,只读属性,只写属性。
11.什么是索引器?
答:索引器是C#中的一种语法结构。如下:
[访问修饰符] 数据类型this[数据类型 标识符]
{ get{}; //get访问器
set{}; //set访问器
}
12. 索引器的作用是什么?
答:作用:索引器是实现封装的一种方式,起到保护类成员的作用;同时使用起来简单方便:为集合对象创建索引器后,可以对类对象指定索引来直接访问数组元素即用索引数组的方式索引对象。
13. 索引器可以重载吗?可以为索引器指定几个索引器参数?
答:索引器可以重载。可以为索引器至少指定一个索引器参数。
14.什么时候使用属性,什么时候使用索引器?
答:类中有成员变量就应该有属性。当成员变量是集合类型的时候,可以创建索引器。
五.程序阅读题
1.阅读下列程序,写出程序的输出结果。 考察类对象
public class TPoint
{ int x, y;
public void setpoint(int x1,int y1)
{ x = x1; y = y1; }
public void dispoint()
{ Console.WriteLine("点:({0},{1})", x, y); }
}
class Program
{ static void Main(string[] args)
{ TPoint p1, p2;
p1= new TPoint(); p1.setpoint(2, 6);
p2 = p1; p2.setpoint(8, 3);
p1.dispoint(); p2.dispoint();
}
}
点:(8,3)
点:(8,3)
2.阅读下列程序,写出程序的输出结果。考察方法参数传递
class Program
{ static void f1(ref int a, ref int b, out int sum, out int sub)
{ int t;
t=a; a=b; b=t;
sum = a + b; sub = a - b;
}
public static void Main(string[] args)
{ int x=10, y=20,xx=30,yy=40;
f1(ref x, ref y, out xx, out yy);
Console.WriteLine("x={0},y={1},xx={2},yy={3}", x,y,xx, yy);
}
}
x=20,y=10,xx=30,yy=10
3.阅读下列程序,写出程序的输出结果。考察索引器
public class Weeks
{ string[] week= { "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" };
public string this[int i]
{ get
{ if (i >= 0 && i< 7) return week[i];
else return week[0];
}
set
{ if (i >= 0 && i< 7) week[i] = value;
}
}
}
class Program
{ static void Main()
{ Weeks w = new Weeks();
w[0] = "星期天"; w[1] = "星期一";
Console.WriteLine(w[2]); Console.WriteLine(w[7]);
}
}
Tues
星期天
4.阅读下列程序,写出程序的输出结果。考察委托使用
delegate void mydelegate(double x, double y);
class MyDeClass
{ public void add(double x, double y)
{ Console.WriteLine("{0}+{1}={2}", x, y, x + y ); }
public void sub(double x, double y)
{ Console.WriteLine("{0}-{1}={2}", x, y, x - y); }
}
class Program
{ static void Main(string[] args)
{ MyDeClass obj = new MyDeClass();
mydelegate p;
p = obj.add;
p += obj.sub;
p(10, 20);
}
}
10+20=30
10-20=-10
5.阅读下列程序,写出程序的输出结果。考察委托使用
public delegate int mydelegate(int x, int y);
class Math
{ public int fun1(int x, int y)
{ return x * x + y * y; }
public int fun2(int x, int y)
{ return x * x - y * y; }
}
class Program
{ static void Main(string[] args)
{ int result;
mydelegate objCall;
Math objMath = new Math();
objCall = objMath.fun1;
result = objCall(5, 3);
Console.WriteLine("结果为{0}", result);
objCall = objMath.fun2;
result = objCall(5, 3);
Console.WriteLine("结果为{0}", result);
Console.Read();
}
}
结果为34
结果为16
5. 阅读下列程序,写出程序的输出结果。考察事件
public delegate void mydelegate1(int i);
class MyEvent
{ public event mydelegate1 Event1;
public void FireEvent1(int i)
{ if (Event1 != null) Event1(i); }
}
public class Program
{ public static void show(int i)
{ Console.Write("{0} ", i); }
public static void Main()
{ MyEvent a = new MyEvent();
a.Event1 += new mydelegate1(show);
for (int i = 0; i <= 30; i++)
if (i % 7 == 0) a.FireEvent1(i);
}
}
0 7 14 21 28
6. 阅读下列程序,写出程序的输出结果。考察运算符重载
class Complex
{ double a, b;
public Complex(double m, double n)
{ a=m; b=n; }
public static Complex operator +(Complex x,Complex y)
{ Complex t=new Complex(0,0);
t.a=x.a+y.a; t.b=x.b+y.b;
return(t);
}
public void DispCom()
{ if (b>0 ) Console.WriteLine("{0}+{1}i",a,b);
else Console.WriteLine("{0}-{1}i",a,-b);
}
}
class Program
{ public static void Main(string[] args)
{ Complex x=new Complex(1,2); Complex y=new Complex(3,4);
Complex z=new Complex(0,0);
z=x+y;
x.DispCom();
y.DispCom();
z.DispCom();
}
}
1+2i
3+4i
4+6i
六.编程题
1.创建一个Student类,要求:
- 该类封装学生的姓名、性别和成绩等信息。
- 通过构造函数给姓名和性别信息赋值。
- 姓名和性别信息只能读不能写,成绩信息通过属性进行读写,对成绩属性进行赋值时,若成绩大于100分赋100分,若成绩低于0分赋0分。
- 具有一个判断成绩等级的方法
class Student
{ private string name;
private string sex;
private int cj;
public Student(string name, string sex)
{ this.name = name; this.sex = sex; }
public string Name
{ get { return name; } }
public string Sex
{ get { return sex; } }
public int Score
{ get { return cj; }
set { if (value > 100) cj = 100;
else if (value < 0) cj = 0;
else cj = value;
}
}
public string grade(int a)
{ string dj;
if (a >= 90) dj = "优秀";
else if (a >= 80) dj = "良好";
else if (a >= 70) dj = "中等";
else if (a >= 60) dj = "及格";
else dj = "不及格";
return dj;
}
}
2.声明一个用于检查用户合法性及用户级别的类CheckUser,具体要求如下:
- 该类包含UserName(用户名)和UsePwd(密码)两个string类型的属性。
- 包含一个带有两个string类型参数的构造函数。
- 包含一个返回值为int类型的UserLevel()方法,返回值为0表示高级用户,为1表示普通用户,为2表示用户不存在。若用户名为“zhangsan”,密码为”123456”,则为高级用户。若用户名为“lisi”,密码为”654321”,则为普通用户。所有其他用户均为不合法用户。
class CheckUser
{ private string name;
private string pwd;
public string UserName
{ get { return name; }
set { name = value; }
}
private string UserPwd
{ get { return pwd; }
set { pwd = value; }
}
public CheckUser(string name, string pwd)
{ this.name = name; this.pwd = pwd; }
public int UserLevel()
{ int level = 2;
if (UserName == "zhangsan" && UserPwd == "123456") level = 0;
if (UserName == "lisi" && UserPwd == "654321") level = 1;
return level;
}
}
3.设计实现一个商品销售的简单管理程序。具体要求如下:
- 每一种商品对象要存储的是商品名称、库存量及商品的单价。
- 每销售一件商品要计算销售总额和商品库存量。
class Goods
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
private int count; //商品库存量
private double price; //商品价格
static private double sum = 0; //所有商品的销售额
public Goods(string name, int count, double price)
{ this.name = name; this.count = count; this.price = price; }
public void makesale(int num)
{
this.count = this.count - num; //修改商品库存量
sum = sum + this.price * num; //修改所有商品的销售总额
}
public int Count
{ get { return count; } }
public static double Sum
{ get { return sum; } }
}
class Program
{
static void Main(string[] args)
{
Goods Candy = new Goods("糖果", 200, 2);
Goods Chips = new Goods("薯片", 500, 5);
Candy.makesale(50); Chips.makesale(10);
Console.WriteLine("{0}的库存={1}", Candy.Name, Candy.Count);
Console.WriteLine("{0}的库存={1}", Chips.Name,Chips.Count);
Console.WriteLine("Sum={0}", Goods.Sum);
Console.Read();
}
}
4.声明一个名为MyCar的类,具体要求如下:
- MyCar类可以被任何类访问
- 该类包含有两个属性:string类型的CarType和double类型的CarPrice
- 该类具有两个重载构造函数:一个无参数,一个包含两个参数(对应CarType和CarPrice属性)。使用无参数构造函数初始化MyCar类对象时,CarType属性值默认为“SUV”,CarPrice属性值默认为24.5。
5.编写一个名为CTimer1的类,该类能够存放时间信息(设定三个域分别用来存放时分秒信息),并且具有设置时间和显示时间的功能(设置和显示时间可定义成类的方法)。
6.创建一个名为Person的类,具体要求如下:
- 含有静态字段total(存放学生总数),实例字段ID(学号)、name(姓名)、sex(性别)
- 创建构造函数,为新实例设置字段值,并记录实例个数。
- 创建静态方法,显示当前学生总数。
- 创建实例方法,显示学生的学号、姓名和性别。
- 在主函数中调用实例化Person类,并调用静态方法和实例方法,要求第一次实例化显示自己的学号和姓名等。
class Person
{ public static int total=0;
public int num;
public string name;
public string sex;
public Person(int n, string a, string s)
{ num = n; name = a; sex = s; total++; }
public static void displayNum()
{ Console .WriteLine ("total:{0}",total ); }
public void DisplayAll()
{ Console.WriteLine("学号:{0}\t姓名:{1}\t性别:{2}", num ,name,sex ); }
}
public class test
{ static void Main()
{ Person myPerson = new Person(1001, "张小为", "女");
Person.displayNum();
myPerson.DisplayAll();
}
}
7.创建一个复数类Complex,可以实现复数的赋值(通过构造函数)、显示(通过实例方法)和加法运算(通过“+”运算符重载)。
class Complex
{ int real, imag;
public Complex(int a, int b)
{ real = a; imag = b; }
public void Display()
{ Console.WriteLine("Complex.real={0},Complex.imag={1}", real, imag); }
public static Complex operator +(Complex p1, Complex p2)
{ Complex p=new Complex(0,0);
p.real = p1.real + p2.real;
p.imag = p1.imag + p2.imag;
return p;
}
}
8.设计一个控制台应用程序,创建一个List类,可以存储整数、实数、字符数据等(最多存放100个元素),并可以添加元素、删除元素、获取指定位置的元素、获取元素的实际个数、获取所有元素等。用相关数据进行测试。
class List
{ private int Max = 100; //存储最多元素
private int num = 0; //存储的实际元素个数
private object[] list; //存储数组元素
public List() //构造函数
{ list = new object[Max]; }
public void add(object obj) //添加一个元素
{ list[num] = obj; num++; }
public void delete(int pos) //删除一个元素
{ for (int i = pos + 1; i < num; i++) list[i - 1] = list[i];
num--;
}
public object get(int pos) //获取指定位置的元素
{ if (pos < num) return list[pos];
else return null;
}
public int getnum() //获取实际元素个数
{ return num; }
public string disp() //获取所有元素
{ string s = "";
for (int i = 0; i < num; i++) s += list[i] + " ";
return s;
}
}
class Program
{ static void Main(string[] args)
{ List list = new List();
list.add("abc");
list.add(1.23);
list.add(2);
list.add('a');
Console.WriteLine("元素序列:{0}", list.disp());
Console.WriteLine("元素个数:{0}", list.getnum());
Console.WriteLine("位置1的元素:{0}", list.get(1));
Console.WriteLine("删除位置2的元素");
list.delete(2);
Console.WriteLine("元素序列:{0}", list.disp());
Console.Read();
}
}
9.设计一个控制台应用程序,编程计算0~100中所有能被7整除的整数。要求:将输出结果的命令置于事件处理程序中,每找到一个符合条件的数,就通过触发事件来执行输出程序。
public delegate void mydelegate1(int i);
class MyEvent //事件源类
{ public event mydelegate1 Event1; //定义事件
public void FireEvent1(int i) //引发事件Event1的方法
{ if (Event1 != null) Event1(i); }
}
public class Program //创建订阅者类
{ public static void show(int i)
{ Console.WriteLine("事件触发,能被7整除的数是:{0}", i); }
public static void Main()
{ MyEvent a = new MyEvent();
//订阅事件,把方法FireEvent1添加到事件Event1的列表中
a.Event1 += new mydelegate1(show);
for(int i=0;i<=100;i++)
if (i % 7 == 0) a.FireEvent1(i); //触发事件
Console.Read();
}
}
10.请设计一个类,用来模拟栈及其操作。
说明:栈是一种重要的数据结构,在内存中占用连续的存储单元。栈有两个端点,固定的栈底和浮动的栈顶。栈有两种基本操作:push(压栈)和pop(出栈)。压栈是向栈顶位置写入一个元素,然后使栈顶指示器加1;出栈是先使栈顶指示器减1,再把该位置的元素读出来。
提示:可用一个数组成员(假设为buffer)表示栈的空间,用一个整型成员(假设为sp)表示栈顶指示器,并在构造函数中分配栈的空间和设置sp的值为0。出栈与压栈均用类的方法来实现,一般设其方法名分别为push和pop。
class Stack
{ private int[] arr; //栈空间
private int sp; //栈顶指示器
private int count; //允许的栈元素的最多个数
public Stack(int Length) //栈的构造函数形式一
{ count = Length; sp = 0; arr = new int[Length]; }
public Stack() //栈的构造函数的另一种形式
{ count = 10; sp = 0; arr = new int[10]; }
public bool isEmptyStack()
{ if (sp == 0) return true;
else return false;
}
public bool isFullStack()
{ if (sp ==count ) return true;
else return false;
}
public void push(int element) //压栈操作
{ arr[sp] = element; sp = sp + 1; }
public int pop() //出栈操作
{ sp = sp - 1; return (arr[sp]); }
public string putstack()
{ int i;
string stack = "";
for (i = 0; i < sp; i++) stack = stack + arr[i].ToString()+ " " ;
return stack;
}
}
11.设计一个控制台应用程序项目a,输入若干个学生的姓名、英语和数学成绩,求出总分,并按总分从高到低排序。要求设计一个学生类Student,所有学生对象存放在一个Student对象数组中,通过一个方法对其按照总分进行降序排序,最出输出排序后的结果,输出结果类似于下图所示。
控制台应用程序项目a的执行结果
public class Student
{ private string name;
private int eng, math, sum;
public int psum
{ get { return sum; } }
public void inscore()
{ Console.Write("姓名:"); name = Console.ReadLine();
Console.Write("英语:"); eng = int.Parse(Console.ReadLine());
Console.Write("数学:"); math = int.Parse(Console.ReadLine());
sum = eng + math;
}
public void display()
{ Console.WriteLine("\t{0}\t{1}\t{2}\t{3}", name, eng, math, sum); }
}
class Program
{ const int Max = 100;
static void sort(int n, params Student[] p) //采用冒泡排序法排序
{ int i, j;
Student tmp;
for (i = 0; i < n - 1; i++)
{ for (j = 0; j < n-i-1; j++)
if (p[j].psum < p[j+1].psum)
{ tmp = p[j + 1]; p[j + 1] = p[j]; p[j] = tmp; }
}
}
static void Main(string[] args)
{ int n, i;
Student[] p = new Student[Max]; //定义对象引用数组
Console.Write("n:");
n = int.Parse(Console.ReadLine());
for (i = 0; i < n; i++) //创建对象引用的实例
p[i] = new Student();
for (i = 0; i < n; i++)
{ Console.WriteLine("输入第{0}个学生数据:", i + 1);
p[i].inscore();
}
Console.WriteLine("排序前:");
Console.WriteLine("\t姓名\t英语\t数学\t总分");
for (i = 0; i < n; i++)
{ Console.Write("序号{0}:", i + 1);
p[i].display();
}
sort(n, p); //按总降序排序
Console.WriteLine("排序后:");
Console.WriteLine("\t姓名\t英语\t数学\t总分");
for (i = 0; i < n; i++)
{ Console.Write("第{0}名:", i + 1);
p[i].display();
}
}
}
说明:可以采用任一种排序方法,也可以采用继承Icomparable接口的方式实现(见第7章习题)。
12. 设计一个控制台应用程序用于模拟考试过程,其中有一个教师类Teacher和一个学生类Student,教师宣布开始考试,学生接收后开始答题,学生答题完毕引发答题完毕事件,教师收卷。
public delegate void EndExamType(DateTime endtime, Student stud);
//声明完成考试委托类型
public delegate void StartExamType(DateTime starttime);
//声明开始考试委托类型
class Student //学生类
{
private string name; //学生姓名
public event EndExamType EndExam; //定义完成考试事件
public Student(string name) //构造函数
{ this.name = name;
}
public string pname //学生姓名属性
{ get { return name; }
}
public void Testing(DateTime begintime) //学生开始考试事件调用的方法
{ Console.WriteLine("学生{0}在{1}时开始答题...", name, begintime);
}
public void HandIn() //学生交卷引发完成考试事件
{
EndExam(DateTime.Now, this);
}
}
class Teacher //教师类
{
public event StartExamType StartExam;
public void NotifyBeginExam()
{
Console.WriteLine("教师宣布开始考试");
StartExam(DateTime.Now); //引发开始考试事件
}
public void Accept(DateTime accepttime, Student stud)
//学生完成考试事件调用的方法
{
Console.WriteLine(" 学生" + stud.pname + "完成考试,老师收卷");
}
}
class Program
{
static void Main(string[] args)
{
Teacher t = new Teacher();
Student[] s = new Student[5];
s[0] = new Student("张军");
s[1] = new Student("陈华");
s[2] = new Student("王丽");
s[3] = new Student("许源");
s[4] = new Student("刘畅");
foreach (Student st in s)
{
t.StartExam += new StartExamType(st.Testing);
//给每个学生订阅教师的开始考试事件
st.EndExam += new EndExamType(t.Accept);
//给教师订阅每个学生的完成答卷事件
}
t.NotifyBeginExam(); //教师宣布开始考试
Console.WriteLine("经过一段时间...");
s[1].HandIn(); //一学生完成答题交卷
Console.WriteLine("经过一段时间...");
s[2].HandIn(); //一学生完成答题交卷
Console.WriteLine("经过一段时间...");
s[4].HandIn(); //一学生完成答题交卷
Console.WriteLine("经过一段时间...");
s[0].HandIn(); //一学生完成答题交卷
Console.WriteLine("经过一段时间...");
s[3].HandIn(); //一学生完成答题交卷
}
}