我正在创建一个程序,允许用户创建银行帐户并将其保存为文件,您也可以删除它们。我的代码删除文件中的帐户时遇到问题,我删除帐户的功能如下所示。
int deleteCustomer(account acc[], int numCust)
{
string target;
bool accFound = false;
int count = 0;
cout << "Enter account number: ";
cin >> target;
for (int i = 0; i < numCust; i++)
{
if (acc[i].acctNum == target)
{
accFound = true;
break;
}
count++;
}
if (accFound == false)
{
cout << "That account does not exist." << endl;
system("pause");
system("cls");
}
else if (accFound == true)
{
ofstream outFile;
outFile.open("customer.dat");
for (int i = count; i < numCust - 1; i++)
{
outFile << acc[i+1].acctNum;
outFile << '#';
outFile << acc[i+1].name;
outFile << '#';
outFile << acc[i+1].cBal;
outFile << '#';
outFile << acc[i+1].sBal;
outFile << '#';
}
numCust--;
outFile.close();
}
return numCust;
}
该功能应该覆盖用户选择的帐户,方法是将文件保存在前一个位置并返回新的客户数。它似乎运行良好,但它没有做任何事情,我不确定为什么。任何输入都会有所帮助,谢谢。
答案 0 :(得分:2)
这里有几个问题:
一些风格的东西:
count
中。这很好,但非常误导。不要使用误导性的变量名。正如您从上面的评论中可以看出的那样,我也误读了那一部分。if (booleanValue == true)
而不是编写if (booleanValue)
,这会产生相同的代码,但会更短,读取速度可能更快。以类似的方式,您可以将if (booleanValue == false)
替换为!booleanValue
。std
等名称空间(例如,使用std::string
而不是string
并避免using namespace std;
),以避免编写具有暧昧代码的内容。如果您使用的其他名称空间也包含string
(或任何其他成员),那么您无论如何都必须明确命名名称空间,或者至少让其他人在阅读您的代码时感到困惑。还有无意中使用不同类型引入的潜在错误。解决实际问题:
我认为这是一些家庭作业或一些教程/类代码或类似的东西?如果是这样,请不要复制以下代码,而是尝试考虑它是如何工作的。一旦理解了,就自己实施,只有在你真正陷入困境时才使用我的代码片段。
一般来说,保持代码和功能最小化是一种很好的软件设计。不要创造超级功能&#34;做几件事。同时尝试使代码可重用,因此如果您更改了某些内容,您只能在一个地方进行调整。
以上面的代码为例。无论何时添加,删除或更新帐户,您都必须编写新文件。您是否计划多次复制相同的代码?如果您不得不调整文件格式,则必须随处更改。
您还需要一些方法来实际删除客户数据集。您可能知道,删除数组中的条目将要求您移动它后面的所有条目(以保持它的连续性)。这可能是一项非常昂贵的操作。
为避免这种情况,我要将新成员bool valid
添加到account
。默认情况下,此项设置为false
。一旦有一些数据(通过从文件或用户读取),它的值将被设置为true
。
因此,将其拆分为两个独立的函数(将公共代码 - 保存 - 移动到自己的函数中):
// By returning an integer value, you're able to communicate issues or problems
// without having to rely on exceptions (in case you're using C++).
// Note that I don't do any error checking here for simplicity.
// Parameters:
// filename - the target file to write
// acc - the array holding all customer accounts
// size - the maximum amount of values in acc
// Return value: 0, if everything went fine
// (I skipped actual error handling to keep it simple!)
int saveCustomers(const char *filename, account acc[], int size) {
std::ofstream outFile(filename);
// Iterate over all entries
for (int i = 0; i < num; ++i) {
// Do we actually have to store the account?
if (acc[i].valid) {
outfile << acc[i].acctNum << '#' << acc[i].name; // write all the values the way you did
}
}
outFile.close();
return 0; // Everything ok
}
既然已经完成,您就可以创建功能来修改客户数据了:
int deleteCustomerByNumber(account acc[], int num, std::string target) {
// Iterate over all accounts and look for the selected one
for (int i = 0; i < num; ++i) {
// Only check valid accounts and see whether it's the target
if (acc[i].valid && acc[i].acctNum == target) {
acc[i].valid = false; // Mark it as invalid
return 0; // Everything ok
}
}
return 1; // Didn't find it!
}
以类似的方式,您可以查找空/未使用的条目以实际向其写入数据。
奖金 - 替代(STL)方法:
由于您使用的是C ++,我建议您使用不同的数据结构,而不仅仅是一个简单的数组:
如果您使用STL容器(更具体地说:地图),您可以更轻松地处理所有事情。
#include <map>
// Create a typedef to simplify expressions
typedef std::map<std::string, account> accmap;
// All accounts would be stored in this object:
accmap accounts;
// To do a quick lookup of any account:
accmap::const_iterator a = accounts.find(accountNumber);
if (a == accounts.end())
;// Account not found!
else {
a->first; // This is your account number
a->second; // This is your `account` object
}
// To delete a specific account:
accounts.erase(accountNumber)
// To create a new account simply access it:
accounts[accountNumber].name = newName;
答案 1 :(得分:1)
您需要保存所有之前索引和之后索引,否则您实际上只删除了一个以上的帐户。大概你也应该从输入数组中删除记录。您也没有对输入或输出进行任何错误处理。你需要修复你的输出循环,它没有正确使用索引。
试试这个:
int deleteCustomer(account acc[], int numCust)
{
string target;
int accFound = -1;
cout << "Enter account number: ";
if (cin >> target)
{
for (int i = 0; i < numCust; ++i)
{
if (acc[i].acctNum == target)
{
accFound = i;
break;
}
}
}
if (accFound == -1)
{
cout << "That account does not exist." << endl;
system("pause");
system("cls");
}
else
{
for (int i = accFound+1; i < numCust; ++i)
acc[i-1] = acc[i];
--numCust;
ofstream outFile;
outFile.open("customer.dat");
for (int i = 0; (i < numCust) && (outFile); ++i)
{
outFile << acc[i].acctNum;
outFile << '#';
outFile << acc[i].name;
outFile << '#';
outFile << acc[i].cBal;
outFile << '#';
outFile << acc[i].sBal;
outFile << '#';
}
if (!outFile)
cout << "Error saving customer file" << endl;
}
return numCust;
}
如果您不想更新阵列,那么您可以改为:
int deleteCustomer(account acc[], int numCust)
{
string target;
int accFound = -1;
cout << "Enter account number: ";
if (cin >> target)
{
for (int i = 0; i < numCust; ++i)
{
if (acc[i].acctNum == target)
{
accFound = i;
break;
}
}
}
if (accFound == -1)
{
cout << "That account does not exist." << endl;
system("pause");
system("cls");
}
else
{
ofstream outFile;
outFile.open("customer.dat");
for (int i = 0; (i < numCust) && (outFile); ++i)
{
if (i != accFound)
{
outFile << acc[i].acctNum;
outFile << '#';
outFile << acc[i].name;
outFile << '#';
outFile << acc[i].cBal;
outFile << '#';
outFile << acc[i].sBal;
outFile << '#';
}
}
if (!outFile)
Cout << "Error saving customer file" << endl;
--numCust;
}
return numCust;
}
最后,在更新文件时,最好先将新数据写入临时文件,然后仅在一切成功时将原始文件替换为临时文件。这样可以降低破坏原始文件的风险。
答案 2 :(得分:0)
要删除文件&#34;上的帐户,这部分代码:
for (int i = count; i < numCust - 1; i++)
{
outFile << acc[i+1].acctNum;
outFile << '#';
outFile << acc[i+1].name;
outFile << '#';
outFile << acc[i+1].cBal;
outFile << '#';
outFile << acc[i+1].sBal;
outFile << '#';
}
应该是
for (int i = 0; i < numCust; i++)
{
if(i == count) continue;// remove the account user selected
outFile << acc[i].acctNum;
outFile << '#';
outFile << acc[i].name;
outFile << '#';
outFile << acc[i].cBal;
outFile << '#';
outFile << acc[i].sBal;
outFile << '#';
}