简体   繁体   English

C++ 赋值文件处理部分的问题

[英]Problem with file handling part of C++ assignment

This function is supposed to take care of updating the file after calling the respective functions for depositing or withdrawing from a user account.此函数应该负责在调用用于从用户帐户存款或取款的相应函数后更新文件。 But it fails to do just that.但它没有做到这一点。 I've checked as much as I can and all the other functions seem to be doing their jobs properly.我已经尽可能多地检查过,所有其他功能似乎都在正常工作。 I've traced it down to the specific lines where the program seems to fail.我已经将其追溯到程序似乎失败的特定行。

int pos = (-1) * static_cast<int>(sizeof(ac));
File.seekp(pos, ios::cur);

//File.write((char *)&ac, sizeof(BankAccount));
File.write(reinterpret_cast<char *>(&ac), sizeof(BankAccount));

Yes, these are two versions of the line because I don't fully understand how either of them work.是的,这是该行的两个版本,因为我不完全了解它们中的任何一个是如何工作的。 (First version is mine, second line is from a sample program we were given) (第一个版本是我的,第二行来自我们给出的示例程序)

void makeDepositOrWithdraw(int option)
{
    int num;
    cout << "\nEnter account number: ";
    cin >> num;
    int amt;
    bool found = false;
    BankAccount ac;
    SavingsAccount save;
    fstream File;
    File.open("Account.dat", ios::binary | ios::in | ios::out);
    if (!File)
    {
        cout << "Cannot retrieve database right now. Try again later";
        return;
    }
    while (!File.eof() && found == false)
    {
        File.read(reinterpret_cast<char *>(&ac), sizeof(BankAccount));
        if (ac.getAccountNo() == num)
        {
            ac.displayAcc();
            if (option == 1)
                save.makeDeposit();
            if (option == 2)
                save.makeWithdrawal();
            int pos = (-1) * static_cast<int>(sizeof(ac));
            File.seekp(pos, ios::cur);

            //File.write((char *)&ac, sizeof(BankAccount));
            File.write(reinterpret_cast<char *>(&ac), sizeof(BankAccount));

            cout << "__________________________________"
                 << "\nRecord updated ";
            found = true;
        }
    }
    File.close();
    if (!found)
        cout << "Record not found";
}

EDIT: I'm sorry for being really bad at explaining this.编辑:我很抱歉在解释这个方面非常糟糕。 The initial creation of a new account works.新帐户的初始创建有效。 But trying to make additional deposit doesn't run into any error, the variables are being properly updated all the way up to the main BankAccount class.但是尝试进行额外存款不会遇到任何错误,变量一直正确更新到主BankAccount类。 But nothing gets updated in the already existing account in the .dat file.但是 .dat 文件中现有帐户中没有任何更新。 Program still executes without any error.程序仍然执行,没有任何错误。 I'm assuming if I understand the problem with the depositing part, I'll be able to solve the problem with withdrawing too, as both are handled in the same function.我假设如果我了解存款部分的问题,我也可以解决提款问题,因为两者都在同一功能中处理。

#include <iostream>
#include <fstream>
#include <cctype>
#include <iomanip>
using namespace std;

class BankAccount
{
private:
    float Balance, ServChargePerMonth, AnnualInterestRt, DepoAmt, WithdrwAmt;
    int NoOfDepositPerMonth, NoOfWithdrawalPerMonth, AccountNo;
    char Name[50], type;

public:
    virtual void makeDeposit()
    {
        Balance += DepoAmt;    //adding argument to acc bal
        NoOfDepositPerMonth++; //incrementing noOfDeposit
    };

    virtual void makeWithdrawal()
    {
        Balance -= WithdrwAmt;    //subtracting argument from acc bal
        NoOfWithdrawalPerMonth++; //incrementing noOfWithdrawal
    };

    virtual void createAcc()
    {
        cout << "\nEnter your account number: ";
        cin >> AccountNo;
        cout << "\nEnter your full name: ";
        cin.ignore();
        cin.getline(Name, 50);
        cout << "\nEnter the type of Account (C for current or S for savings): ";
        cin >> type;
        type = toupper(type);
        cout << "\nEnter initial deposit amount: ";
        cin >> Balance;
        cout << "___________________________________________________________"
             << "\n\nAccount created." << endl;
    };

