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

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


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 <string>
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 <iostream>
#include <fstream>
#include <conio.h>
#include <cstdlib>
#include <ctype.h>
#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<<endl;;
        cout<<"+----------------------------+"<<endl;
        cout<<"+ 1 开户    2 销户    3 存款 +"<<endl;
        cout<<"+ 4 取款    5 查询    6 转账 +"<<endl;
        cout<<"+ 7 挂失    8 解挂    9 改密 +"<<endl;
        cout<<"+                     0 退出 +"<<endl;
        cout<<"+----------------------------+"<<endl;
        cout<<"请输入操作指令:";
        cin>>i;
        if(i>=0 && i<=9)
            break;
        else
            cout<<"请重新选择功能"<<endl;;
    }
    return i;
}

/*
* 功能说明:输入密码
* 返回值:整型的密码值
* 技术说明:
(1)此功能在多个模块中都要用到且功能单一,作为基础类中的成员函数
(2)为了便于在输入中只显示*,接受输入时以字符形式输入,而后转为对应的整型数
(3)规定密码由不全为0的6位数字构成
*/
int Basic::inputPassword()
{
    char ch;       //接收字符形式密码
    int iPass=0;   //要转换为数字
    while(1)
    {
        while((ch=getch())!='\r') //getch在接受输入后,不在屏幕上显示
        {
            putchar('*');         //接受任何字符,屏幕上只显示*
            if(isdigit(ch))       //将字符串转化为整型,保存在iPass中
                iPass=iPass*10+(ch-'0');
            else
            {
                iPass=0;
                break;     //退出for循环后,再次接受
            }
        }
        fflush(stdin);     //清除键盘缓存区中已经有的输入
        cout<<endl;
        if(iPass==0)       //此条件成立可能由两种情况引起:输入了非数字字符被直接重置为0,或6位全0后正常退出for循环
        {
            cout<<"密码要求全为数字,且不能全0!"<<endl;;
            cout<<"请重新输入密码: ";
        }
        else
            break;
    }
    return iPass;       //返回密码的整型值
}


clerk.cpp

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


/*
* 功能描述:用构造函数读取文件中保存的业务员信息,用于登录
* 其他说明:因为此处无法自己建立二进制文件,所以采用文本存储,而在际应用中,业务员账号和密码是不允许显示的。
*/
Clerk::Clerk()               //开始前从文件中读取业务员信息
{
    ifstream infile("clerk.txt",ios::in);
    if(!infile)              //测试是否成功打开文件
    {
        cerr<<"open error!"<<endl;
        exit(1);
    }
    int i=0;
    while(!infile.eof())
    {
        infile>>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; i<N; ++i)  //匹配业务员姓名,寻找下标
        {
            if(sName==name[i])
            {
                break;
            }
        }
        cout<<"请输入密码:";
        iPassword=inputPassword(); //输入密码
        if(iPassword==password[i]) //账号密码匹配
        {
            right=true;
            break;
        }
        else
        {
            if(times>0)
                cout<<"对不起您的用户名或密码输入错误,请重新输入。您还有"<<times<<"次机会。"<<endl;
            else
            {
                cout<<"对不起,您的用户名或密码已输入错误3次,您不能进入系统。"<<endl;
            }
        }
    }
    return right;
}


user.cpp

/***********************************************************
* 版权所有 (C)2015, 陈文青。
*
* 文件名称: main.cpp
* 文件标识:
* 内容摘要:主函数
* 其它说明:
* 当前版本: V1.0
* 作    者:陈文青
* 完成日期: 20150715
*
* 修改记录:
* 修改日期: 20150715
* 版本号: V1.0
* 修改人: 陈文青
* 修改内容:
**********************************************************/
#include <iostream>
#include <cstring>
#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<<"户主姓名:"<<name<<endl;
}
/*
* 功能说明:输出手机号码
*/
void User::showPhonenumber()
{
    cout<<"绑定手机号码:"<<phonenumber<<endl;
}
/*
* 功能说明:输出身份证号
*/
void User::showIDcard()
{
    cout<<"身份证号:"<<IDcard<<endl;
}
/*
* 功能说明:输出余额
* 其他说明:在输出的时候要加上前缀prompt,例如:“余额:”
*/
void User::showSex()
{
    cout<<"性别:";
    if(sex=='m')
        cout<<"男"<<endl;
    if(sex=='f')
        cout<<"女"<<endl;
}
void User::showBalance(string prompt)
{
    cout<<prompt<<" "<<balance<<"元"<<endl;
}

