首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >个人财务管理工具

个人财务管理工具
EN

Code Review用户
提问于 2019-12-05 16:29:09
回答 2查看 277关注 0票数 5

我正在寻找关于这个个人理财工具的反馈。我想知道什么是我做得好,哪些不是很好。请不要批评我使用匈牙利符号的事实,这是我的大学作业所要求的,我知道我可能应该使用课程,但目前我只是坚持程序性的方法。

一家信誉良好的银行要求您创建一个个人财务管理程序。该程序将需要能够获取用户的月工资,他们的每月账单,以及任何可能发生的每周账单。然后,我们将对这些数据进行细分,找出他们的工资中有多少是留给储蓄的。用户应该能够输入任何金额的每月帐单和每周帐单。用户还可以选择在计算中添加家中的其他用户。一旦将所有相关信息都包括在内,就应该根据每周、每月和每年的成本对账单进行概述。输入

  • 用户名(必须大于1)
  • 月工资(必须超过1)
  • 用户必须支付的不同账单(每人)

输出

  • 用户姓名
  • 周、月、年工资总额
  • 每周、每月、年度票据共计
  • 在法案上的支出总额
  • 左转储蓄共计
  • 超过和低于可以节省的总数的10%
  • 每月能省多少钱?
  • 超过和低于每月可节省的总额的10%

代码

Personal Finance Management.cpp

此文件包含main函数。程序执行在那里开始和结束。

代码语言:javascript
复制
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
using namespace std;

void Addusers(vector<string>&sUserName)
{
    string sUserNameInput = "";
    cout << "\nEnter the name of household member: ";
    cin >> sUserNameInput;
    sUserName.push_back(sUserNameInput);
}
void AddMonthlyWage(vector<string>&sUserName,vector<double> &dMonthlyWage)
{
    double dInputMonthlyWage = 0;
    cout << "\n" << *sUserName.rbegin() << "'s monthly income: ";
    cin >> dInputMonthlyWage;
    dMonthlyWage.push_back(dInputMonthlyWage);
}

void YearlyAmount(vector<double>&dYearlySalary,vector<double>&dMonthlyWage, vector<string>&sUserName)
{
    double dYearlySalaryProcess = 0;
    dYearlySalaryProcess = *dMonthlyWage.rbegin() * 12;
    dYearlySalary.push_back(dYearlySalaryProcess);
}

void WeeklyAmount(vector<double>&dYearlySalary, vector<double>&dWeeklySalary, vector<string>&sUserName)
{
    double dWeeklySalaryProcess = 0;
    for (int iCount = 0; iCount != sUserName.size(); iCount++)
    {
    dWeeklySalaryProcess = (*dYearlySalary.rbegin() / 12) / 4;
    dWeeklySalary.push_back(dWeeklySalaryProcess);
    }
}

double dCalculateBillAmounts(double dYearlySalary,const double dIncomeTax, double dWaterBill, double dElectricityBill)
{
    double dTotalBillProcess = 0;
    dTotalBillProcess = (dYearlySalary * dIncomeTax) + dWaterBill + dElectricityBill;
    return dTotalBillProcess;
}

void BillAmounts(vector<double> &dYearlySalary, vector<string>&sUserName, vector<double>&dTotalBill)
{
    const double dIncomeTax = 0.1;
    vector<double> dWaterBill;
    vector<double> dElectricityBill;
    double dTotalBillProcess = 0;
    double dInputBill = 0;
    
    cout << "\nPlease enter " << *sUserName.rbegin() << "'s water bill: ";
    cin >> dInputBill;
    dWaterBill.push_back(dInputBill);
        

    cout << "\nPlease enter " << *sUserName.rbegin() << "'s electricity bill: ";
    cin >> dInputBill;
    dElectricityBill.push_back(dInputBill);
    
    dTotalBillProcess = dCalculateBillAmounts(*dYearlySalary.rbegin(), dIncomeTax, *dWaterBill.rbegin(), *dElectricityBill.rbegin());
    dTotalBill.push_back(dTotalBillProcess);

}
double CalculateMonthly(double dAmount)
{
    double dCalculateMonthlyProcess = dAmount / 12;
    return dCalculateMonthlyProcess;
}
double CalculateWeekly(double dAmount)
{
    double dCalculateWeeklyProcess = dAmount / 54;
    return dCalculateWeeklyProcess;
}
double TotalOver(double dAmount, double dPercentage)
{
    double dPercentageUnder = dAmount + (dAmount * dPercentage);
    return dPercentageUnder;
}
double TotalUnder(double dAmount, double dPercentage)
{
    double dPercentageOver = dAmount - (dAmount * dPercentage);
    return dPercentageOver;
}

void DisplayResults(vector<string> &sUserName, vector<double> &dMonthlyWage, vector<double> &dTotalBill, vector<double> &dYearlySalary,vector<double> &dWeeklySalary)
{
    vector<double> dTotalSavings;
    double dTotalSavingsProcess = 0;
    double dSavingsOverProcess = 0;
    double dSavingsUnderProcess = 0;
    vector<double> dSavingsOverPercentage;
    vector<double> dSavingsUnderPercentage;
    const double dPercentage = 0.1;
    
    vector<double> dBillsOverPercentage;
    vector<double> dBillsUnderPercentage;
    double dBillsOverProcess = 0;
    double dBillsUnderProcess = 0;
    
    for (int iCount = 0; iCount != sUserName.size(); iCount++)
    {
        cout << "\nResults for - " << sUserName.at(iCount) << ".";
        cout << "\n--Salary--";
        cout << "\nYearly salary is: £" << dYearlySalary.at(iCount) << ".";
        cout << "\nMonthly salary: £" << dMonthlyWage.at(iCount) << ".";
        cout << "\nWeekly salary is: £" << dWeeklySalary.at(iCount) << ".";
        cout << "\n--Bills--";
        cout << "\nTotal spent on bills: £" << dTotalBill.at(iCount) << ".";
        cout << "\nMonthly bill cost: £" << CalculateMonthly(dTotalBill.at(iCount)) << ".";
        cout << "\nWeekly bill cost: £" << CalculateWeekly(dTotalBill.at(iCount)) << ".";
        
        cout << "\n--Savings over and under 10%--";
        dTotalSavingsProcess = dYearlySalary.at(iCount) - dTotalBill.at(iCount);
        dTotalSavings.push_back(dTotalSavingsProcess);
        cout << "\nTotal savings: £" << dTotalSavings.at(iCount);
        
        dSavingsOverProcess = TotalOver(dTotalSavings.at(iCount), dPercentage);
        dSavingsOverPercentage.push_back(dSavingsOverProcess);
        cout << "\n" << dPercentage * 100 << "% over their total savings: £" << dSavingsOverPercentage.at(iCount);
        
        dSavingsUnderProcess = TotalUnder(dTotalSavings.at(iCount),dPercentage);
        dSavingsUnderPercentage.push_back(dSavingsUnderProcess);
        cout << "\n" << dPercentage * 100 << "% under their total savings: £" << dSavingsUnderPercentage.at(iCount);
        cout << "\n--Bills over and under 10%--";
        dBillsOverProcess = TotalOver(dTotalBill.at(iCount), dPercentage);
        dBillsOverPercentage.push_back(dBillsOverProcess);
        cout << "\n" << dPercentage * 100 << "% over their total bills: £" << dBillsOverPercentage.at(iCount);
        
        dBillsUnderProcess = TotalUnder(dTotalBill.at(iCount),dPercentage);
        dBillsUnderPercentage.push_back(dBillsUnderProcess);
        cout << "\n" << dPercentage * 100 << "% under their total bills: £" << dBillsUnderPercentage.at(iCount);
        cout << "\n";
    }
}

void ContinueOptions(bool &bExit)
{
    char cSelection = 0;
    cout << "Do you wish to add another family member? (Y/N) ";
    cin >> cSelection;
    cSelection = toupper(cSelection);
    if(cSelection == 'Y')
    {
        cout << "\nAdd a new family member";
    }
    else
    {
        cout << "\nGoodbye!";
        bExit = true;
    }
}
int main()
{
    vector<string>sUserName;
    vector<double>dMonthlyWage;
    vector<double>dYearlySalary;
    vector<double>dWeeklySalary;
    vector<double>dTotalBills;
    bool bExit = false;
    do
    {
        //Procedure 1
        Addusers(sUserName);
        //Procedure 2
        AddMonthlyWage(sUserName,dMonthlyWage);
        //Procedure 3
        YearlyAmount(dYearlySalary,dMonthlyWage, sUserName);
        //Procedure 4
        WeeklyAmount(dYearlySalary,dWeeklySalary, sUserName);
        //Procedure 5
        BillAmounts(dYearlySalary,sUserName,dTotalBills);
        //Procedure 6
        DisplayResults(sUserName, dMonthlyWage,dTotalBills,dYearlySalary,dWeeklySalary);
        //Procedure 7
        ContinueOptions(bExit);
    }while(bExit == false);
    cout << "\n";
}
EN

