关于c++的问题:登录时报错无法登陆(银行账户管理系统)

登录时报错无法登陆(银行账户管理系统)(C++)
求看看如何修改

img

img


#include<iostream>
#include<string>
#include<fstream>
#include<vector>
using namespace std;
class Account {
protected:
    string name;//姓名
    string id; //账号
    string password;//密码 
    double balance;//余额
    bool live; //账号是否存活 
    char mark; //标记是否为管理员
public:
    Account() {}
    Account(string nn, string ni, string np, double nb, bool nl, char nm) {
        name = nn;
        id = ni;
        password = np;
        balance = nb;
        live = nl;
        mark = nm;
    }
    //查询余额
    double query() {
        return balance;
    }
    //取款
    bool withdraw(double money) {
        if (balance < money)
            return false;
        balance -= money;
        return true;
    }
    //存款
    void deposit(double money) {
        balance += money;
    }
    //成员对外接口
    string getName() {
        return name;
    }
    string getID() {
        return id;
    }
    string getPassword() {
        return password;
    }
    double getBalance() {
        return balance;
    }
    char getMark() {
        return mark;
    }
    bool isLive() {
        return live;
    }
    void setPassword(string np) {
        password = np;
    }
    void setLive(bool nl) {
        live = nl;
    }
    void setBalance(double nb) {
        balance = nb;
    }
};
class FileTools {
public:
    static vector<Account> accounts;
    //读取文件中的账户信息
    static void getAccounts() {
        //打开文件读入流
        ifstream in;
        in.open("ID.txt", ios::in);
        //读取数据到数组中
        string id, password, name;
        double balance;
        char mark; //标记是否为管理员
        accounts.clear();
        while (in >> mark >> id >> password >> name >> balance) {
            accounts.push_back(Account(name, id, password, balance, true, mark));
        }
        in.close();
    }
    //将内存中的账户信息存储到文件
    static void saveAccounts() {
        //打开文件输出流
        ofstream out;
        out.open("ID.txt", ios::out);
        //输出到文件中(已经删除的账户就不存了)
        for (int i = 0; i < accounts.size(); i++) {
            Account a = accounts[i];
            if (a.isLive())
                out << a.getMark() << " " << a.getID() << " "
                << a.getPassword() << " " << a.getName() << " "
                << a.getBalance() << endl;
        }
        out.close();
    }
    //将日志信息写入到日志文件
    static void addLog(string log) {
        //打开文件输出流
        ofstream out;
        out.open("LOG.txt", ios::out|ios::app);
        //输出到日志文件中
        out <<log<< endl;
        out.close();
    }
    //查找某个用户在数组中的位置
    static int findAccountByID(string id) {
        for (int i = 0; i < accounts.size(); i++) {
            if (accounts[i].getID() == id) {
                return 1;
            }
        }
        //没找到返回-1;
        return -1;
    }
};
vector<Account> FileTools::accounts;
class Admin :public Account {
public:
    Admin(Account a) {
        name = a.getName();
        id = a.getID();
        password = a.getPassword();
        balance = a.getBalance();
        live = true;
    }
    //添加用户
    void addAccount(Account a) {
        FileTools::accounts.push_back(a);
    }
    //根据账号删除用户
    bool deleteAccountByID(string id) {
        int index = FileTools::findAccountByID(id);
        //没找到账号
        if (index == -1)
            return false;
        //修改账户为已死亡
        FileTools::accounts[index].setLive(false);
        return true;
    }
    //根据账号修改用户的余额
    bool editPasswordByID(string id, string password) {
        int index = FileTools::findAccountByID(id);
        //没找到账号
        if (index == -1)
            return false;
        //进行修改
        FileTools::accounts[index].setPassword(password);
        return true;
    }
private:
};
class Frame {
    int nowAccount; //当前用户(下标)
public:
    Frame() {
        int select;
        while (true) {
            //一级菜单
            cout << "请输入选项进行对应操作" << endl;
            cout << "1,用户登录" << endl;
            cout << "2,管理员操作" << endl;
            cout << "3,注册新用户" << endl;
            cout << "0,退出" << endl;
            cin >> select;
            cout << "-------------------------------------------" << endl;
            if (select == 0) {
                //退出之前保存文件
                FileTools::saveAccounts();
                break;
            }
            string id, password;
            int index;
            switch (select) {
            case 1: {
                if (loginFrame()) {
                    accountFrame();
                    FileTools::saveAccounts();
                }
                break;
            }
            case 2: {
                if (loginFrame()) {
                    if (FileTools::accounts[nowAccount].getMark() != '*') {
                        cout << "-------------------不是管理员-------------------" << endl;
                    }
                    else {
                        cout << "-------------------------------------------" << endl;
                        adminFrame();
                        FileTools::saveAccounts();
                    }
                }
                break;
            }
            case 3: {
                registFrame();
                break;
            }
        }
    }
}
    //登录窗口
    bool loginFrame() {
        string id, password;
        int index;
        cout << "输入账号密码" << endl;
        while (true) {
            cin >> id;
            if (id == "0") { //登录失败
                cout << "-------------------登录失败-------------------" << endl;
                return false;
            }
            if ((index = FileTools::findAccountByID(id)) != -1) {
                cin >> password;
                if (password != FileTools::accounts[index].getPassword()) {
                    cout << "密码错误," << endl;
                }
                else {
                    //登录成功
                    cout << "-------------------登录成功-------------------" << endl;
                    nowAccount = index;
                    return true;
                }
            }
            else {
                //没找到账号
                cout << "账号不存在,";
            }
            cout << "请重新输入账号密码或输入 0 退出" << endl;
        }
    }
    //用户窗口
    void accountFrame() {
        int select;
        double money;
        while (true) {
            cout << "1,存钱" << endl;
            cout << "2,取钱" << endl;
            cout << "3,查余额" << endl;
            cout << "0,退出" << endl;
            cin >> select;
            if (select == 0)
                return;
            switch (select) {
            case 1: {
                cout << "输入金额:";
                cin >> money;
                double nowMoney = FileTools::accounts[nowAccount].getBalance();
                FileTools::accounts[nowAccount].setBalance(nowMoney + money);
                cout << "-------------------存钱成功-------------------" << endl;
                break;
            }
            case 2: {
                cout << "输入取钱金额:";
                cin >> money;
                double nowMoney = FileTools::accounts[nowAccount].getBalance();
                if (nowMoney < money) {
                    cout << "-------------------余额不足-------------------" << endl;
                }
                else {
                    FileTools::accounts[nowAccount].setBalance(nowMoney - money);
                    cout << "-------------------取钱成功-------------------" << endl;
                }
                break;
            }
            case 3: {
                cout << "当前余额为:" <<
                    FileTools::accounts[nowAccount].getBalance() << endl;
                cout << "------------------------------------------" << endl;
                break;
            }
        }
    }
}
    //管理员窗口
    void adminFrame() {
        int select;
        string id, password, np, name;
        Admin admin(FileTools::accounts[nowAccount]);
        while (true) {
            cout << "1,添加账户" << endl;
            cout << "2,删除账户" << endl;
            cout << "3,修改密码" << endl;
            cout << "0,退出" << endl;
            cin >> select;
            if (select == 0)
                break;
            switch (select) {
            case 1: {
                cout << "输入账号,密码,姓名" << endl;
                cin >> id >> password >> name;
                admin.addAccount(Account(name, id, password, 0, true, '#'));
                FileTools::saveAccounts();
                cout << "-------------------添加成功-------------------" << endl;
                break;
            }
            case 2: {
                cout << "输入账号" << endl;
                cin >> id;
                if (admin.deleteAccountByID(id)) {
                    FileTools::saveAccounts();
                    cout << "-------------------删除成功-------------------" << endl;
                }
                else {
                    cout << "------------------账号不存在-------------------" << endl;
                }
                break;
            }
            case 3: {
                cout << "输入账号,和新密码" << endl;
                cin >> id >> np;
                if (admin.editPasswordByID(id, np)) {
                    FileTools::saveAccounts();
                    cout << "-------------------账号重复-------------------" << endl;
                }
                else {
                    cout << "-------------------注册成功-------------------" << endl;
                }
                break;
            }
            }
        }
    }
    //注册窗口
    void registFrame() {
        string name, id, password;
        cout << "输入姓名" << endl;
        cin >> name;
        cout << "输入账号" << endl;
        while (true) {
            cin >> id;
            if (FileTools::findAccountByID(id) != -1) {
                //有重复的账号
                cout << "-------------------账号重复-------------------" << endl;
            }
            else {
                cout << "输入密码" << endl;
                cin >> password;
                FileTools::accounts.push_back(Account(name, id, password, 0, true, '#'));
                FileTools::saveAccounts();
                cout << "-------------------注册成功-------------------" << endl;
                return;
            }
        }
    }
};
int main() {
    FileTools::getAccounts();
    Frame frame;
    return 0;
}