    void displayAcc()
    {
        cout << "\nAccount number: " << AccountNo
             << "\nAccount holder name: " << Name
             << "\nType of account: " << type
             << "\nAccount balance: $" << Balance
             << "\nTotal number of deposits: " << NoOfDepositPerMonth
             << "\nTotal number of withdrawals: " << NoOfWithdrawalPerMonth
             << "\nService Charge: $" << ServChargePerMonth << endl;
    };

    //getters
    float getBalance() { return Balance; }
    float getDepoAmt() { return DepoAmt; }
    int getNoOfDeposit() { return NoOfDepositPerMonth; }
    int getNoOfWithdraw() { return NoOfWithdrawalPerMonth; }
    int getAccountNo() { return AccountNo; }

    //setters
    void setServChargePerMonth(float servCharge) //note: increasing, not setting
    {
        ServChargePerMonth += servCharge;
    }
    void setWithdrawAmt(float Amount)
    {
        WithdrwAmt = Amount;
    }
    void setBalance(float blnce)
    {
        Balance = blnce;
    }
    void setDepoAmt(float Amount)
    {
        DepoAmt = Amount;
    }
};
class CheckingAccount : public BankAccount
{
public:
    void makeWithdrawal(float WithdrwAmt)
    {
        if ((BankAccount::getBalance() - WithdrwAmt) < 0) //note: float doens't go below 0
            setBalance(getBalance() - 15.0);              //deducting $15
        else
            BankAccount::setWithdrawAmt(WithdrwAmt);
        BankAccount::makeWithdrawal();
    }
};
class SavingsAccount : public BankAccount
{
private:
    bool statusVar;
    bool status()
    {
        if (getBalance() < 25.0)
            statusVar = false;
        else
            statusVar = true;
        return statusVar;
    }

public:
    //setter
    void setStatus(bool statusVar)
    {
        statusVar = status();
    }
    bool getStatus() { return statusVar; }

    void makeWithdrawal()
    {

        if (status()) //check if active
        {
            cout << "Enter the amount you would like to withdraw today: ";
            float WithdrwAmt;
            cin >> WithdrwAmt;
            CheckingAccount temp;
            temp.makeWithdrawal(WithdrwAmt); //perform the reqd. check, as well as call the base ver.
        }
        else
        {
            cout << "Your account has deactivated. Please increase "
                 << "your balance to reactivate your account.";
        }
    }

    void makeDeposit()
    {
        cout << "Enter the amount you would like to deposit today: ";
        float temp;
        cin >> temp;
        setDepoAmt(temp); //setting value for amt of deposit
                          //check previous balance
        if (!status())    //if <$25,
        {                 //reactivate the acc. if depoAmt brings bal to $25
            if ((getBalance() + getDepoAmt()) >= 25.0)
                setStatus(true);
        }
        //check
        BankAccount::makeDeposit(); //and then call the base ver.
    }
};

void createAcc()
{
    BankAccount ac;
    ofstream writeFile;
    writeFile.open("Account.dat", ios::binary | ios::app);
    ac.createAcc();
    writeFile.write(reinterpret_cast<char *>(&ac), sizeof(BankAccount));
    writeFile.close();
}

void makeDepositOrWithdraw(int option)
{
    int num;
    cout << "\nEnter account number: ";
    cin >> num;
    int amt;
    bool found = false;
    BankAccount ac;
    SavingsAccount save;
    fstream File;
    File.open("Account.dat", ios::binary | ios::in | ios::out);
    if (!File)
    {
        cout << "Cannot retrieve database right now. Try again later";
        return;
    }
    while (!File.eof() && found == false)
    {
        File.read(reinterpret_cast<char *>(&ac), sizeof(BankAccount));
        if (ac.getAccountNo() == num)
        {
            ac.displayAcc();
            if (option == 1)
                save.makeDeposit();
            if (option == 2)
                save.makeWithdrawal();
            int pos = (-1) * static_cast<int>(sizeof(ac));
            File.seekp(pos, ios::cur);

            //File.write((char *)&ac, sizeof(BankAccount));
            File.write(reinterpret_cast<char *>(&ac), sizeof(BankAccount));

            cout << "__________________________________"
                 << "\nRecord updated ";
            found = true;
        }
    }
    File.close();
    if (!found)
        cout << "Record not found";
}

