程序设计基础课程实训报告:银行储蓄系统

基本系统组织在六个文件中:

程序设计基础课程实训报告:银行储蓄系统_第1张图片

header.h

#ifndef BANK_H_INCLUDED
#define BANK_H_INCLUDED

/***********************************************************
* 版权所有 (C)2015, 陈文青。
*
* 文件名称: header.h
* 文件标识:
* 内容摘要:项目的头文件,类的声明:Basic <-- User <-- Bank
                                        ^
                                        |
                                      Clerk
* 其它说明:
* 当前版本: V1.0
* 作    者:陈文青
* 完成日期: 20150715
*
* 修改记录:
* 修改日期: 20150715
* 版本号: V1.0
* 修改人: 陈文青
* 修改内容:
**********************************************************/
#include 
using namespace std;
class Bank;

/*
* 功能描述:基础类:Basic,定义最基本的功能
* 其它说明:成员函数为最单一的常用函数:改密,显示菜单。
            数据成员包括最基础的姓名及密码,以及N(人数)
*/
class Basic
{
public:
    int chooseInMenu();    //显示菜单并由业务员选择
    int inputPassword();   //返回键盘输入的密码
protected:
    char name[20];     //户主姓名
    int password;      //密码
    int N;             //户主数目
};
/*
* 功能描述:继承Basic的Clerk类,用作业务员员登录
*/
class Clerk:public Basic
{
public:
    Clerk();               //开始前从文件中读取业务员信息
    bool clerk_login();    //业务员登录
private:
    string name[20];     //户主姓名
    int password[20];    //密码
    int N;               //业务员人数
};

/*
* 功能描述:继承Basic类的User,用户类,定义单个用户的成员及其函数
*/
class User:public Basic
{
public:
    void setUser(int acc, char* nam, int pw, double bal,char se,char* ID,char* add,char* pn,int sta);  //对象成员的赋值
    void showName();
    void showPhonenumber();
    void showIDcard();
    void showSex();
    void showBalance(string prompt);  //显示余额,前面加上提示词prompt
    bool isNormalUser();              //存款、取款、转帐等功能,需要账户处于正常姿态,处于正常状态时返回true,其他情形返回false并提示
    bool passwordIsRight();           //校验密码,输入的密码正确则返回true
    friend class Bank;                //将Bank声明为友元类,方便其访问数据成员
protected:
    int account;     //账号
    int password;    //密码
    char name[20];   //用户名
    double balance;  //账户余额
    char sex;        //性别
    char IDcard[20]; //身份证号
    char address[20];//地址
    char phonenumber[12]; //绑定电话号码
    int status;      //状态 0-正常  1-挂失  2-销户
};

/*
* 功能描述:继承User类的Bank,银行类,定义银行的操作功能,并将User的对象数组作为数据成员
*/
class Bank:public User     //银行操作功能,继承于用户类
{
public:
    Bank();                 //开始前从文件中读数据,存在数组中
    ~Bank();                //程序结束前,将数组中的数据写入到文件中
    void work();            //业务驱动
    void openAccount();     //开户
    void cancelAccount();   //注销账户
    void save();            //存款
    void withdraw();        //取款
    void showAccount();     //查询余额
    void transferAccounts();//转账
    void reportLoss();      //挂失
    void cancelLoss();      //解除挂失
    void updatePassword();  //更改密码
    int getUser();          //输入账号查询用户,返回用户在对象数组中的下标
private:
    int N;              //实际的用户数目
    User *users;        //User数组,动态数组;
};
#endif // BANK_H_INCLUDED
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED



#endif // HEADER_H_INCLUDED

basic.cpp

/***********************************************************
* 版权所有 (C)2015, 陈文青。
*
* 文件名称: basic.cpp
* 文件标识:
* 内容摘要:Basic类内函数的定义
* 其它说明:
* 当前版本: V1.0
* 作    者:陈文青
* 完成日期: 20150715
*
* 修改记录:
* 修改日期: 20150715
* 版本号: V1.0
* 修改人: 陈文青
* 修改内容:
**********************************************************/
#include 
#include 
#include 
#include 
#include 
#include "header.h"
using namespace std;

/*

关于getch():
所在头文件:conio.h
函数用途:从控制台读取一个字符,但不显示在屏幕上
返回值:读取的字符
在不同平台,输入回车,getch()将返回不同数值,而getchar()统一返回10(即\n)
1)windows平台下ENTER键会产生两个转义字符 \r\n,因此getch返回13(\r)。
2)unix、 linux系统中ENTER键只产生 \n ,因此getch返回10(\n)。
3)MAC OS中ENTER键将产生 \r ,因此getch返回13(\r)。
由于令输入ENTER键的时候不产生输入字符,不输出*,所以不能用getchar(),并且不能把条件设为  (ch=getch())!='\n'
所以使用 ch=getch())!='\r'


关于fflush(stdin):
函数用途:为避免键盘缓存区中未读出的字符影响程序,用fflush(stdin);清除输入缓存区
所在头文件:stdio.h


关于isdigit(ch):
所在头文件:ctype.h
函数用途:用于判断字符是否为整型
*/

