网吧计费管理系统开发历程与源码分享(武汉理工大学程序设计综合实验课程设计)

那么,就让我们来谈一谈这个计费管理系统吧!一开始,我就充满了激情和热情,准备写出一份完美无缺的代码。不过,事情往往不是那么容易的,我很快就发现了一些困难。

首先,添加卡的功能是比较简单的,只需要在数据库中新增一条记录即可。不过,查询卡的功能就比较复杂了,因为用户可能会输入精准的卡号,也可能只输入一部分。为了解决这个问题,我决定采用模糊查询的方式,让用户输入的关键字与数据库中所有的卡号进行匹配,然后返回所有匹配到的结果。这样一来,就可以同时满足用户的需求了。

另外,激活、注销、挂失、上机、下机等功能也都比较好实现。其中,上机和下机的时候需要统计费用,还要随机打折优惠,这个我觉得可以用一个算法来实现。不过,如果用户欠费了,就需要处理异常情况了。这个时候,我决定将欠费的用户记录到黑名单中,以便以后做出相应的处理。

退费和转账这两个功能也比较简单,只需要在数据库中做出相应的修改即可。展示卡信息、删除卡、查询统计营业额这些功能也不难实现。最后,管理员设计和聊天室设计,我觉得可以考虑使用一些现有的开源库来实现。

不过,编写这个计费管理系统还是有一些困难的。比如,我在处理异常情况的时候,遇到了一些棘手的问题。我一开始是想将欠费的用户直接从数据库中删除,但是后来发现这样会对数据的完整性造成一定的影响。所以,我决定将欠费的用户记录到黑名单中,并对黑名单进行特殊处理,这样可以保证数据的完整性。

还有,当用户输入模糊关键字的时候,需要使用模糊匹配算法来查询数据库,这个算法也不是那么好实现。我调研了一下,发现可以使用正则表达式来实现模糊匹配。不过,正则表达式的语法比较复杂,需要花费一些时间来学习和理解。

在编写过程中,我也学到了很多东西,比如如何优化算法,如何处理异常情况,如何提高代码的可读性和可维护性等等。我觉得,编写这个计费管理系统的关键是要有耐心和毅力,不怕遇到问题,敢于尝试各种不同的方法。同时,也要善于利用现有的资源,比如开源库、论坛、博客等等,以便更好地解决问题。

编程语言的选择

当初为什么选择用C++而不是C语言开发这个系统?毕竟那老掉牙的经典视频教程可是用纯C写的呀!

哈哈,这个问题好玩!当然,我选择用C++而不是C语言开发这个系统,主要是因为C++比C更加强大和灵活。

首先,C++可以支持面向对象的编程方式,这使得代码的组织和维护更加方便。与C语言相比,C++中的类和对象等概念可以更好地抽象现实世界的问题,使得代码更加易于理解和扩展。

其次,C++中还包含了许多有用的功能和库,比如STL和模板等。这些功能和库可以帮助我们更加高效地开发代码,减少出错的概率。

此外,C++也是一门被广泛使用的语言,拥有大量的开发人员和社区支持。这意味着在开发过程中,我们可以轻松地获取到各种教程、文档、工具等等,以便更好地完成开发任务。

当然,如果我只是要写一些简单的程序,也可以选择使用C语言。不过对于这个计费管理系统来说,我认为使用C++是更好的选择。毕竟,我们不仅要编写代码,还要关注系统的性能、可扩展性等等因素,这些都需要C++的强大能力来支持。使用C++而不是C语言开发这个计费管理系统,不仅是因为C++更加强大和灵活,也是因为它能够更好地满足我们的开发需求。

系统功能模块化

为什么将系统功能封装成不同的类来调用实现呢?

首先,我选择将系统功能封装成不同的类来调用实现,主要是为了实现代码的模块化和可维护性。通过将功能进行分离和封装,我们可以更好地管理代码,减少出错的概率,并且便于维护和升级。

其次,面向对象编程的一个重要思想就是“单一职责原则”。这意味着每个类应该只负责一项职责,以便代码更加清晰易懂。如果将所有的功能都放在一个类中实现,那么会导致代码臃肿,可读性差,不利于后续的开发和维护。

另外,使用类来封装功能,还可以使得代码更加灵活。如果我们需要添加新的功能或者修改某个功能的实现,只需要修改对应的类即可,不需要对其他代码进行大规模修改。这也使得整个开发过程更加高效和安全。

当然,作为一名懒惰又勤奋的程序员,我最大的愿望就是写尽可能少的代码。通过将功能封装成不同的类,我们可以避免重复编写代码,并且提高代码的复用率。这样一来,我们可以写更少的代码,但实现更多的功能,岂不美哉!