错误提示信息是vector下标越界
具体你不要直接运行,而是单步执行,这样可以告诉你出错的代码行。

  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/7432797
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:【算法设计与分析】数字统计问题(C++实现)
  • 除此之外, 这篇博客: 设计算法判断给定的无向图是树(C++)(附源码,可以直接运行)中的 设计算法判断给定的无向图是树 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 从做完本次作业到写这篇博客已经过去了大概两三个月,对一些点可能已经忘记了。
    中间也许有写的不好的地方,请大家见谅。
    

    一、算法思想:
    判断方法为使用DFS进行遍历,看是否可以将图节点全部遍历(判断是否是连通图),同时统计边数,判断是否为N-1。这两个条件缺一不可。即必须是连通图且边数为N-1(N为顶点个数)。
    二、图的建立
    首先一个比较困难的问题就是图的创建,我采用的是邻接表的形式创建的,有一个node1类型的数组ver,其用来存储节点的数据信息,每一个node1类型的struct都有一个data数据域和node2类型的指针域firstadj,用来指向其之后的节点信息。对于node2类型的struct,其也有两种类型的数据,一个是index,用来指示当前节点在之前数组的下标,还有一个就是nextadj,用来指向下一个以数组元素为箭头尾部的节点。具体如下边的代码。
    同时还需要注意的一点就是,对于无向图的存储,我们使用邻接表存储的话,对其求边数,每个边数都统计了两遍的,最后得出的结果是要除以2才是真实的边数。
    注释:由于我们使用的是邻接表存储图结构,每次输出拓扑排序的都是本邻接表所对应的拓扑排序。而图的邻接表可能有多种。对于求拓扑排序会有影响,但是对于我们的这次判断是否是树,邻接表只需要能表示出是哪个图就ok了。

    struct node2 {
    	int index;//在数据数组中的下标,如果顶点编号从1开始,则index对应减1
    	node2* nextadj;//指向邻接表之后的节点
    	node2() {
    		index = -1;
    		nextadj = NULL;
    	}
    };
    
    struct node1 {
    	int data;//具体顶点值
    	node2* firstadj;//指向第一个节点
    	node1() {
    		firstadj = NULL;
    		data = -1;
    	}
    };
    

    对应到代码中就是我写的两个函数,一个创建顶点,一个创建边,大家仔细读一读就可以看懂,我就不过多叙述了。

    	void create_ver();//创建图顶点信息
    	void create_edge(int k, int length);//创建边信息
    

    三、测试数据
    1.第一个给出一个树来判断
    在这里插入图片描述
    判断结果如下:
    在这里插入图片描述
    2.再给出一个不是树的图
    在这里插入图片描述
    判断结果如下:
    在这里插入图片描述

    四、源代码
    上述测试的两个图代码我都写在了下面。只需要将注释的改一改就可以了

    #include<iostream>
    #define v 6//V为定义的顶点数目
    //#define v 7//V为定义的顶点数目
    using namespace std;
    struct node2 {
    	int index;//在数据数组中的下标,如果顶点编号从1开始,则index对应减1
    	node2* nextadj;//指向邻接表之后的节点
    	node2() {
    		index = -1;
    		nextadj = NULL;
    	}
    };
    
    struct node1 {
    	int data;//具体顶点值
    	node2* firstadj;//指向第一个节点
    	node1() {
    		firstadj = NULL;
    		data = -1;
    	}
    };
    
    //采用邻接表存储图
    class Graph {
    public:
    	Graph();
    	void create_ver();//创建图顶点信息
    	void create_edge(int k, int length);//创建边信息
    	void shuchu();//输出图的信息
    	bool istree();//判断是否是树,算法1
    	void DFS(int v0);//对图的遍历
    private:
    	node1 ver[v];//存储顶点信息
    	bool visited[v];//存储是否访问过的信息
    	int count;//遍历时记录边的个数
    };
    //构造函数
    Graph::Graph()
    {
    	for (int i = 0; i < v; i++)//初始化数据数组
    	{
    		ver[i].data = -1;
    		ver[i].firstadj =NULL ;
    	}
    	for (int i = 0; i < v; i++)//初始化标志数组
    		visited[i] = false;
    	count = 0;
    }
    
    void Graph::DFS(int v0)
    {
    	cout << ver[v0].data << " ";//访问第一个顶点
    	visited[v0] = true;//改变标志
    	node2* w = ver[v0].firstadj;//获得第一个邻接点
    	while (w!=NULL)//如果有的话,则进行下列判断
    	{
    		count++;//此处找到一条表
    		if (visited[w->index] != true)//如果没有访问过,则继续DFS
    			DFS(w->index);
    		w = w->nextadj;
    	}
    }
    
    bool Graph::istree()
    {
    	cout << "深度优先遍历的顺序为:";
    	DFS(0);//遍历整个图
    	count = count / 2;//除以2为真实边数
    	cout<<endl << "该图的边数为:" << count << endl;
    	if (count != v - 1)//树的边数应该为N-1
    		return false;
    	for (int i = 0; i < v; i++)    //即一次dfs没有访问完,此时应该为非连通图,故不是树
    		if (visited[i] == false)
    			return false;
    }
    
    void Graph::create_ver()
    {
    	cout << "请依序输入图的顶点信息:";
    	for (int i = 0; i < v; i++)
    	{
    		int x;
    		cin >> x;
    		ver[i].data = x;
    		ver[i].firstadj = NULL;
    	}
    }
    
    //K为顶点编号,length为以该顶点为箭头尾部的边的条数
    void Graph::create_edge(int k, int length)
    {
    	cout << "*****************************************" << endl;
    	int x;//需要连接的节点编号
    	node2* p = NULL;
    	cout << "请输入顶点" << k << "的边信息:" << endl;
    	for (int i = 0; i < length; i++)
    	{
    		if (i == 0)
    		{
    			cout << "请输入第1条边(编号大于1):";
    			cin >> x;
    			ver[k - 1].firstadj = new node2;
    			ver[k - 1].firstadj->index = x - 1;
    			p = ver[k - 1].firstadj;//p指向新建立的节点
    		}
    		else
    		{
    			cout << "请输入第" << i + 1 << "条边:";
    			cin >> x;
    			p->nextadj = new node2;
    			p->nextadj->index = x - 1;
    			p = p->nextadj;//p指向新建的节点
    		}
    	}
    	cout << "*****************************************" << endl;
    }
    
    void Graph::shuchu()
    {
    	cout << "*****************************************" << endl;
    	cout << "您所创建的图为:" << endl;
    	cout << "顶点为:" << endl;
    	for (int i = 0; i < v; i++)
    		cout << ver[i].data << " ";
    	cout << endl;
    	cout << "邻接链表结构为:" << endl;
    	for (int i = 0; i < v; i++)
    	{
    		cout << ver[i].data;
    		node2* p = ver[i].firstadj;
    		while (p != NULL)
    		{
    			cout << "→" << ver[p->index].data;
    			p = p->nextadj;
    		}
    		cout << endl;
    	}
    	cout << "*****************************************" << endl;
    }
    
    int main()
    {
    	Graph G;
    	//创建图
    	G.create_ver();
    	/*//边数为7的数的创建
    	//create_edge的形参一为图顶点的编号,形参2为以该顶点为箭头尾部的边数
    	G.create_edge(1, 1);
    	G.create_edge(2, 2);
    	G.create_edge(3, 4);
    	G.create_edge(4, 1);
    	G.create_edge(5, 1);
    	G.create_edge(6, 1);
    	G.create_edge(7, 2);*/
    
    	//边数为6的创建
    	G.create_edge(1, 2);
    	G.create_edge(2, 3);
    	G.create_edge(3, 3);
    	G.create_edge(4, 3);
    	G.create_edge(5, 3);
    	G.create_edge(6, 2);
    	//判断是否是树
    	
    	G.shuchu();
    	if (G.istree())
    		cout << "改图是树!!!";
    	else
    		cout << "该图不是树!!!";
    	return 0;
    }
    
  • 您还可以看一下 夏曹俊老师的C++实战精讲--商用软件中的C++工程开发技术实践课程中的 临时对象的构建:对象构建空间性能构建中的开销问题小节, 巩固相关知识点