目录
实验目的:
1.加深理解面向对象编程的概念,如类、对象、实例化等。
2.熟练掌握类的封装、继承和多态机制。
3.掌握变成常用的几种排序算法。
4.理解异常的产生过程和异常处理的概念,掌握C#异常处理的方法。
5.能够将面向对象思想应用于编程实践,开发出规模稍大的应用,如图书管理,银行存取款业务等。
实验内容:
【实验3-1】图书管理应用。
设计一个图书卡片类Card,用来保存图书馆卡片分类记录。这个类的成员包括书名、作者、馆藏数量。至少提供两个方法:
store——书的入库处理;
show——显示图书信息。
程序运行时,可以从控制台上输入需入库图书的总数,根据这个总数创建Card对象数组,然后输入数据,最后可以选择按书名、作者或入库量排序。
A.跟着学习
using System;
using static System.Reflection.Metadata.BlobBuilder;
namespace Test3_1
{
class Card
{
private string title, author;
private int total;
public Card()
{
title = ""; author = "";
total = 0;
}
public Card(string title, string author, int total)
{
this.title = title;
this.author = author;
this.total = total;
}
public void store(ref Card card)
{
title = card.title;
author = card.author;
total = card.total;
}
public void show()
{
Console.WriteLine("Title: {0}, Author: {1}, Total: {2} ", title, author, total);
}
public string Title
{
get { return title; }
set { title = value; }
}
public string Author
{
get { return author; }
set { author = value; }
}
public int Total
{
get { return total; }
set { total = value; }
}
}
class test3_1
{
static void Main(string[] args)
{
test3_1 T = new test3_1();
Card[] books;
int[] index;
int i, k;
Card card = new Card();
Console.Write("请输入需要入库图书的总数:");
string sline = Console.ReadLine();
int num = int.Parse(sline);
books = new Card[num];
for (i = 0; i < num; i++)
books[i] = new Card();
index = new int[num];
for (i = 0; i < num; i++)
{
Console.Write("请输入书名: ");
card.Title = Console.ReadLine();
Console.Write("请输入作者: ");
card.Author = Console.ReadLine();
Console.Write("请输入入库量: ");
sline = Console.ReadLine();
card.Total = int.Parse(sline);
books[i].store(ref card);
index[i] = i;
}
Console.Write("请选择按什么关键字排序(1.按书名,2.按作者,3.按入库量)");
sline = Console.ReadLine();
int choice = int.Parse(sline);
switch (choice)
{
case 1:
T.sortTitle(books, index);
break;
case 2:
T.sortAuthor(books, index);
break;
case 3:
T.sortTital(books, index);
break;
}
for (i = 0; i < num; i++)
{
k = index[i];
(books[k]).show();
}
Console.Read();
}
void sortTital(Card[] books, int[] index)
{
int i, j, m, n, temp;
for (m = 0; m < index.Length - 1; m++)
for (n = 0; n < index.Length - m - 1; n++)
{
i = index[n]; j = index[n + 1];
if (books[i].Total > books[j].Total)
{
temp = index[n];
index[n] = index[n + 1];
index[n + 1] = temp;
}
}
}
void sortAuthor(Card[] books, int[] index)
{
int i, j, m, n, temp;
for (m = 0; m < index.Length - 1; m++)
for (n = 0; n < index.Length - m - 1; n++)
{
i = index[n]; j = index[n + 1];
if (string.Compare(books[i].Author, books[j].Author) > 0)
{
temp = index[n]; index[n] = index[n + 1]; index[n + 1] = temp;
}
}
}
void sortTitle(Card[] books, int[] index)
{
int i, j, m, n, temp;
for (m = 0; m < index.Length - 1; m++)
for (n = 0; n < index.Length - m - 1; n++)
{
i = index[n];
j = index[n + 1];
if (string.Compare(books[i].Title, books[j].Title) > 0)
{
temp = index[n];
index[n] = index[n + 1];
index[n + 1] = temp;
}
}
}
}
}
B.自己思考
将上述程序中class Test3_1中的三个方法:
Void sortTitle(Card[] book,int[] index)
Void sortAuthor(Card[] book,int[] index)
Void sortTotal(Card[] book,int[] index)
改写成一个方法sort(Card[] book,int[] index,int method),其中增加的参数method指示按什么字段排序。
重新修改、编译和运行程序,观察运行结果。
using System;
using static System.Reflection.Metadata.BlobBuilder;
namespace Chapter3_1_1
{
class Card
{
private string title, author;
private int total;
public Card()
{
title = ""; author = "";
total = 0;
}
public Card(string title, string author, int total)
{
this.title = title;
this.author = author;
this.total = total;
}
public void store(ref Card card)
{
title = card.title;
author = card.author;
total = card.total;
}
public void show()
{
Console.WriteLine("Title: {0}, Author: {1}, Total: {2} ", title, author, total);
}
public string Title
{
get { return title; }
set { title = value; }
}
public string Author
{
get { return author; }
set { author = value; }
}
public int Total
{
get { return total; }
set { total = value; }
}
}
class test3_1
{
static void Main(string[] args)
{
test3_1 T = new test3_1();
Card[] books;
int[] index;
int i, k;
Card card = new Card();
Console.Write("请输入需要入库图书的总数:");
string sline = Console.ReadLine();
int num = int.Parse(sline);
books = new Card[num];
for (i = 0; i < num; i++)
books[i] = new Card();
index = new int[num];
for (i = 0; i < num; i++)
{
Console.Write("请输入书名: ");
card.Title = Console.ReadLine();
Console.Write("请输入作者: ");
card.Author = Console.ReadLine();
Console.Write("请输入入库量: ");
sline = Console.ReadLine();
card.Total = int.Parse(sline);
books[i].store(ref card);
index[i] = i;
}
Console.Write("请选择按什么关键字排序(1.按书名,2.按作者,3.按入库量)");
sline = Console.ReadLine();
int method = int.Parse(sline);
T.sort(books,index,method);
for (i = 0; i < num; i++)
{
k = index[i];
(books[k]).show();
}
Console.Read();
}
void sort(Card[] book, int[] index,int method)
{
if (method == 1)//method为1则是按照书名排序
{
int i, j, m, n, temp;
for (m = 0; m < index.Length - 1; m++)
for (n = 0; n < index.Length - m - 1; n++)
{
i = index[n];
j = index[n + 1];
if (string.Compare(book[i].Title, book[j].Title) > 0)
{
temp = index[n];
index[n] = index[n + 1];
index[n + 1] = temp;
}
}
}
else if (method == 2)//method为2 则是按照作者排序
{
int i, j, m, n, temp;
for (m = 0; m < index.Length - 1; m++)
for (n = 0; n < index.Length - m - 1; n++)
{
i = index[n]; j = index[n + 1];
if (string.Compare(book[i].Author, book[j].Author) > 0)
{
temp = index[n]; index[n] = index[n + 1]; index[n + 1] = temp;
}
}
}
else//按照入库量排序
{
int i, j, m, n, temp;
for (m = 0; m < index.Length - 1; m++)
for (n = 0; n < index.Length - m - 1; n++)
{
i = index[n]; j = index[n + 1];
if (book[i].Total > book[j].Total)
{
temp = index[n];
index[n] = index[n + 1];
index[n + 1] = temp;
}
}
}
}
}
}
【实验3-2】银行卡存取款业务。
假设某银行共发出M张储蓄卡,每张储蓄卡拥有唯一的卡号,每天每张储蓄卡至多支持拥有者的N笔“存款”或“取款”业务。根据实际发生的业务,实时处理数据,以反映最新情况。
设储蓄卡包含的数据域有:卡号,当前余额,允许当日发生的业务次数(定义成静态变量,为所有Card类所共享),当日实际发生的业务书,以及一个数组记录发生的具体业务。它提供得到主要方法有store(),处理判断是否超过当日允许发生的最大笔数,当前余额是否足以取款,以及实时修改当前数据等。
当持卡者输入正确得卡号、存款或取款金额后,程序进行相应的处理;若输入了不正确的数据,程序会提示持卡者重新输入;若输入的卡号为负数,银行终止当日业务。
A.跟着学习
using System;
namespace Chapter3_2
{
class Card
{
long cardNo; //卡号
decimal balance; //余额
int currentNum; //当日业务实际发生笔数
static int number; //每张卡允许当日存款或取款的总次数
decimal[] currentMoney; //存放当日存取款金额,正值代表存款,负值代表负数
public Card()
{
currentMoney = new decimal[number];
}
public Card(long No, decimal Balance)
{
cardNo = No;
balance = Balance;
currentMoney = new decimal[number];
}
public void store(decimal Money, out int status)
{
if (currentNum == number) //本卡已达当日允许的业务次数
{
status = 0;
return;
}
if (balance + Money < 0)
{
status = -1; //存款余额不足,不能完成本次的取款业务
return;
}
currentMoney[currentNum] = Money; //记录当日存取款金额
balance += Money; //更新当前余额
currentNum++; //当日业务次数加1
status = 1; //成功处理完当前业务
}
public void show()
{
Console.WriteLine("卡号:{0},当前余额:{1},当日发生业务的次数:{2}", cardNo, balance, currentNum);
for (int i = 0; i < currentNum; i++)
{
Console.WriteLine("当日存款/取款的情况:{0}", currentMoney[i]);
}
}
static public int Number //设置允许当日存款或取款的总次数
{
set
{
number = value;
}
}
public long CardNo //设置CardNo属性是为了查看卡号
{
get
{
return cardNo;
}
}
}
class Test3_2
{
static void Main(string[] args)
{
Test3_2 T = new Test3_2();
Card[] person;
int Num, status, k;
long CardNo;
decimal Balance, Money;
Console.Write("请输入允许当日存款或取款的总次数:");
string sline = Console.ReadLine();
Card.Number = int.Parse(sline);
Console.Write("请输入某银行发出的储蓄卡总数: ");
sline = Console.ReadLine();
Num = int.Parse(sline);
person = new Card[Num];
for(int i=0;i<Num;i++)
{
Console.Write("请输入卡号: ");
sline = Console.ReadLine();
CardNo = long.Parse(sline);
Console.Write("请输入{0}账户余额: ", CardNo);
sline = Console.ReadLine();
Balance = decimal.Parse(sline);
person[i] = new Card(CardNo, Balance);
}
while(true)
{
Console.WriteLine("现在正进行存款取款的业务处理,如果输入的卡号<0,则结束业务处理");
Console.Write("请输入卡号:");
sline = Console.ReadLine();
CardNo = long.Parse(sline);
if (CardNo < 0)
break;
k = T.Locate(person, CardNo);
if(k==-1)
{
Console.WriteLine("对不起,不存在{0}号的储蓄卡", CardNo);
continue;
}
Console.WriteLine("请输入卡金额(正值代表存款,负值代表取款):");
sline = Console.ReadLine();
Money = decimal.Parse(sline);
person[k].store(Money, out status);
switch(status)
{
case -1:
Console.WriteLine("存款余额不足,不能完成本次的取款业务");
break;
case 0:
Console.WriteLine("本卡已达当日允许的业务次数");
break;
case 1:
Console.WriteLine("成功处理完当前业务");
person[k].show();
break;
}
}
}
int Locate(Card[] person,long cardNo)
{
for(int i = 0; i < person.Length;i++)
{
if (person[i].CardNo == cardNo)
return i;
}
return -1;
}
}
}
根据上面的程序代码和运行结果,补充Locate()方法的实现,用顺序查找法查找当前银行有没有该卡号,如果没有,返回-1;否则,返回对象数组的下标。
int Locate(Card[] person,long cardNo)
{
for(int i = 0; i < person.Length;i++)
{
if (person[i].CardNo == cardNo)
return i;
}
return -1;
}
运行截图:
B.自己思考
1.修改Card类,增加每日使用金额额度不超过5000的限制功能。
using Chapter_3_2;
using System;
using static System.Net.Mime.MediaTypeNames;
namespace Chapter_3_2
{
class Card
{
long cardNo;
decimal balance;
int currentNum;
static int number;
decimal[] currentMoney;
public Card()
{
currentMoney = new decimal[number];
}
public Card(long No, decimal Balance)
{
cardNo = No;
balance = Balance;
currentMoney = new decimal[number];
}
public void store(decimal Money, out int status)
{
//当每日使用金额额度超过5000时设置为状态-2
if (Money <= -5000)
{
status = -2;
return;
}
if (Money >= 5000)
{
status = -2;
return;
}
if (currentNum == number)
{
status = 0;
return;
}
if (balance + Money < 0)
{
status = -1;
return;
}
currentMoney[currentNum] = Money;
balance += Money;
currentNum++;
status = 1;
}
public void show()
{
Console.WriteLine("卡号:{0},当前余额:{1},当日发生业务的次数:{2}", cardNo, balance, currentNum);
for (int i = 0; i < currentNum; i++)
{
Console.WriteLine("当日存款/取款的情况: {0}", currentMoney[i]);
}
}
static public int Number
{
set
{ number = value; }
}
public long CardNo
{
get { return cardNo; }
}
}
}
class Test_3_2
{
static void Main(string[] args)
{
Test_3_2 T = new Test_3_2();
Card[] person;
int Num, status, k;
long CardNo;
decimal Balance, Money;
Console.Write("请输入允许当日存款或取款的总次数: ");
string sline = Console.ReadLine();
Card.Number = int.Parse(sline);
Console.Write("请输入某银行发出的储蓄卡总数: ");
sline = Console.ReadLine();
Num = int.Parse(sline);
person = new Card[Num];
for (int i = 0; i < Num; i++)
{
Console.Write("请输入卡号: ");
sline = Console.ReadLine();
CardNo = long.Parse(sline);
Console.Write("请输入{0} 账户余额: ", CardNo);
sline = Console.ReadLine();
Balance = decimal.Parse(sline);
person[i] = new Card(CardNo, Balance);
}
while (true)
{
Console.WriteLine("现在正进行存款取款款的业务处理,如果输入的卡号<0, 则结束业务处理");
Console.Write("请输入卡号: ");
sline = Console.ReadLine();
CardNo = long.Parse(sline);
if (CardNo < 0)
break;
k = T.Locate(person, CardNo);
if (k == -1)
{
Console.WriteLine("对不起,不存在{0}号的储蓄卡", CardNo);
continue;
}
Console.WriteLine("请输入卡金额(正值代表存款,负值代表取款) : ");
sline = Console.ReadLine();
Money = decimal.Parse(sline);
person[k].store(Money, out status);
switch (status)
{
//增加超过金额的分支
case -2:
Console.WriteLine("由于超过5000信用额度,不能完成本次业务");
break;
case -1:
Console.WriteLine("存款余额不足,不能完成本次的取款业务");
break;
case 0:
Console.WriteLine("本卡已达当日允许的业务次数");
break;
case 1:
Console.WriteLine("成功处理完当前业务");
person[k].show();
break;
}
}
}
private int Locate(Card[] person, long cardNo)
{
int i;
for (i = 0; i < person.Length; i++)
if (person[i].CardNo == cardNo)
return i;
return -1;
}
}
运行结果截图:
2.再次修改Card类,要求对银行卡进行操作前必须验证用户密码,并且在输入密码时屏幕 上用“*”显示,为简单起见,初始密码均设为123456.
using Chapter_3_2;
using System;
using static System.Net.Mime.MediaTypeNames;
namespace Chapter_3_2
{
class Card
{
long cardNo;
decimal balance;
int currentNum;
static int number;
decimal[] currentMoney;
public Card()
{
currentMoney = new decimal[number];
}
public Card(long No, decimal Balance)
{
cardNo = No;
balance = Balance;
currentMoney = new decimal[number];
}
public void store(decimal Money, out int status)
{
if (Money <= -5000)
{
status = -2;
return;
}
if (Money >= 5000)
{
status = -2;
return;
}
if (currentNum == number)
{
status = 0;
return;
}
if (balance + Money < 0)
{
status = -1;
return;
}
currentMoney[currentNum] = Money;
balance += Money;
currentNum++;
status = 1;
}
public void show()
{
Console.WriteLine("卡号:{0},当前余额:{1},当日发生业务的次数:{2}", cardNo, balance, currentNum);
for (int i = 0; i < currentNum; i++)
{
Console.WriteLine("当日存款/取款的情况: {0}", currentMoney[i]);
}
}
static public int Number
{
set
{ number = value; }
}
public long CardNo
{
get { return cardNo; }
}
}
}
class Test_3_2
{
static void Main(string[] args)
{
Test_3_2 T = new Test_3_2();
Card[] person;
int Num, status, k;
long CardNo;
decimal Balance, Money;
Console.Write("请输入允许当日存款或取款的总次数: ");
string sline = Console.ReadLine();
Card.Number = int.Parse(sline);
Console.Write("请输入某银行发出的储蓄卡总数: ");
sline = Console.ReadLine();
Num = int.Parse(sline);
person = new Card[Num];
for (int i = 0; i < Num; i++)
{
Console.Write("请输入卡号: ");
sline = Console.ReadLine();
CardNo = long.Parse(sline);
Console.Write("请输入{0} 账户余额: ", CardNo);
sline = Console.ReadLine();
Balance = decimal.Parse(sline);
person[i] = new Card(CardNo, Balance);
}
while (true)
{
Console.WriteLine("现在正进行存款取款款的业务处理,如果输入的卡号<0, 则结束业务处理");
Console.Write("请输入卡号: ");
sline = Console.ReadLine();
CardNo = long.Parse(sline);
if (CardNo < 0)
break;
Console.Write("请输入密码:");
string pwd = "";
char chr = Console.ReadKey().KeyChar;
while (chr != '\r')
{
Console.Write("\b");
if (chr == '\b' && pwd != "")
{
pwd = pwd.Substring(0, pwd.Length - 1);
}
else
{
pwd = pwd + chr.ToString();
Console.Write("*");
}
chr = Console.ReadKey().KeyChar;
}
Console.WriteLine();
if (pwd != "123456")
{
Console.WriteLine("对不起,密码错误");
continue;
}
k = T.Locate(person, CardNo);
if (k == -1)
{
Console.WriteLine("对不起,不存在{0}号的储蓄卡", CardNo);
continue;
}
Console.WriteLine("请输入卡金额(正值代表存款,负值代表取款) : ");
sline = Console.ReadLine();
Money = decimal.Parse(sline);
person[k].store(Money, out status);
switch (status)
{
case -2:
Console.WriteLine("由于超过5000信用额度,不能完成本次业务");
break;
case -1:
Console.WriteLine("存款余额不足,不能完成本次的取款业务");
break;
case 0:
Console.WriteLine("本卡已达当日允许的业务次数");
break;
case 1:
Console.WriteLine("成功处理完当前业务");
person[k].show();
break;
}
}
}
private int Locate(Card[] person, long cardNo)
{
int i;
for (i = 0; i < person.Length; i++)
if (person[i].CardNo == cardNo)
return i;
return -1;
}
}
运行结果截图:
密码正确:
密码错误:
本次实验到这就结束啦!