/*
 * 功能描述:显示菜单并由业务员选择
 * 返回值:用户选择的功能,范围0-9
*/
int Basic::chooseInMenu()
{
    int i;
    while(1)
    {
        cout<>i;
        if(i>=0 && i<=9)
            break;
        else
            cout<<"请重新选择功能"<


clerk.cpp

/***********************************************************
* 版权所有 (C)2015, 陈文青。
*
* 文件名称: clerk.cpp
* 文件标识:
* 内容摘要:Clerk类内成员函数的定义
* 其它说明:
* 当前版本: V1.0
* 作    者:陈文青
* 完成日期: 20150715
*
* 修改记录:
* 修改日期: 20150715
* 版本号: V1.0
* 修改人: 陈文青
* 修改内容:
**********************************************************/
#include "header.h"
#include 
#include 
#include 
using namespace std;


/*
* 功能描述:用构造函数读取文件中保存的业务员信息,用于登录
* 其他说明:因为此处无法自己建立二进制文件,所以采用文本存储,而在际应用中,业务员账号和密码是不允许显示的。
*/
Clerk::Clerk()               //开始前从文件中读取业务员信息
{
    ifstream infile("clerk.txt",ios::in);
    if(!infile)              //测试是否成功打开文件
    {
        cerr<<"open error!"<>name[i]>>password[i];   //读取业务员信息……
        ++i;
    }
    N=i;                   //存储业务员人数
    infile.close();
}

/*
* 功能描述:业务员登录
* 返回值:如果登录验证正确,返回right,否则返回false
*/
bool Clerk::clerk_login()   //业务员登录
{
    string sName;         //输入业务员户名
    int iPassword;        //输入管理密码
    int times=3;          //进入系统时只允许三次输入错误
    bool right=false;     //用于判断
    int i;                //用于匹配业务员密码
    //进入系统,密码三次不对将退出
    while(times--)
    {
        cout<<"请输入业务员用户名:";
        cin>>sName;
        for(i=0; i0)
                cout<<"对不起您的用户名或密码输入错误,请重新输入。您还有"<


user.cpp

/***********************************************************
* 版权所有 (C)2015, 陈文青。
*
* 文件名称: main.cpp
* 文件标识:
* 内容摘要:主函数
* 其它说明:
* 当前版本: V1.0
* 作    者:陈文青
* 完成日期: 20150715
*
* 修改记录:
* 修改日期: 20150715
* 版本号: V1.0
* 修改人: 陈文青
* 修改内容:
**********************************************************/
#include 
#include 
#include "header.h"
using namespace std;

/*
* 功能说明:用于对用户对象进行赋值
*/
void User::setUser(int acc, char* nam, int pw, double bal,char se,char* ID,char* add,char* pn,int sta)
{
    account=acc;
    strcpy(name,nam);
    password=pw;
    balance=bal;
    sex=se;
    strcpy(IDcard,ID);
    strcpy(address,add);
    strcpy(phonenumber,pn);
    status=sta;
}
/*
* 功能说明:输出姓名
*/
void User::showName()
{
    cout<<"户主姓名:"<


bank.cpp

/***********************************************************
* 版权所有 (C)2015, 陈文青。
*
* 文件名称: bank.cpp
* 文件标识:
* 内容摘要:Bank类内函数的定义
* 其它说明:
* 当前版本: V1.0
* 作    者:陈文青
* 完成日期: 20150715
*
* 修改记录:
* 修改日期: 20150715
* 版本号: V1.0
* 修改人: 陈文青
* 修改内容:
**********************************************************/
#include 
#include 
#include 
#include "header.h"
using namespace std;

/*
* 功能描述:用构造函数读取文件中保存的业务数据
* 其它说明:关于二进制文件与string类型的一点说明:
            因为string类没有提供二进制文件读写的接口,所以只能将所有存入二进制文件的string的类型全部改为字符型数组
*/
Bank::Bank()
{
    ifstream infile("account.dat",ios::in|ios::binary);
    if(!infile)   //检测文件是否成功打开
    {
        cerr<<"open error!"<>acc>>nam>>pw>>bal>>se>>ID>>add>>pn>>sta)   //当读取成功,建立成员数据
    {
        users[i].setUser(acc,nam,pw,bal,se,ID,add,pn,sta);
        i++;
    }
    */
    infile.close();
}

/*
* 功能描述:用析构函数,在退出系统时,将数据保存到文件中
*/
Bank::~Bank()
{
    ofstream outfile("account.dat",ios::out|ios::binary);
    if(!outfile)    //测试文件打开操作是否成功,不成功则提示后退出。
    {
        cerr<<"open error!"<>nam;
    cout<<"性别(m代表男性,f代表女性):";
    cin>>se;
    cout<<"身份证号:";
    cin>>ID;    //身份证号
    cout<<"家庭住址:";
    cin>>add;   //地址
    cout<<"联系方式:";
    cin>>pn;    //电话号码
    int iPass1, iPass2;      //两次输入的密码
    cout<<"密码:";
    iPass1=inputPassword();  //输入密码1
    cout<<"确认密码:";
    iPass2=inputPassword();  //输入密码2
    if(iPass1==iPass2)
    {
        pw=iPass1;
        sta=0; //账户状态为“正常”
        cout<<"存入金额:";
        cin>>bal;
        //将数组长度增加一个单位
        users=(User *)realloc(users,(N+2)*sizeof(User));  //增加一个对象的数组长度,以防止数据溢出
        users[N].setUser(acc, nam, pw, bal, se, ID, add, pn, sta);
        N++; //正式用户数增加1,确认了新用户已经加入
        cout<<"您已成功开户!"<=0)        //说明id账户存在
    {
        users[who].showName();
        if(users[who].passwordIsRight())
        {
            users[who].showBalance("余额");   //提示"余额"二字,显示金额
            cout<<"确认销户(y/n)?";
            if(tolower(getchar())=='y')
            {
                cout<<"请输入您所绑定的手机号,确认销户信息:";  //手机验证,确认销户信息,实际运用中会收到验证码
                cin>>PN;
                if(PN==users[who].phonenumber)
                {
                    users[who].showBalance("您已销户成功!本次取款金额为");
                    users[who].balance=0;  //取款后余额变0
                    users[who].status=2;   //状态变为注销
                }
                else
                    cout<<"对不起,您所输入的手机号码不是您的账户所绑定的手机号码,销户失败。";
            }
            else
            {
                cout<<"您取消了操作,销户失败!"<=0)        //说明id账户存在
    {
        if(users[who].status==0)
        {
            users[who].showName();
            cout<<"请输入存款金额:";
            cin>>money;
            users[who].balance+=money;
            users[who].showBalance("存款后,您所剩的账户余额为:");
        }
        else if(users[who].status==1)
        {
            cout<<"该用户处于挂失状态,存款失败!"<=0)        //说明id账户存在
    {
        if(users[who].isNormalUser())
        {
            users[who].showName();
            if(users[who].passwordIsRight())
            {
                cout<<"请输入取款金额:";
                cin>>money;
                if(money>users[who].balance)  //余额要大于取款金额
                {
                    cout<<"对不起,您的余额不足,取款失败!"<=0)        //说明id账户存在
    {
        users[who].showName();
        if(users[who].passwordIsRight())
        {
            users[who].showName();
            users[who].showSex();
            users[who].showPhonenumber();
            users[who].showIDcard();
            users[who].showBalance("账户余额:");
            cout<<"状态:"<=0)        //说明id账户存在
    {
        if(users[whoout].isNormalUser())         //转出账户处于正常状态
        {
            users[whoout].showName();
            if(users[whoout].passwordIsRight())  //输入密码正确
            {
                cout<<"输入转账金额:";
                cin>>money;
                if(money>users[whoout].balance)  //转出金额足够
                {
                    cout<<"对不起,您的余额不足,转账失败!"<=0)        //说明id账户存在
                    {
                        users[whoin].showName();          //显示转入帐户的姓名
                        if(users[whoin].isNormalUser())   //转入帐号正常
                        {
                            users[whoout].balance-=money; //金额计算
                            users[whoin].balance+=money;
                            users[whoout].showBalance("转账成功,您的账户所剩余额为:");
                        }
                    }
                }
            }
        }
    }
    return;
}
/*
 * 功能描述:挂失账户
*/
void Bank::reportLoss()
{
    int who;
    string PN;       //确认手机号
    who = getUser();   //根据账号查询用户,返回用户的下标
    if(who>=0)         //说明id账户存在
    {
        users[who].showName();
        if(users[who].passwordIsRight())
        {
            if(users[who].status==0)
            {
                cout<<"请输入您所绑定的手机号,确认挂失信息:"; //手机验证,确认挂失信息,实际运用中会收到验证码
                cin>>PN;
                if(PN==users[who].phonenumber)
                {
                    users[who].status=1;
                    cout<<"您已挂失成功。"<=0)        //说明id账户存在
    {
        users[who].showName();
        if(users[who].passwordIsRight())
        {
            if(users[who].status==0)
            {
                cout<<"该账户处于正常状态,不需要解除挂失。"<>pn;
                if(users[who].phonenumber==pn)
                {

                    cout<<"请输入您的的身份证号码:";
                    cin>>ID;
                    if(users[who].IDcard==ID)
                    {
                        users[who].status=0;
                        cout<<"解除挂失成功。"<=0)        //说明id账户存在
    {
        users[who].showName();
        if(users[who].passwordIsRight())
        {
            cout<<"请输入新密码:";
            iPass1=inputPassword();  //输入密码1
            cout<<"确认密码:";
            iPass2=inputPassword();  //输入密码2
            if(iPass1==iPass2)
            {
                users[who].password=iPass1;
                cout<<"修改成功!"<>id;
    int index=-1;
    int low=0, high=N-1, mid;
    while(low<=high)
    {
        mid = (low+high)/2;
        if(users[mid].account==id)
        {
            index=mid;
            break;    //找到了,立即退出循环
        }
        else if (users[mid].account>id)
            high=mid-1;
        else
            low=mid+1;
    }
    if (index<0)
        cout<<"该用户不存在,操作失败!"<


main.cpp

/***********************************************************
* 版权所有 (C)2015, 陈文青。
*
* 文件名称: main.cpp
* 文件标识:
* 内容摘要:主函数
* 其它说明:
* 当前版本: V1.0
* 作    者:陈文青
* 完成日期: 20150715
*
* 修改记录:
* 修改日期: 20150715
* 版本号: V1.0
* 修改人: 陈文青
* 修改内容:
**********************************************************/
#include 
#include "header.h"
using namespace std;
/*主函数:*/
int main()
{
    cout<<"+----------------------+\n";
    cout<<"+   欢迎光临CSDN银行   +\n";
    cout<<"+----------------------+\n";
    Clerk c;    //读入业务员信息,进行业务员登陆。

    if (c.clerk_login())
    {
        Bank b;
        b.work();
    }
    return 0;
}

涉及文件:

将clerk的数据明文存储在记事本里。在登录系统的时候,这里所有的帐号都可以进入系统。最多可存储20个clerk,同时进行操作。

clerk.txt

程序设计基础课程实训报告:银行储蓄系统_第2张图片

二进制文件:用于保存用户信息

account.dat

程序设计基础课程实训报告:银行储蓄系统_第3张图片

运行结果:

业务员登录+开户

程序设计基础课程实训报告:银行储蓄系统_第4张图片

销户+存款

程序设计基础课程实训报告:银行储蓄系统_第5张图片

取款+查询

程序设计基础课程实训报告:银行储蓄系统_第6张图片

转账

程序设计基础课程实训报告:银行储蓄系统_第7张图片

挂失+解挂

程序设计基础课程实训报告:银行储蓄系统_第8张图片

改密+退出

程序设计基础课程实训报告:银行储蓄系统_第9张图片

知识点总结:

这个项目是我在老师给的代码的基础上,改进而来的,其中改进的地方有:

1,使用动态数组。2,使用继承机制。3,使用二进制文件。4,按接近实际业务的要求,处理业务实体中较完善的信息,并在相关业务中使用。


一开始拿到这个程序的时候,我想通过自己的努力,把每一行代码敲出来。但是每写出来一个小小的函数,都会出来数不尽的错误。把错误改出来加进项目的时候,又会出现各种各样的矛盾和各种看不见的bug。到了最后真的到了寸步难行的地步,60分我感觉自己都拿不到了,所以最后还是认输了,去看了老师的架构。这原因还是归咎于我对这个项目的整体把握不到位。

老师毕竟是老师,经验是相当重要的东西。在老师的代码中,我学到了很多自己平时完全考虑不到的东西,包括架构,细节考虑,还有一些相当方便的函数。

在老师给的架构基础上,我还是花了相当多的时间来完成这个程序。


每每遇到bug的时候,只要保持一份淡定的心态,利用单步执行,一步一步去猜测,寻找错误的那个语句,最后慢慢修正这些bug,错误终归还是能解决的。

其中像二进制文件不能存储string类型的数据,realloc函数扩展数组容量这种知识点,都是通过自己百度,自学改进而来的。真正当自己的程序跑出来的时候,真的相当的开心,激动。


总之,这次实训给了我很多的经验和收获,感觉自己的耐心有了特别大的提高!


你可能感兴趣的:(C++,二分查找,文件流,继承,派生,设计)