综上所述,我选择将系统功能封装成不同的类来调用实现,主要是为了实现代码的模块化和可维护性,以及使得代码更加灵活和高效。当然,还有一点点懒惰的想法,我相信这也是大多数程序员的共同心声吧!

模块调用的大致思路

首先,我想把整个系统分成三个主要的模块:计费管理模块、卡管理模块和聊天室模块。其中,计费管理模块负责统计每张卡的使用情况,卡管理模块负责管理每张卡的信息和状态,聊天室模块负责实现聊天功能。

接下来,我发现计费管理模块和卡管理模块是高度相关的,因为每张卡的使用情况都需要记录在卡的信息中,所以我决定将这两个模块合并成一个模块,并且将其实现为一个名为“BillingSystem”的类。

而“Card”类则是用来表示每张卡的信息和状态的,例如卡号、姓名、余额等等。在“BillingSystem”类中,我通过维护一个“Card”类的vector来实现卡的增删查改等功能。

为了使代码更加清晰易懂,我还创建了一个名为“Card_Service”的类,用于封装一些与卡相关的服务功能,例如卡的充值、退款、上机、下机等等。

最后,我实现了一个名为“ChattingRoom”的类,用于实现聊天室的功能。这个类通过调用函数接口,实现了多个用户之间的聊天功能,让用户可以更好地交流和互动。

我的分模块思路具体就是先将整个系统分成三个主要模块,然后根据模块之间的关系将计费管理模块和卡管理模块合并为一个模块,并通过创建“Card”和“Card_Service”类来实现相关功能,最后实现聊天室模块。我相信,通过这样的模块化设计,我们可以更好地管理代码,提高代码的可维护性和复用性,并且使得开发过程更加愉快和高效!

文件的读写操作

首先,文件的存取可以帮助我们在程序结束之后将数据保存到本地,从而保证数据不会因为程序的关闭而丢失。例如,在我们的计费管理系统中,我们需要记录每张卡的使用情况、余额等信息,如果不进行文件存取,这些信息只能在程序运行期间保存在内存中,一旦程序结束,这些信息就会丢失。

其次,文件的存取也可以帮助我们在程序启动时从文件中读取之前保存的数据,从而恢复程序上次关闭时的状态。这对于用户来说是非常方便的,因为他们不需要每次都重新输入卡的信息或者从头开始聊天,可以直接接着上次的操作进行。

如果我们不实现文件的存取,那么程序每次启动时都需要用户重新输入之前的数据,这不仅浪费用户的时间,而且也可能会因为输入错误等原因导致数据丢失,影响用户体验。

文件的存取非常重要,可以帮助我们保护数据,恢复程序状态,提高用户体验。如果不进行文件存取,我们就可能会面临数据丢失、用户体验不佳等问题,这是我们不想看到的。

主函数的设计

啊,这个main函数啊,是这个系统的大脑啊。它调用了BillingSystem、ChattingRoom、UserMenu、Card_Service四个类来实现各种功能。哎呀,感觉我就像是一个神奇的调度员啊,让各个模块一起协作,才能让这个系统运转起来。

要说难点和头疼的地方嘛,那就是文件的保存和读取啊。这个系统的各种信息都需要保存在文件中,可是一不小心就会出错啊。你说我要是给你看这个main函数一堆读取和保存文件的代码,你会不会吓得跑路啊?所以啊,我就想到了把这个麻烦的事情交给BillingSystem这个类去做。这样就可以让代码更加简洁明了,让我这个调度员更加从容自信了。

至于这个系统的其他模块嘛,其实也都是有很明确的功能的。BillingSystem就是负责卡片的管理,ChattingRoom就是实现了聊天室的功能,UserMenu就是显示菜单和接收用户输入,Card_Service则是提供了一些卡片的服务。把这些功能都分开来,不仅可以让代码更加清晰,也更加方便维护和修改。

说到开发难点,我倒觉得是实现卡片之间的转账功能啊。这个功能看起来简单,但其实牵涉到了卡片余额的修改,还要涉及到密码验证、账户检查等等。所以,我就设计了一个transferBalance的函数,让它能够自动处理这些问题。这样,用户就可以轻松愉快地完成卡片之间的转账啦!

Main.cpp

#include <iostream> // 这个是用来输入输出的头文件,cin和cout就在里面
using namespace std; // 哦,不用自己敲std::cout了,自动给你加上std::

#include "BillingSystem.h" // 自己写的类
#include "ChattingRoom.h" // 还有一个
#include "UserMenu.h" // 我们还要写一个菜单,因为我们的用户太懒了,不愿意记住数字

#include "Card_Service.h" // 这个又是干嘛的呢?谁知道呢。。。因为我懒得看了

int main() {
    BillingSystem billingSystem; // 实例化一个计费系统,这个系统可以让你随心所欲的花钱

    double costPerMinute = 0.1; // 一分钟多少钱?这个可以自己随便定,反正不是你的钱

    int choice; // 一个整数,记录用户的选择,很重要,要好好珍惜

    //测试段
    BillingSystem bs; // 另外一个计费系统
    bs.addCard("123456", "John Doe", (string &) "password"); // 给这个系统加上一些卡号和密码,不知道这些密码是不是"password"
    bs.addCard("789012", "Jane Due", (string &) "password");
    bs.addCard("345678", "John Dmith", (string &) "password");
    bs.addCard("367548", "John Smith", (string &) "password");

    vector<Card*> mCards = bs.findCardsByIdSubstring("D"); // 这个是在查找名字里有"D"的卡号
    for (Card*& card : mCards) {
        cout << card->getId() << " " << card->getName() << "\n"; // 输出卡号和名字,嗯,很好,看起来有很多朋友啊
    }

    while (true) { // 循环一下,因为我们想不断的让用户花钱啊

        printMenu(); // 调用这个函数,输出一个菜单,让用户选择他想干嘛

        cin >> choice; // 让用户输入他的选择,我们会把这个记录下来,等等会用到

        string id, name, password; // 一些字符串变量,用来存储一些信息
        double amount; // 还有一个浮点数,存储钱的数量
        Card* card; // 这个是个指针,指向一张卡

        vector<Card> cards; // 一个卡的集合,是不是很有趣?

        switch (choice) { // 根据用户的选择,我们来执行不同的操作

            case 1:
                cout << "Enter card ID: ";
                cin >> id;
                cout << "Enter card holder's name: ";
                cin.ignore();
                getline(cin, name);
                cout << "Enter card holder's password: ";
                getline(cin, password);

                // 添加卡片,这里其实是暗示你:好像是我自己的钱似的,反正是我要管这些卡
                billingSystem.addCard(id, name, password);
                cout << "Card added successfully!\n";
                break;

           case 2: {
                cout << "1. Precise Query 2. Blurry Query" << endl;
                cout << "Which One? ";
                int queryChoice;
                cin >> queryChoice;
                cout << "Enter card ID: ";
                cin >> id;

                switch (queryChoice) {
                    case 1:
                    // 查找一张卡片(ID精确匹配),这里其实是暗示你:找出谁欠我钱了
                        card = billingSystem.findCard(id);
                        if (card) {
                            cout << "Card found!\n";
                            printCard(card);
                        } else {
                            cout << "Card not found!\n";
                        }
                    break;
                case 2:
                   // 查找卡片(ID模糊匹配),这里其实是暗示你:谁还欠我钱呢?
                        vector<Card *> matchingCards = billingSystem.findCardsByIdSubstring(id);
                    if (!matchingCards.empty()) {
                        cout << "Cards found!\n";
                        printAllCards(matchingCards);
                    } else {
                        cout << "Cards not found!\n";
                    break;
                    }
            break;

        case 3:
            cout << "Enter card ID: ";
            cin >> id;
            // 激活卡片,这里其实是暗示你:收钱收到手软了,我要给这些钱找个家
            if (billingSystem.activateCard(id)) {
                 cout << "Card activated successfully!\n";
            } else {
                cout << "Card activation failed!\n";
            }
            break;

        case 4:
            cout << "Enter card ID: ";
            cin >> id;
            cout << "Enter card Password: ";
            cin>> password;
            card = billingSystem.findCard(id);
            if (card && billingSystem.checkPassword(card,password) &&             billingSystem.rechargeCard(card)) {
            // 给卡片充值,这里其实是暗示你:收钱收到手软了,我要给这些钱找个家
            cout << "Card recharged successfully!\n";
            } else {
            // 充值失败,这里其实是暗示你:他欠我钱,结果连还钱的本事都没有
            cout << "Recharge failed!\n";
            }
            break;
        case 5:
            cout << "Enter card ID: ";
            cin >> id;
            cout << "Enter card Password: ";
            cin >> password;
            cout << "Enter refund amount: ";
            cin >> amount;
            // 退款嘛,有钱就是任性,没钱就是调皮。先输入卡号,再输密码,最后输入退款金额。注意:一定要输正整数,不能输小数,否则可能被误认为刻意设置的Bug。
            card = billingSystem.findCard(id);
            // 先判断卡片是否存在,再判断密码是否正确,最后进行退款操作
            if (card && billingSystem.checkPassword(card, password) && billingSystem.refund(card, amount)) {
// 这里有个小技巧,先用findCard函数查找卡片是否存在,再用checkPassword函数检查密码是否正确,最后进行退款操作。没必要重复发明轮子。
            cout << "Refund successful!\n";// 如果退款成功,就输出“Refund successful!”,反之输出“Refund failed!”。切记,千万别把成功和失败的输出颠倒了。
            } else {
            cout << "Refund failed!\n";
            }
            break;

       case 6:
            cout << "Enter card ID: ";
            cin >> id;
            cout << "Enter card password: ";
            cin >> password;

            //首先,我们需要找到目标卡。如果我们找到了它,并且会话成功开始、密码校验通过以及验证码也正确,那么我们就可以说“Session started successfully(会话成功开始)!”。
            if (billingSystem.findCard(id)&& billingSystem.startCardSession(card)&&
            billingSystem.checkPassword(card,password)&&
    billingSystem.checkVerificationCode()) {
            // 若卡被找到,并且会话开始、密码校验通过且验证码也正确
        cout << "Session started successfully!\n";
    } else {
           // 哦,如果找不到目标卡,或者会话没有成功开始,或者密码校验不通过,或者验证码不正确,我们会输出“Failed to start session(会话开始失败)!”。
            cout << "Failed to start session!\n";
    }
            break;

        case 7:
            cout << "Enter card ID: ";
            cin >> id;
             //我们处理的是结束卡片的会话。这个操作的难点在于如何将会话记录存储在系统中以供后续使用,而且我们还需要计算出本次会话的费用。
            card = billingSystem.findCard(id);
            //调用了BillingSystem的endCardSession()方法来结束会话,并传递了记录、每分钟的通话费用等参数。
            if (card && billingSystem.endCardSession(card, billingSystem.getRecords(), 0.1)) {

            cout << "Session ended successfully!\n";
            } else {
            cout << "Failed to end session!\n";
            }
            break;

        case 8:
            cout << "Enter card ID: ";
            cin >> id;
            card = billingSystem.findCard(id);
            if (card) {
                card->cancel();
                cout << "Card canceled successfully!\n";
                } else {
                cout << "Failed to cancel card!\n";
                }
            break;


        case 9:
            cout << "Enter card ID: ";
            cin >> id;
            cout << "Enter card Password: ";
            cin >> password;
            card = billingSystem.findCard(id);
            if (card && billingSystem.checkPassword(card, password)) {
                if (billingSystem.isInBlacklist(card->getName())) {
                    cout << "Cannot operate with this card as its owner is in the blacklist. Contact the manager!\n" << endl;
                break;
            }
            card->lost();
            cout << "Card reported as lost successfully!\n";
            } else {
            cout << "Failed to report card as lost!\n";
            }
          break;
        case 10:
            cout << "Enter card ID: ";
            cin >> id;
            cout << "Enter card Password: ";
            cin>> password;
            card = billingSystem.findCard(id);
            if (card&&billingSystem.checkPassword(card,password)) {
                if(billingSystem.isInBlacklist(card->getName())){
                    cout<<"Cannot operate with this card as its owner is in the blacklist.Contact the manager!\n"<<endl;
                    break;
                }
                card->lost();
                cout << "Card reported as lost successfully!\n";
            } else {
                cout << "Failed to report card as lost!\n";
            }
            break;

        // “Case 10, 如果你的卡丢了,可以在这里挂失。如果你不是你,但你试图挂失,那么你就像是一只企图跳过一只蜜蜂的兔子,最终会被抓住的。”

         case 11:
            deleteAllCards();
            break;

        // "Case 11, 通过删除所有卡片来清空所有记录。这就像是打开电视机,但是你没开机,而是直接把电视砸了,这样你就解决了你的问题,但是你也不再有电视了。"

         case 12:
             printAllCards();
             break;

        // “Case 12, 打印所有的卡片信息。这就像是在拿着万能胶水尝试修复踏板的电梯,但实际上你只是将踏板粘在了地上,让所有的乘客都能踩在它上面。”

         case 13:
            billingSystem.queryRecords();
            break;

        // “Case 13, 查询所有的通话记录,就像是探索无人区,但是你不知道在那里会发生什么,或者是否能够幸存下来。”

        case 14:
            billingSystem.loginAdmin();
            break;

        // “Case 
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值