void display()
{
    int num;
    cout << "\nEnter account number: ";
    cin >> num;
    bool flag = false;
    BankAccount ac;
    ifstream inFile;
    inFile.open("Account.dat", ios::binary);
    if (!inFile)
    {
        cout << "Cannot retrieve database right now. Try again later";
        return;
    }
    cout << "\nBALANCE DETAILS\n";
    while (inFile.read(reinterpret_cast<char *>(&ac), sizeof(BankAccount)))
    {
        if (ac.getAccountNo() == num)
        {
            ac.displayAcc();
            flag = true;
        }
    }
    inFile.close();
    if (!flag)
        cout << "\nAccount number does not exist";
}

void deleteAcc()
{
    int num;
    cout << "\nEnter account number: ";
    cin >> num;
    BankAccount ac;
    ifstream inFile;
    ofstream outFile;
    inFile.open("Account.dat", ios::binary);
    if (!inFile)
    {
        cout << "Cannot retrieve database right now. Try again later";
        return;
    }
    outFile.open("temp.dat", ios::binary);
    inFile.seekg(0, ios::beg);
    while (inFile.read(reinterpret_cast<char *>(&ac), sizeof(BankAccount)))
    {
        if (ac.getAccountNo() != num)
        {
            outFile.write(reinterpret_cast<char *>(&ac), sizeof(BankAccount));
        }
    }
    inFile.close();
    outFile.close();
    remove("Account.dat");
    rename("temp.dat", "Account.dat");
    cout << "__________________________________________"
         << "Your account has been closed.";
}

int main()
{
    char opt;
    int temp;
start:
    do
    {
        system("clear");
        cout << "\n1. Create new account"
             << "\n2. Make a deposit"
             << "\n3. Make a withdrawal"
             << "\n4. Balance enquiry"
             << "\n5. Close existing account"
             << "\n6. Exit"
             << "\n\nPlease select your option(1-6)" << endl;
        cin >> opt;
        system("clear");
        switch (opt)
        {
        case '1':
            createAcc();
            break;
        case '2':
            makeDepositOrWithdraw(1);
            break;
        case '3':
            makeDepositOrWithdraw(2);
            break;
        case '4':
            display();
            break;
        case '5':
            deleteAcc();
            break;
        case '6':
            cout << "Thank you for banking with us" << endl;
            break;
        default:
            cout << "\a" << endl;
            goto start;
            break;
        }
        cin.ignore();
        cin.get();
    } while (opt != '6');
}

C++ places restrictions on the kind of objects you can use binary reads and writes on. C++ 对可以使用二进制读取和写入的对象类型进行了限制。 They are complicated rules but the problem with your BankAccount object is that it has virtual functions and these mean you cannot use binary reads and writes.它们是复杂的规则,但是您的BankAccount对象的问题在于它具有虚函数,这意味着您不能使用二进制读取和写入。

Another problem is that you have several different kind of objects but your code reads and writes only BankAccount objects, not CheckingAccount objects or SavingsAccount objects.另一个问题是您有几种不同类型的对象,但您的代码只读取和写入BankAccount对象,而不是CheckingAccount对象或SavingsAccount对象。

So the code as written cannot work.所以写的代码不能工作。

It's a common beginner mistake.这是一个常见的初学者错误。 Binary reads and writes are very limited in their functionality but beginners try to read and write all sorts of complex objects and expect it to just work, which it doesn't.二进制读取和写入的功能非常有限,但是初学者尝试读取和写入各种复杂对象并期望它能够正常工作,但事实并非如此。

You need to redesign how you do the I/O in your program.您需要重新设计在程序中执行 I/O 的方式。 I'm not sure what you requirements are but dropping the use of binary I/O seems the simplest way to proceed.我不确定您的要求是什么,但放弃使用二进制 I/O 似乎是最简单的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM