来自数据集的银行帐户结构输出(这是一项任务)

时间:2014-03-30 14:18:15

标签: c++

我被要求建立以下内容。在这个阶段,我只能编写相应的.h文件的任务,不幸的是,尽管经过数小时的研究,并且由于成为远程教育学生的困境,我的老师不给我帮助。我不确定这些.h结构是否正确,我不确定从哪里开始创建函数。你能告诉我我的.h文件是否正确你能告诉我如何创建这个.h文件相应的功能吗?

  • 包含三个成员的Customer结构(在头文件Customer.h中定义): 客户名称,用户ID和PIN。

    #ifndef CUSTOMER_H
    #define CUSTOMER_H
    using namespace std;
    
    struct customer
    {
        std::string name;
        std::string pin;
        std::string user_id
    };
    
  • 创建客户的函数CreateCustomer()。它有三个参数来初始化结构的每个成员(客户名称,用户ID和PinNumber)。所有参数都应具有默认参数空白值。原型: Customer * CreateCustomer(const string& name,const string& id,const string& pin)

  

Customer * CreateCustomer(const string& name,const string& id,const string& pin){       返回新客户{name,id,pin};

  • 包含三个成员的事务结构(在头文件Transaction.h中定义):Transaction Date,Description和Amount。金额不能为负值。

      

    // .h文件

    struct Transaction 
    {
        std::string date;
        std::string description;
        double amount;
    };
    
  • 创建Transaction的函数CreateTransaction()。它有三个参数来初始化结构的每个成员(交易日期,描述和金额)。所有参数都应具有默认参数值。日期设置为“01/01/2014”,描述为空白,金额为零。原型: Transaction * CreateTransaction(const string& date,const string& description,const double& amount))

    transaction* CreateTransaction(const string& date, const string& description, const double& amount) {return new transaction { date, description, amount};
    
  • 包含七个成员的帐户结构(在头文件Account.h中定义): 帐户持有人,数量,余额,总存款,提款总额,交易清单数组 现有交易记录中最多100条记录和交易计数。

    // the .h file 
    struct Account 
      {
        Customer customer;
        int number;
        double balance, total_deposit, total_withdrawal}    
    
  • 创建帐户的函数CreateAccount()。它有六个参数来初始化结构的每个适当的成员。 date参数用于为Transaction List数组创建第一个事务,描述是来自balance参数的Opening balance。因此,在创建帐户后,应将事务计数设置为1。来自第三个参数的所有参数都应具有默认参数值。日期设置为“01/01/2014”,余额,存款和取款设置为零值。原型:

      

    帐户* CreateAccount(const Customer& customer,const std :: string&   openingDate =“01/01/2014”,const double& openingBalance = 0,const   双&安培;存款= 0,const double&撤回= 0);

考虑到上述情况我已经获得了一个数据集,其想法是它曾经有一个特定的输出,他们的代码提供了我的作业表粘贴在下面

> Provided Code - main() int main() { Customer* Mary =
> CreateCustomer("Mary Jones", "235718", "5074"); Customer* John =
> CreateCustomer("John Smith", "375864", "3251"); Account* MaryAccount =
> CreateAccount(*Mary, "06-3121-10212357", "01/03/2014", 100); Account*
> JohnAccount = CreateAccount(*John, "06-3121-10213758", "10/03/2014");
> RecordWithdraw(MaryAccount, CreateTransaction("01/03/2014", "ATM
> Withdrawal", 50) ); RecordDeposit(MaryAccount,
> CreateTransaction("02/03/2014", "Deposit", 90) );
> RecordWithdraw(MaryAccount, CreateTransaction("04/03/2014", "ATM
> Withdrawal", 150) ); RecordDeposit(MaryAccount,
> CreateTransaction("05/03/2014", "Deposit", 20) );
> RecordWithdraw(MaryAccount, CreateTransaction("05/03/2014",
> "Withdraw", 100) ); RecordWithdraw(MaryAccount,
> CreateTransaction("05/03/2014", "Withdraw", 50) );
> RecordDeposit(JohnAccount, CreateTransaction("11/03/2014", "Deposit",
> 20) ); RecordDeposit(JohnAccount, CreateTransaction("12/03/2014",
> "Deposit", 80) ); RecordWithdraw(JohnAccount,
> CreateTransaction("12/03/2014", "Withdraw", 50) );
> PrintReport(MaryAccount); PrintReport(JohnAccount); return 0; }

2 个答案:

答案 0 :(得分:2)

如果我以前的评论冒犯了你,我很抱歉。我想要推荐的是学习你可能在课堂上遗漏的语言的基础知识。

我将在这里总结一下要点,让你重温记忆:

包括警卫

他们的目的是阻止程序包含多个定义。他们的通用语法如下:

#ifndef X
#define X

    ...

#endif

这样做是为了在首次包含文件时,ifndef X将“评估”到预处理器中的true,并输入ifndef的正文(正文结束) #endif结束的地方)。正文应该做的第一件事是定义X,以便下次包含文件时,ifndef将“评估”到预处理器中的false,并将“跳过”包含的定义在体内。

标识符X当然应该对每个文件都是唯一的。

using namespace指令

如果包含<string>(请注意标题不应包含.h),则应包含string命名空间中定义的std类。现在你有两个选择:

  1. 请参阅std::string
  2. 的课程
  3. 使用std导入using namespace std;命名空间,并能够使用string
  4. 引用该课程

    这首先被认为是更好的,但在学术环境中,第二个主要是使用。只需选择一种方法并坚持下去。

    其他小事

    std Transaction[]
    

    没有任何意义。每个声明/声明都应以分号(;)结尾,并且您已在程序的其他部分中执行此操作。

    客户结构

    您的客户结构应包含:

    • 名称
    • 用户ID

    名称可以用字符串表示,因此我会使用std::string。使用的ID和引脚看起来像数字值,因此我可能会使用int两者,导致结构为:

    struct Customer
    {
        std::string name;
        int pin;
        int user_id;
    };
    

    函数CreateCustomer

    这是分配:

      

    创建Customer的函数CreateCustomer()。它有三个参数来初始化结构的每个成员(Customer Name,User ID和PinNumber)。所有参数都应具有默认参数空白值。

         

    原型:Customer* CreateCustomer(const string& name, const string& id, const string& pin)

    从回归类型来看,我实际上害怕作业要求你做什么。他可能会要求你返回一个动态分配的对象,这是非常糟糕的做法。但只是为了分配,这很简单,您可以这样做:

    Customer* CreateCustomer(const string& name, const string& id, const string& pin) {
        return new Customer { name, id, pin };
    }
    

    没有太多可以解释的。这是动态分配的内存,你应该记得以后再delete。 “动态记忆”的主题肯定太长了,不能在这里解释清楚,只需阅读你解释它的书的章节。

    Transaction结构

    你为这个绘制的草图实际上非常准确。描述和日期均为std::string,金额为double。唯一的问题是你不应该担心在名称前加Transaction前缀,因为它们是Transaction结构的本地代码:

    struct Transaction {
        std::string date;
        std::string description;
        double amount;
    };
    

    CreateTransaction函数

    这与之前的CreateCustomer函数完全相同。既然我们有Transaction这应该是微不足道的。我会将此作为练习留给读者。

    Account

    作业要求:

    • 帐户持有人
    • 平衡
    • 总存款
    • 完全退出
    • 最多100条记录的交易数组
    • 现有交易记录的交易计数

    对于帐户持有人,我们提供了全新的Customer课程。对于该号码,我们可以再次使用int。对于balancetotal_deposittotal_withdrawal,我们可以使用double(处理资金时,需要浮点数来表示分数)。

    所以struct应该是这样的:

    struct Account {
        Customer customer;
        int number;
        double balance, total_deposit, total_withdrawal;
    

    现在对于阵列来说这会让人感到困惑。一方面看起来你的教授希望你使用一个C数组,另一方面(事务计数)似乎你应该更有活力。在我看来,您应该包含<vector>并使用std::vector。如果您还没有谈过矢量,可以使用数组:

        Transaction transactions[100];
    };
    

    令人困惑的CreateAccount

    这里的任务非常令人困惑,至少在我看来并且显然没有原型,但我确信你可以通过修改来解决问题:

    • for循环
    • 阵列
    • new

答案 1 :(得分:0)

根据@Jefffrey的回答,这里有一些我在你的程序中注意到的事情。

struct CUSTOMER_H
{
    std::string name[8];
    std::string pin;
    std::string Userid;
};

看起来你对基于字符的字符串和std::string之间的区别感到困惑。使用C样式的基于字符的字符串,可以创建char的数组。数组必须是固定大小的,你必须留下尾随空的最后一个元素\0,它标记字符串的结尾。所以在这种情况下,你可以这样做:

char name[8]; //this creates a character array with 8 elements numbered 0-7. You need to leave name[7] alone so it can hold the trailing \0, though, or you'll crash your program. So this can effectively hold a 7-character name.

但是,由于你在其他地方使用std::string,你可能也想在这里做。与基于字符的字符串不同,std::string是一个可变长度的字符串,它负责标记自己的结尾。你不需要在这里创建一个数组;刚

std::string name;

会做的。

  

包含三个成员的Transaction结构(在头文件Transaction.h中定义):Transaction Date,Description和Amount。金额不能为负值。

听起来,交易结构比数据容器更复杂:如果您确保数量永远不会消极,那么您需要使用 getters < / em>和 setters 。这些是简单的功能,旨在提供对分配给变量的内容的一些控制。他们的工作方式如下:

//Transaction.h: we're just declaring things here
struct Transaction
{
  //<snip>
  double getAmount();
  void setAmount(double newAmount);

private:
  double amount;
}

顾名思义,getAmount函数将返回amount中存储的值。 setAmount函数应检查以确保newAmount为正数,并且仅在amount为正数时才存储。private另外值得注意的是amount关键字:如果使用交易的任何人都可以直接查看和更改private变量,那么我们的特殊getter和setter对我们没有太大作用,因此amount让我们将它隐藏在Transaction类之外的任何东西中。这样,只有Transaction类中的代码才能更改//Transaction.cpp: we're actually implementing things here. Yey code! double Transaction::getAmount() //note that we prefix the method name with the class name and a double colon. This is required when you're creating a class method. { return amount; //short and sweet. We don't need to do anything special here, we're just letting outside code see the value of amount since they can't access it directly. } void Transaction::setAmount(double newAmount) { if (newAmount > 0) //this is why we're doing the whole getter-setter thing. Now we get to control what goes into amount: amount will only be updated if newAmount > 0. { amount = newAmount; } }

我怀疑你以前见过这些,所以我会为你写这些:

std::vector
  

包含七个成员的帐户结构(在头文件Account.h中定义):帐户持有人,数量,余额,总存款,总提款,最多100个记录的交易清单数组以及现有交易记录的交易计数。 / p>

@ Jefffrey在这里的答案非常好,所以你应该大部分都遵循它。我只想注意一件小事:交易清单/交易计数。 (好吧,两件小事。)

根据我在介绍级别课程中看到的内容,我还是愿意打赌你还没有覆盖struct Account { //<snip> Transaction transactions[100]; int transactionCount; } ,固定大小的数组要求支持这个理念。你的教授可能正在寻找的是一个C风格的交易数组,它有一个单独的交易计数器变量:

transactions

同样,请务必记住,transactionCount数组是通过索引0-99, 1-100访问的。因此,如果transactions[1]为2,并不意味着,您可以访问transactions[2]transactions[0]。您的代码将执行您不会感激的事情,包括返回垃圾值到可能崩溃。您想要transactions[1]std::int。另外,请勿使用int;只需将整数变量声明为//CreateAccount prototype: Account* CreateAccount(const Customer& customer, const std::string& openingDate = "01/01/2014", const double& openingBalance = 0, const double& deposit = 0, const double& withdraw = 0);

  

创建帐户的函数CreateAccount()。它有六个参数来初始化结构的每个适当的成员。 date参数用于为Transaction List数组创建第一个事务,描述是来自balance参数的Opening balance。因此,在创建帐户后,应将事务计数设置为1。来自第三个参数的所有参数都应具有默认参数值。日期设置为&#34; 01/01 / 2014&#34;,余额,存款和取款设置为零值。

这很令人困惑,但让我们试着将其分解。

的createAccount:

  • 创建帐户
  • 有六个参数,但只考虑日期,余额,存款和提款。基于一些直觉和您的Account结构的声明,缺少的参数之一可能是Customer对象。
    • 具有大多数参数的默认值
    • 做了一些设置工作

由于缺乏信息,此代码可能不完整或有些错误,但我会尽我所能处理您提供的内容。

Account*

首先,缺少一个参数。我不知道它是什么,所以我无法添加它;你需要这样做。

另请注意,我们正在返回Account - 指向帐户的指针。这是非常糟糕的主意,通常您只想返回= <value> - 这是一个普通的帐户对象,不会因为手动内存分配/释放而导致您头痛。不幸的是,这位教授似乎喜欢返回动态创建的对象,所以我们需要按照他的方式去做。 在没有充分理由的情况下,不要在实际代码中执行此操作。

最后,请注意= 0= "01/01/2014"CreateAccount) - 这是指定默认参数值的方式。调用CreateAccount的人将能够跳过这些参数,并且将使用我们在原型中指定的参数。或者他们可以调用//for the purposes of the next few lines of code, JoeCool is a valid Customer object that we've already set up using CreateCustomer. CreateAccount(JoeCool); //creates an account belonging to JoeCool. The opening date will be automatically set to 01/01/2014 and the balance, deposit and withdrawal will all be set to 0. CreateAccount(JoeCool, "09/10/14"); //creates an account belonging to JoeCool. The opening date will be set to 09/10/14, overriding our default date; however, since we didn't specify a balance, deposit, or withdrawal, they'll all be set to 0. CreateAccount(JoeCool, "12/11/15", 50, 100, 25); //creates an account belonging to JoeCool. We've overridden all our default parameters, so the opening date will be set to 12/11/15, the opening balance will be set to 50, the deposit will be set to 100, and the withdrawal will be set to 25. 并指定所有参数,我们的默认值将被覆盖。所以这三个调用都是有效的:

CreateAccount

我实际上会将此作为练习实施。但是,我认为您在执行此操作时需要记住一些一般概念。

  • 由于某种原因,代码被分解为函数。不要试图在CreateTransaction中做所有事情;将部分工作交给getTransactionCount
  • 不要忘记让您的交易数组与您的交易柜台保持同步。这可能会非常混乱;我建议尝试使用一些getter和setter类型方法,例如getTransaction(int index)(没有setter for this!事务计数将在内部递增,不需要任何外部代码来设置它),CreateTransaction,当然还有CreateTransaction。这样,getTransaction可以创建一个新的事务并增加事务计数器,getTransactionCount可以返回一个单独的事务项,而不是让外部代码访问您的完整事务数组,CreateTransaction可以使确保外部代码不会弄乱你的交易柜台。
  • 别忘了你的理智检查。是否有人试图提取比账户中更多的钱?顺便说一句,这就是为什么你想把大部分工作都传递给CreateTransaction的原因:你可以在一个地方编写健全性检查,然后让其余的代码使用它们,而不是必须检查一切到处。只需进行多笔交易来设置余额,然后存入任何东西,然后提取任何东西,让{{1}}决定主叫代码是否做了非法行为(负存款,负余额,提取大于余额)。