<2015年大一C++实训项目>银行储蓄系统

来源:互联网 发布:linux桌面使用入门 编辑:程序博客网 时间:2024/05/16 11:39
/******************************************** 版权所有 (C)2015,Annpion。** 文件名称:main.cpp*文件标识:无*内容摘要:该代码是程序的主要运行的首部分。*其他说明:无*当前版本:V1.0*作者:王耀鹏*完成日期:2015/7/17*******************************************/#include <iostream>#include "Bank.h"using namespace std;int main(){    cout<<"+-----------------------+\n";    cout<<"+    欢迎光临中国银行   +\n";    cout<<"+-----------------------+\n";    if (pass())    {        Bank b;        b.work();    }    return 0;}/******************************************** 版权所有 (C)2015,Annpion。** 文件名称:Bank.h*文件标识:无*内容摘要:该代码定义、声明类以及函数。*其他说明:无*当前版本:V1.0*作者:王耀鹏*完成日期:2015/7/17*******************************************/#ifndef BANK_H_INCLUDED#define BANK_H_INCLUDED#include <cstring>using namespace std;struct UserIndex{    int No;    long offset;};class Bank;class User{public:    void setUser(int acc, char *nam, int pw, double bal,int sta);    void showName();    void showStatus(string prompt);    int getaccount();    void showBalance(string prompt); //显示余额,前面加上提示词prompt    bool passwordIsRight();   //校验密码,输入的密码正确则返回true    bool isNormalUser(); //存款、取款、转帐等功能,需要账户处于正常姿态,处于正常状态时返回true,其他情形返回false并提示    friend class Bank;private:    int account;    char name[8];    int password;    double balance;    int status;};class Bank{public:    Bank();    ~Bank();    void work();    void openAccount();    void cancelAccount();    void save();    void withdraw();    void showAccount();    void transferAccounts();    void reportLoss();    void cancelLoss();    void updatePassword();    void createIndex();    void EnlargeArray();    void writeIndex(UserIndex *ui, int n);    long getUser();private:    int maxNum;    int UserNum;    UserIndex *userIndex;};int pass();int chooseInMenu();int inputPassword();void createIndex();void writeIndex(UserIndex *ui, int n);void init();void done();void EnlargeArray();#endif // BANK_H_INCLUDED/******************************************** 版权所有 (C)2015,Annpion。** 文件名称:Bank.cpp*文件标识:无*内容摘要:该代码实现Bank类中的各个函数。*其他说明:无*当前版本:V1.0*作者:王耀鹏*完成日期:2015/7/17*******************************************/#include <iostream>#include <fstream>#include <cstdlib>#include <algorithm>#include <ctype.h>#include "bank.h"using namespace std;fstream dataFile, indexFile;/********************************************功能描述:构造Bank类中的数据成员。*输入参数:User-用户类*输出参数:userIndex-用户索引            UserNum-用户人数*返回值:无*其他说明:从文件中读入用户数据作成用户索引。*******************************************/Bank::Bank(){    createIndex();}/********************************************功能描述:析构Bank类。*输入参数:无*输出参数:无*返回值:无*其他说明:把索引写入文件,清除内存。*******************************************/Bank::~Bank(){    writeIndex(userIndex,UserNum);    dataFile.close();    delete []userIndex;}/********************************************功能描述:选择所需的功能。*输入参数:iChoice-功能序号*输出参数:无*返回值:无*其他说明:利用输入的序号调用各个功能函数。*******************************************/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);}/********************************************功能描述:开户。*输入参数:user-用户类*输出参数:userIndex-用户索引            UserNum-用户人数*返回值:无*其他说明:用户增加,索引增加,人数增加。*******************************************/void Bank::openAccount(){    User user;    int acc;   //账号    char nam[8];   //姓名    int pw;   //密码    double bal;   //金额    int sta;    cout<<"正在开户"<<endl;    acc=10001+UserNum;    cout<<"账号:"<<acc<<endl;    cout<<"户主姓名:";    cin>>nam;    int iPass1, iPass2;    cout<<"密码:";    iPass1=inputPassword();  //输入密码1    cout<<"确认密码:";    iPass2=inputPassword();  //输入密码2    if(iPass1==iPass2)    {        pw=iPass1;        sta=0; //账户状态为“正常”        cout<<"存入金额:";        cin>>bal;        user.setUser(acc, nam, pw, bal,sta);        dataFile.seekp(0,ios::end);        dataFile.write((char *)&user,sizeof(user));        dataFile.seekg(-sizeof(User),ios::end);        userIndex[UserNum].No=user.account;        userIndex[UserNum].offset=dataFile.tellg();        UserNum++; //正式用户数增加1,确认了新用户已经加入        cout<<"成功开户!"<<endl;        dataFile.seekp(0,ios::beg);        dataFile.write((char *)&UserNum,sizeof(UserNum));        if(UserNum>=maxNum)            EnlargeArray();    }    else    {        cout<<"两次密码不一致,未成功开户!"<<endl; //没有N++,则读入的值无效    }}/********************************************功能描述:销户。*输入参数:location-用户数据位置*输出参数:user-用户类*返回值:无*其他说明:用户状态被改变。*******************************************/void Bank::cancelAccount(){    User user;    long location;    location = getUser();  //根据账号查询用户,返回用户的偏移量    if(location>=0)   //说明id账户存在    {        dataFile.seekg(location);        dataFile.read((char *)&user,sizeof(user));        user.showName();        if(user.isNormalUser())        {            if(user.passwordIsRight())            {                user.showBalance("余额");   //提示"余额"二字,显示金额                cout<<"确认销户(y/n)?";                if(tolower(getchar())=='y')                {                    user.showBalance("销户成功!本次取款金额为");                    user.balance=0;  //取款后余额变0                    user.status=2;  //状态变为注销                    dataFile.seekp(location);                    dataFile.write((char *)&user,sizeof(user));                }                else                {                    cout<<"你取消了操作,销户失败!"<<endl;                }                fflush(stdin);  //清除了getchar()时在键盘缓存中的遗留,以免影响后续操作            }        }    }}/********************************************功能描述:存款。*输入参数:location-用户数据位置*输出参数:user-用户类*返回值:无*其他说明:用户余额改变。*******************************************/void Bank::save(){    User user;    long location;    double money;    location = getUser();  //根据账号查询用户,返回用户的偏移量    if(location>=0)   //说明id账户存在    {        dataFile.seekg(location);        dataFile.read((char *)&user,sizeof(user));        user.showName();        if(user.isNormalUser())        {            cout<<"输入存款额:";            cin>>money;            user.balance+=money;            user.showBalance("存款后,您有");            dataFile.seekp(location);            dataFile.write((char *)&user,sizeof(User));        }    }    return;}/********************************************功能描述:取款。*输入参数:location-用户数据位置*输出参数:user-用户类*返回值:无*其他说明:用户余额改变。*******************************************/void Bank::withdraw(){    User user;    long location;    double money;    location = getUser();  //根据账号查询用户,返回用户的偏移量    if(location>=0)   //说明id账户存在    {        dataFile.seekg(location);        dataFile.read((char *)&user,sizeof(User));        user.showName();        if(user.passwordIsRight())        {            if(user.isNormalUser())            {                cout<<"输入取款额:";                cin>>money;                if(money>user.balance)  //亲,不玩透支                {                    cout<<"余额不足,取款失败!"<<endl;                }                else                {                    user.balance-=money;                    user.showBalance("取款后,还有");                    dataFile.seekp(location);                    dataFile.write((char *)&user,sizeof(User));                }            }        }    }    return;}/********************************************功能描述:查询。*输入参数:location-用户数据位置*输出参数:user-用户类*返回值:无*其他说明:显示用户数据。*******************************************/void Bank::showAccount(){    User user;    long location;    location = getUser();  //根据账号查询用户,返回用户的偏移量    if(location>=0)   //说明id账户存在    {        dataFile.seekg(location);        dataFile.read((char *)&user,sizeof(user));        user.showName();        if(user.passwordIsRight())        {            user.showBalance("余额:");            user.showStatus("状态:");        }    }    return;}/********************************************功能描述:转账。*输入参数:location-用户数据位置*输出参数:user-用户类*返回值:无*其他说明:用户余额被改变。*******************************************/void Bank::transferAccounts(){    User user1,user2;    long whoout, whoin;    double money;    cout<<"转出自";    whoout = getUser();  //根据账号查询用户,返回用户的偏移量    if(whoout>=0)   //说明id账户存在    {        dataFile.seekg(whoout);        dataFile.read((char *)&user1,sizeof(User));        user1.showName();        if(user1.isNormalUser())        {            if(user1.passwordIsRight())            {                cout<<"输入转账金额:";                cin>>money;                if(money>user1.balance)                {                    cout<<"余额不足,转账失败!"<<endl;                }                else                {                    cout<<"转出到";                    whoin = getUser();  //根据账号查询用户,返回用户的偏移量                    if(whoin>=0)   //说明id账户存在                    {                        dataFile.seekg(whoin);                        dataFile.read((char *)&user2,sizeof(User));                        if(user2.isNormalUser())                        {                            user1.balance-=money;                            user2.balance+=money;                            user1.showBalance("转账后,您还有");                            dataFile.seekp(whoout);                            dataFile.write((char *)&user1,sizeof(User));                            dataFile.seekp(whoin);                            dataFile.write((char *)&user2,sizeof(User));                        }                    }                }            }        }    }    return;}/********************************************功能描述:挂失。*输入参数:location-用户数据位置*输出参数:user-用户类*返回值:无*其他说明:用户状态被改变。*******************************************/void Bank::reportLoss(){    User user;    long location;    location = getUser();  //根据账号查询用户,返回用户的偏移量    if(location>=0)   //说明id账户存在    {        dataFile.seekg(location);        dataFile.read((char *)&user,sizeof(User));        user.showName();        if(user.passwordIsRight())        {            if(user.isNormalUser())            {                user.status=1;                cout<<"挂失成功"<<endl;                dataFile.seekp(location);                dataFile.write((char *)&user,sizeof(user));            }        }    }    return;}/********************************************功能描述:解挂。*输入参数:location-用户数据位置*输出参数:user-用户类*返回值:无*其他说明:用户状态被改变。*******************************************/void Bank::cancelLoss(){    User user;    long location;    location = getUser();  //根据账号查询用户,返回用户的偏移量    if(location>=0)   //说明id账户存在    {        dataFile.seekg(location);        dataFile.read((char *)&user,sizeof(User));        user.showName();        if(user.passwordIsRight())        {            if(user.status==0)            {                cout<<"该账户处于正常状态,不需要解除挂失"<<endl;            }            else if(user.status==1)            {                user.status=0;                cout<<"解除挂失成功"<<endl;                dataFile.seekp(location);                dataFile.write((char *)&user,sizeof(user));            }            else            {                cout<<"该账户已销户,操作无效"<<endl;            }        }    }    return;}/********************************************功能描述:改密。*输入参数:location-用户数据位置*输出参数:user-用户类*返回值:无*其他说明:用户密码被改变。*******************************************/void Bank::updatePassword(){    User user;    long location;    int iPass1,iPass2;    location = getUser();  //根据账号查询用户,返回用户的偏移量    if(location>=0)   //说明id账户存在    {        if(user.isNormalUser())        {            dataFile.seekg(location);            dataFile.read((char *)&user,sizeof(User));            user.showName();            if(user.passwordIsRight())            {                cout<<"新密码:";                iPass1=inputPassword();  //输入密码1                cout<<"确认密码:";                iPass2=inputPassword();  //输入密码2                if(iPass1==iPass2)                {                    user.password=iPass1;                    cout<<"修改成功!"<<endl;                    dataFile.seekp(location);                    dataFile.write((char *)&user,sizeof(User));                }                else                {                    cout<<"两次输入不同,修改失败!"<<endl;                }            }        }    }    return;}/********************************************功能描述:建立索引。*输入参数:user-用户类*输出参数:userIndex-用户索引*返回值:userIndex-用户索引*其他说明:无。*******************************************/void Bank::createIndex(){    User user;    dataFile.open("binarydata.dat",ios::out|ios::in|ios::binary);    if(!dataFile)    {        cerr<<"can't open binarydata.dat!"<<endl;        exit(1);    }    //建立索引    dataFile.read((char *)&UserNum,sizeof(UserNum));    maxNum=UserNum * 1.1;    userIndex=new UserIndex [maxNum];    //读入数据,建立未排序的索引表    int i, j;    long mOffset;    for(i=0; i<UserNum; ++i)    {        mOffset = dataFile.tellg();        dataFile.read((char*)&user, sizeof(user));        userIndex[i].No = user.getaccount();        userIndex[i].offset = mOffset;    }    UserIndex temp;    for (i=0; i<UserNum-1; i++)        for(j=0; j<UserNum-i-1; j++)            if (userIndex[j].No>userIndex[j+1].No)            {                temp=userIndex[j];                userIndex[j]=userIndex[j+1];                userIndex[j+1]=temp;            }    //将建好的索引表通过文件存储    writeIndex(userIndex, UserNum);    return ;}/********************************************功能描述:扩大数组。*输入参数:userIndex-用户索引*输出参数:userIndex-用户索引*返回值:无*其他说明:扩大索引。*******************************************/void Bank::EnlargeArray(){    User user;    maxNum = UserNum *1.1;    userIndex = new UserIndex[maxNum];    int i;    long mOffset;    for(i=0; i<UserNum; ++i)    {        mOffset = dataFile.tellg();        dataFile.read((char*)&user, sizeof(user));        userIndex[i].No = user.getaccount();        userIndex[i].offset = mOffset;    }    return ;}/********************************************功能描述:写入索引。*输入参数:userIndex-用户索引*输出参数:userIndex.idx-索引文件名*返回值:无*其他说明:无。*******************************************/void Bank::writeIndex(UserIndex *ui, int n){    //打开文件    ofstream indexFile("userIndex.idx", ios::out|ios::binary);    if(!indexFile)    {        cerr<<"can't open userIndex.idx!"<<endl;        exit(1);    }    int i;    for(i=0; i<n; ++i)    {        indexFile.write((char*)&ui[i], sizeof(ui[i]));    }    //关闭文件    indexFile.close();    return;}/********************************************功能描述:寻找用户位置。*输入参数:id-用户账号*输出参数:location-用户数据位置*返回值:无*其他说明:无。*******************************************/long Bank::getUser(){    int id;    long location=-1;    int low=0,high=UserNum-1,mid;    cout<<"账号:";    cin>>id;    while(low<=high)    {        mid = (low+high)/2;        if(userIndex[mid].No==id)        {            location=userIndex[mid].offset;            break;   //找到了,立即退出循环        }        else if (userIndex[mid].No>id)            high=mid-1;        else            low=mid+1;    }    if (location<0)        cout<<"该用户不存在,本次操作失败!"<<endl;    return location; //若找到,其值在0~N-1间,否则,保持-1}/******************************************** 版权所有 (C)2015,Annpion。** 文件名称:User.cpp*文件标识:无*内容摘要:该代码实现User类中的各个函数。*其他说明:无*当前版本:V1.0*作者:王耀鹏*完成日期:2015/7/17*******************************************/#include <iostream>#include "Bank.h"using namespace std;/********************************************功能描述:设置User类中的数据成员。*输入参数:acc-用户账号            nam-用户名称            pw-用户密码            bal-用户余额            sta-用户状态*输出参数:user-用户类*返回值:无*其他说明:无。*******************************************/void User::setUser(int acc, char *nam, int pw, double bal,int sta){    account=acc;    password=pw;    strcpy(name,nam);    balance=bal;    status=sta;}/********************************************功能描述:显示用户名称。*输入参数:user-用户类*输出参数:无*返回值:无*其他说明:显示姓名。*******************************************/void User::showName(){    cout<<"户主姓名:"<<name<<endl;}void User::showStatus(string prompt){    cout<<prompt<<" ";    if(status==0)        cout<<"正常"<<endl;    else if(status==1)        cout<<"挂失"<<endl;    else cout<<"销户"<<endl;}/********************************************功能描述:获取用户账号。*输入参数:user-用户类*输出参数:account-用户账号*返回值:无*其他说明:无。*******************************************/int User::getaccount(){    return account;}/********************************************功能描述:显示用户余额。*输入参数:banlance-用户余额            prompt-显示语句*输出参数:无*返回值:无*其他说明:无。*******************************************/void User::showBalance(string prompt){    cout<<prompt<<" "<<balance<<" 元"<<endl;}/********************************************功能描述:核对用户密码。*输入参数:password-用户密码            iPass-输入密码*输出参数:right-判断对错*返回值:true-正确,false-错误*其他说明:无。*******************************************/bool User::passwordIsRight(){    int iPass;    bool right = true;    cout<<"输入密码:";    iPass=inputPassword();    if(iPass!=password)    {        right = false;        cout<<"输入密码错误,不能继续操作!"<<endl;    }    return right;}/********************************************功能描述:判断用户状态。*输入参数:status-用户状态*输出参数:normal-判断用户状态*返回值:true-正常,false-异常*其他说明:无。*******************************************/bool User::isNormalUser(){    bool normal = true;    if(status!=0)    {        normal = false;        cout<<"该账户处于"<<(status==1?"挂失":"销户")<<"状态,不能继续操作..."<<endl;    }    return normal;}/******************************************** 版权所有 (C)2015,Annpion。** 文件名称:Word.cpp*文件标识:无*内容摘要:该代码实现普通函数。*其他说明:无*当前版本:V1.0*作者:王耀鹏*完成日期:2015/7/17*******************************************/#include <iostream>#include <fstream>#include <conio.h>#include <cstdlib>#include <cstring>#include <ctype.h>#include "Bank.h"using namespace std;/********************************************功能描述:验证业务员密码。*输入参数:sNameInFile-业务员姓名            sPassInFile-业务员密码            sName-业务员输入姓名            sPass-业务员输入密码*输出参数:right-判断正误*返回值:1-成功,0-失败*其他说明:无。*******************************************/int pass(){    char sNameInFile[20];   //由文件中读出的业务员用户名    char sPassInFile[20];  //文件中保存的密码,这一版本中,用字符保存密码    ifstream infile("password.txt",ios::in);    if(!infile)    {        cout<<"password file cannot open!"<<endl;        exit(1);    }    infile>>sNameInFile>>sPassInFile;    infile.close();    char sName[20];   //业务员登录时输入的用户名    char sPass[20];  //业务员登录时输入的密码    char ch;    int iTry=3;   //进入系统时尝试的次数    int right = 0;  //要返回的结果:0-不正确 1-正确    //进入系统,密码三次不对将退出    do    {        cout<<"请输入业务员用户名:";        cin>>sName;        cout<<"请输入密码:";        int i=0;        while((ch=getch())!='\r')  //getch在接受输入后,不在屏幕上显示        {            sPass[i++]=ch;            putchar('*');   //接受任何字符,屏幕上只显示*        }        sPass[i]='\0';        fflush(stdin);        cout<<endl;        if(strcmp(sPass,sPassInFile)==0&&strcmp(sName,sNameInFile)==0)        {            right = 1;            break;        }        else        {            iTry--;            if(iTry>0)                cout<<"超过3次将退出,你还可以尝试"<<iTry<<"次!"<<endl;            else            {                cout<<"对不起,你不能进入系统"<<endl;;            }        }    }    while(iTry);    return right;}/*关于getch()的一点说明:所在头文件:conio.h函数用途:从控制台读取一个字符,但不显示在屏幕上函数原型:int getch(void)返回值:读取的字符在不同平台,输入回车,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)。为避免键盘缓存区中未读出的字符影响程序,用fflush(stdin);清除输入缓存区*//********************************************功能描述:选择功能。*输入参数:i-功能序号*输出参数:i-功能序号*返回值:1-开户,2-销户,3-存款,4-取款,5-查询,6-转账,7-挂失,8-解挂,9-改密,0-退出*其他说明:无。*******************************************/int 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位数字构成(当开头是'0'时,实际不足6位),一旦输入错误将重新输入附:在实际的系统中,密码通常用字符串描述,即使只允许出现数字字符,本例仅作为参考*//********************************************功能描述:输入密码。*输入参数:iPass-用户密码*输出参数:iPass-用户密码*返回值:iPass-用户密码*其他说明:输入的密码在显示时呈星号。*******************************************/int inputPassword(){    char ch;  //接收字符形式密码    int iPass=0;   //要转换为数字    int i;    while(1)    {        for(i=0; i<6; i++)        {            ch=getch();  //输入但不显示            putchar('*');   //输出*            if(isdigit(ch))                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;}

运行结果:


0 0