回答 2

Code Review用户

回答已采纳

发布于 2019-12-05 18:31:15

避免using namespace std

这不是为大量导入全局命名空间而设计的名称空间之一。这样的using指令剥夺了名称空间带来的好处。

总是检查您的输入

看到问题了吗?

cin >> sUserNameInput;sUserName.push_back(sUserNameInput);

如果>>运算符失败,sUserNameInput仍将为空。但是要求必须大于1(大概意味着名称长度),所以我们失败了。

始终检查>>是否成功,或者通过测试流(它有到bool的转换),或者通过设置它来抛出异常(然后适当地处理异常)。

对我们没有更改的引用参数使用const

例如,YearlyAmount()只需要读取dMonthlyWage,而不是修改它,并且根本不使用sUserName

代码语言:javascript
复制
void YearlyAmount(std::vector<double>& dYearlySalary,
                  std::vector<double> const& dMonthlyWage,
                  std::vector<string>&)

我们应该把没用过的人移走。

访问最后一个元素的

std::vector()提供back()作为编写*v.rbegin()的一种更方便的方式。

线以\n

结尾

我们需要在每一行的末尾,而不是在它的开头打印\n

std::toupper()采用int

字符转换函数的参数采用字符的无符号值,表示为int。在推广到unsigned char之前,我们需要将其转换为int,以避免传递负值。

宁愿返回值,也不愿写入引用.

ContinueOptions只有一个返回值,所以返回它。看看这有多清楚:

bool bExit = false;do {.ContinueOptions(bExit);}while(bExit == false);

这就变成:

代码语言:javascript
复制
do
{
    ...
} while(ContinueOptions());

它有这样的功能:

代码语言:javascript
复制
bool ContinueOptions()
{
    std::cout << "Do you wish to add another family member? (y/N) ";
    char cSelection;
    std::cin >> cSelection;
    if (!std::cin) {
        // input failed - assume "no"
        return false;
    }
    bool go_again = std::toupper(static_cast<unsigned char>(cSelection)) == 'Y';
    std::cout << (go_again ? "Add a new family member\n" : "Goodbye!\n");
    return go_again;
}
票数 5
EN

Code Review用户

发布于 2019-12-05 18:38:47

复杂性

代码在遵循单一责任原则状态方面做得很好:

每个模块、类或函数都应该对软件提供的功能的单个部分负责,而该责任应该完全由该模块、类或函数封装。

这方面的例外是函数DisplayResults(),它太复杂了(在一个函数中做的太多了)。根据函数的名称,它应该做一件事情,即显示结果。

Addusers()函数应该负责调用所有函数来添加用户信息,应该有一个新的函数调用AddUserName()

如果用户是类,那么许多函数将需要较少的参数,这将大大简化实现。

calculate函数中,代码可以简单地返回计算,而不是将其分配给变量,然后返回变量。可以将这些函数编写为lambda表达式而不是函数。

避免using namespace std

如果您是专业编写代码的,您可能应该戒掉使用using namespace std;语句的习惯。代码将更清楚地定义cout和其他标识符来自何处(std::cinstd::cout)。当您开始在代码中使用名称空间时,最好确定每个函数的来源,因为可能会有来自不同名称空间的函数名称冲突。您可以在您自己的类中重写标识符cout,也可以在您自己的类中覆盖运算符<<。本堆栈溢出问题将对此进行更详细的讨论。

无用注释

main()中对表单//Procedure N的注释实际上无助于解释任何事情。注释应该用来解释为什么代码可能在做程序员无法通过阅读自文档代码来推断的事情。给定程序中的函数和变量名,这段代码是自记录代码。

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/233480

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档