/*
* 功能说明:用于验证状态
* 其他说明:存款、取款、转帐等功能,需要账户处于正常状态,处于正常状态时返回true,其他情形返回false并提示
           状态 0-正常  1-挂失  2-销户
*/
bool User::isNormalUser()
{
    bool normal = true;
    if(status!=0)
    {
        normal = false;
        cout<<"该账户处于"<<(status==1?"挂失":"销户")<<"状态,不能继续操作..."<<endl;
    }
    return normal;
}
/*
* 功能说明:用于验证密码
*/
bool User::passwordIsRight()
{
    int iPass;
    bool right = true;
    cout<<"输入密码:";
    iPass=inputPassword();
    if(iPass!=password)
    {
        right = false;
        cout<<"输入密码错误,不能继续操作!"<<endl;
    }
    return right;
}


bank.cpp

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

/*
* 功能描述:用构造函数读取文件中保存的业务数据
* 其它说明:关于二进制文件与string类型的一点说明:
            因为string类没有提供二进制文件读写的接口,所以只能将所有存入二进制文件的string的类型全部改为字符型数组
*/
Bank::Bank()
{
    ifstream infile("account.dat",ios::in|ios::binary);
    if(!infile)   //检测文件是否成功打开
    {
        cerr<<"open error!"<<endl;
        abort();
    }
    //利用文件指针计算文件的长度,从而计算出用户对象的个数
    infile.seekg (0, ios::end);   //将文件指针标记在文件末尾
    int length = infile.tellg();  //计算出文件的长度
    N=length/sizeof(User);        //计算出对象的个数,然后用静态数据成员保存用户个数
    users=new User[N+1];          //动态数组建立对象数组
    infile.seekg(0,ios::beg);     //操作完文件指针后一定要把指针重新定义在文件首的位置
    int i=0;   //用户数目
    //读取文件,将文件保存在users[N+1]数组内
    while(!infile.eof())
    {
        infile.read((char *)&users[i],sizeof(users[i]));
        ++i;
    }
    /*
    //文本文件的形式
    while(infile>>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!"<<endl;
        abort();
    }
    int i;
    //将users数组内的内容写回文件
    for(i=0; i<N; i++)
    {
        outfile.write((char *)&users[i],sizeof(users[i]));
    }
    outfile.close();
    free(users);      //对应realloc()函数
    delete[] users;   //切记释放动态数组占用的空间7
}

/*
* 功能描述:办理业务
*/
void Bank::work()
{
    int iChoice;    //用于选择系统功能
    //办理业务
    do
    {
        iChoice = chooseInMenu();  //从菜单中获得功能代码
        switch(iChoice)
        {
        case 1:
            openAccount();      //开户
            break;
        case 2:
            cancelAccount();    //注销账户
            break;
        case 3:
            save();             //存款
            break;
        case 4:
            withdraw();         //取款
            break;
        case 5:
            showAccount();      //查询余额
            break;
        case 6:
            transferAccounts(); //转账
            break;
        case 7:
            reportLoss();       //挂失
            break;
        case 8:
            cancelLoss();       //解除挂失
            break;
        case 9:
            updatePassword();   //更改密码
            break;
        case 0:
            cout<<"欢迎您再来... "<<endl;
        }
    }
    while(iChoice);
}

/*
* 功能描述:开户
* 其它说明:
(1)在进入系统时,在读入数据过程中,已经记录了用户数为N,在数组中对应下标为0~N-1,
开户时要增加一个用户,只要为下标为N的数组元素置值,并在成功之后令N++即可。
账号由系统自动生成(10001+序号),保证其连续,这样在顺序增加的时候,就保证了其有序。

(2)关于realloc函数的一点说明:
     所在头文件:stdlib.h
     语法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。//新的大小一定要大于原来的大小,不然的话会导致数据丢失!
     函数用途:扩展数组的长度,即重新分配存储器块的地址
     返回值:如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。
     注意:这里原始内存中的数据还是保持不变的。当内存不再使用时,应使用free()函数将内存块释放
*/
void Bank::openAccount()
{
    int acc;      //账号
    char nam[20]; //姓名
    int pw;       //密码
    double bal;   //金额
    char se;      //性别
    char ID[20];  //身份证号
    char add[20]; //地址
    char pn[12];  //电话号码
    int sta;      //状态
    cout<<"正在开户:"<<endl;
    acc=10001+N;  //所开账户即为已有账户数目N+初始值10001所表示的账户
    cout<<"请填写以下信息:"<<endl;
    cout<<"账号:"<<acc<<endl;
    cout<<"户主姓名:";
    cin>>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<<"您已成功开户!"<<endl;
    }
    else
    {
        cout<<"对不起,您输入的两次密码不一致,未成功开户!"<<endl; //没有N++,则读入的值无效
    }
}

