[英]Problem with file handling part of C++ assignment
此函数应该负责在调用用于从用户帐户存款或取款的相应函数后更新文件。 但它没有做到这一点。 我已经尽可能多地检查过,所有其他功能似乎都在正常工作。 我已经将其追溯到程序似乎失败的特定行。
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));
是的,这是该行的两个版本,因为我不完全了解它们中的任何一个是如何工作的。 (第一个版本是我的,第二行来自我们给出的示例程序)
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";
}
编辑:我很抱歉在解释这个方面非常糟糕。 新帐户的初始创建有效。 但是尝试进行额外存款不会遇到任何错误,变量一直正确更新到主BankAccount
类。 但是 .dat 文件中现有帐户中没有任何更新。 程序仍然执行,没有任何错误。 我假设如果我了解存款部分的问题,我也可以解决提款问题,因为两者都在同一功能中处理。
#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++ 对可以使用二进制读取和写入的对象类型进行了限制。 它们是复杂的规则,但是您的BankAccount
对象的问题在于它具有虚函数,这意味着您不能使用二进制读取和写入。
另一个问题是您有几种不同类型的对象,但您的代码只读取和写入BankAccount
对象,而不是CheckingAccount
对象或SavingsAccount
对象。
所以写的代码不能工作。
这是一个常见的初学者错误。 二进制读取和写入的功能非常有限,但是初学者尝试读取和写入各种复杂对象并期望它能够正常工作,但事实并非如此。
您需要重新设计在程序中执行 I/O 的方式。 我不确定您的要求是什么,但放弃使用二进制 I/O 似乎是最简单的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.