/*
 * 功能描述:注销账户
 * 其它说明:消找到账户,并将其状态改为2-注销即可。
   注销前应该检查余额,应该先取款再注销
*/
void Bank::cancelAccount()
{
    int who;          //查找到该账号在数组中对应的下标
    who = getUser();  //根据账号查询用户,返回用户的下标
    string PN;        //输入手机号
    if(who>=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<<"您取消了操作,销户失败!"<<endl;
            }
            fflush(stdin);  //清除了getchar()时在键盘缓存中的遗留,以免影响后续操作
        }
    }
}

/*
 * 功能描述:存款
 * 其它说明:需要保证账户存在,且处于正常状态
*/
void Bank::save()
{
    int who;
    double money;
    who = getUser();  //根据账号查询用户,返回用户的下标
    if(who>=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<<"该用户处于挂失状态,存款失败!"<<endl;
        }
        else
        {
            cout<<"该用户已经销户,存款失败!"<<endl;
        }
    }
    return;
}

/*
 * 功能描述:取款
 * 其它说明:消需要保证账户存在,且处于正常状态,另外,余额要足够取
*/
void Bank::withdraw()
{
    int who;
    double money;
    who = getUser();  //根据账号查询用户,返回用户的下标
    if(who>=0)        //说明id账户存在
    {
        if(users[who].isNormalUser())
        {
            users[who].showName();
            if(users[who].passwordIsRight())
            {
                cout<<"请输入取款金额:";
                cin>>money;
                if(money>users[who].balance)  //余额要大于取款金额
                {
                    cout<<"对不起,您的余额不足,取款失败!"<<endl;
                }
                else
                {
                    users[who].balance-=money;
                    users[who].showBalance("取款后,您所剩的账户余额为:");
                }
            }
        }
    }
    return;
}

/*
* 功能描述:查询账户
* 其它说明:显示账户信息
*/
void Bank::showAccount()
{
    int who;
    string sta[3]= {"正常","挂失","已经销户"}; //
    who = getUser();  //根据账号查询用户,返回用户的下标
    if(who>=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<<"状态:"<<sta[users[who].status]<<endl;
        }
    }
    return;
}

/*
 * 功能描述:转账
 * 其它说明:需要保证两个账户都存在,且处于正常状态,另外,转出账户的余额要足够
*/
void Bank::transferAccounts()
{
    int whoout, whoin;
    double money;
    cout<<"转出自";
    whoout = getUser();  //根据账号查询用户,返回用户的下标
    if(whoout>=0)        //说明id账户存在
    {
        if(users[whoout].isNormalUser())         //转出账户处于正常状态
        {
            users[whoout].showName();
            if(users[whoout].passwordIsRight())  //输入密码正确
            {
                cout<<"输入转账金额:";
                cin>>money;
                if(money>users[whoout].balance)  //转出金额足够
                {
                    cout<<"对不起,您的余额不足,转账失败!"<<endl;
                }
                else
                {
                    cout<<"转出到";
                    whoin = getUser();  //根据账号查询用户,返回用户的下标
                    if(whoin>=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<<"您已挂失成功。"<<endl;
                }
                else
                    cout<<"对不起,您输入的手机号并非该账户所绑定的手机号,挂失失败。";
            }
            else if(users[who].status==1)
            {
                cout<<"该账户已经处于挂失状态。"<<endl;
            }
            else
            {
                cout<<"该账户不存在,不能挂失。"<<endl;
            }
        }
    }
    return;
}

/*
 * 功能描述:解除挂失
 * 其它说明:解除挂失需要手机验证,以及身份证号验证
*/
void Bank::cancelLoss()
{
    int who;
    string ID;        //身份证号码
    string pn;        //绑定手机号
    who = getUser();  //根据账号查询用户,返回用户的下标
    if(who>=0)        //说明id账户存在
    {
        users[who].showName();
        if(users[who].passwordIsRight())
        {
            if(users[who].status==0)
            {
                cout<<"该账户处于正常状态,不需要解除挂失。"<<endl;
            }
            else if(users[who].status==1)
            {
                cout<<"请输入您所绑定的手机号,确认解除挂失:"; //手机验证,确认解挂信息,实际运用中会收到验证码
                cin>>pn;
                if(users[who].phonenumber==pn)
                {

                    cout<<"请输入您的的身份证号码:";
                    cin>>ID;
                    if(users[who].IDcard==ID)
                    {
                        users[who].status=0;
                        cout<<"解除挂失成功。"<<endl;
                    }
                    else
                        cout<<"您输入的身份证号码错误,解挂失败。";
                }
                else
                    cout<<"您输入的手机号码错误,解挂失败。";
            }
            else
            {
                cout<<"该账户已销户,操作无效"<<endl;
            }
        }
    }
    return;
}

/*
 * 功能描述:改密码
*/
void Bank::updatePassword()
{
    int who;
    int iPass1, iPass2;
    who = getUser();  //根据账号查询用户,返回用户的下标
    if(who>=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<<"修改成功!"<<endl;
            }
            else
            {
                cout<<"您的两次输入不同,修改失败!"<<endl;
            }
        }
    }
    return;
}

/*
 * 功能描述:输入账号查询用户,返回用户在数组中的下标
 * 入口参数:要查询用户的账号
 * 返回值:如果该用户存在,返回该用户在数组中的下标,否则,返回一个负数(-1)
 * 其他说明:由账号自动产生,使按账号有序。
             本模块采用二分查找
*/
int Bank::getUser()
{
    int id;
    cout<<"账号:";
    cin>>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<<"该用户不存在,操作失败!"<<endl;
    return index;    //若找到,其值在0~N-1间,否则,保持-1
}


main.cpp

/***********************************************************
* 版权所有 (C)2015, 陈文青。
*
* 文件名称: main.cpp
* 文件标识:
* 内容摘要:主函数
* 其它说明:
* 当前版本: V1.0
* 作    者:陈文青
* 完成日期: 20150715
*
* 修改记录:
* 修改日期: 20150715
* 版本号: V1.0
* 修改人: 陈文青
* 修改内容:
**********************************************************/
#include <iostream>
#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


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

account.dat


运行结果:

业务员登录+开户


销户+存款


取款+查询


转账


挂失+解挂


改密+退出


知识点总结:

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

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


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

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

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


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

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


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


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值