初始任务:创建一个程序以添加产品及其特征。功能可以更新。货物本身可以删除并显示所有产品的列表。
我有一个带有4个参数的结构。我需要在文件中存储(写入)新记录,然后能够通过数字ID读取此记录并对该记录执行某些操作。代码:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <stdlib.h>
using namespace std;
struct hardwareData {
int id;
char name[50];
int quantity;
float price;
};
int enterChoice(void);
void newRecord(fstream&);
void updateRecord(fstream&);
void outputRecord(fstream&);
void deleteRecord(fstream&);
void clearData(fstream&);
void outputLine(ostream&, hardwareData);
int main() {
fstream inOutHardware("hardware.dat", ios::in | ios::out);
if (!inOutHardware)
{
cerr << "Error." << endl;
exit(1);
}
int current_choice;
inOutHardware.clear();
while (((current_choice = enterChoice()) != 0))
{
switch (current_choice)
{
case 1:
newRecord(inOutHardware);
break;
case 2:
updateRecord(inOutHardware);
break;
case 3:
deleteRecord(inOutHardware);
break;
case 4:
outputRecord(inOutHardware);
break;
case 5:
int num;
cout << "Clear? (1 - так / 0 - нi)"
<< endl << "Your choice - ";
cin >> num;
if (num == 1) {
clearData(inOutHardware);
cout << "succ!" << endl;
}
else {
cout << "canceled" << endl;
}
break;
default:
cerr << "err" << endl;
break;
}
}
inOutHardware.close();
system("pause");
return 0;
}
void newRecord(fstream &insertInFile)
{
cout << "Input number (1-100): ";
hardwareData hardware;
int id;
cin >> id;
insertInFile.seekg((id - 1) + sizeof(hardware));
insertInFile.read((char *)&hardware, sizeof(hardware));
if (hardware.id == 0)
{
cout << "Input data" << endl;
cin >> hardware.name >> hardware.quantity >> hardware.price;
hardware.id = id;
insertInFile.seekp((id - 1) * sizeof(hardwareData));
insertInFile.write((char *)&hardware, sizeof(hardwareData));
}
else
cerr << "№ " << id
<< " already have info" << endl;
}
void updateRecord(fstream &updateFile)
{
int id;
do
{
cout << "Input number for update: ";
cin >> id;
} while (id < 1 || id > 100);
hardwareData hardware;
updateFile.seekg((id - 1) * sizeof(hardware));
updateFile.read((char *)&hardware, sizeof(hardware));
if (hardware.id != 0)
{
outputLine(cout, hardware);
cout << endl << "Input quan and price : ";
int quan;
float price;
cin >> quan;
cin >> price;
hardware.quantity = quan;
hardware.price = price;
outputLine(cout, hardware);
updateFile.seekp((id - 1) * sizeof(hardware));
updateFile.write((char *)&hardware, sizeof(hardware));
}
else
cerr << " № " << id
<< " empty " << endl;
}
void deleteRecord(fstream &deleteFromFile)
{
cout << "Input number for delete (1-100): ";
int id;
cin >> id;
deleteFromFile.seekg((id - 1) * sizeof(hardwareData));
hardwareData hardware;
deleteFromFile.read((char *)&hardware, sizeof(hardwareData));
if (hardware.id != 0)
{
hardwareData blankhw = { 0, " ", 0, 0 };
deleteFromFile.seekp((id - 1) * sizeof(hardware));
deleteFromFile.write((char*)&blankhw, sizeof(hardware));
cout << "№ " << id << " deleted" << endl;
}
else
cout << "№ " << id << " empty" << endl;
}
void outputRecord(fstream &printRecord)
{
cout << setiosflags(ios::left) << setw(6) << "ID"
<< setw(16) << "NAME" << setw(11) << "QUANTITY"
<< setiosflags(ios::right) << setw(10) << "PRICE" << endl;
printRecord.seekg(0);
hardwareData hardware;
printRecord.read((char*)&hardware, sizeof(hardware));
while (!printRecord.eof())
{
if (hardware.id != 0)
outputLine(cout, hardware);
printRecord.read((char*)&hardware, sizeof(hardware));
}
}
void clearData(fstream &record) {
hardwareData blankHardware = { 0, "", 0, 0.0 };
record.seekp(0);
for (int i = 1; i <= 100; i++)
record.write((char *)&blankHardware, sizeof(blankHardware));
}
int enterChoice(void)
{
cout << "Виберiть опцiю" << endl
<< " 1 - Add " << endl
<< " 2 - update" << endl
<< " 3 - delete" << endl
<< " 4 - output" << endl
<< " 5 - clear" << endl
<< " 0 - exit" << endl;
int choice;
cin >> choice;
return choice;
}
void outputLine(ostream &output, hardwareData c)
{
output << setiosflags(ios::left) << setw(6) << c.id
<< setw(16) << c.name << setw(11) << c.quantity
<< setiosflags(ios::showpoint | ios::right)
<< setw(10) << setprecision(2) << c.price << endl;
}
错误:当我第一次单击文件中所有数据的输出时,所有内容都按标称工作,而下一次,未知字符将无限次显示。
答案 0 :(得分:4)
您反复遇到一个问题,即不检查操作是否成功,然后使用未初始化的数据,因为不会发生初始化。例如:
hardwareData hardware;
int id;
cin >> id;
insertInFile.seekg((id - 1) + sizeof(hardware));
insertInFile.read((char *)&hardware, sizeof(hardware));
if (hardware.id == 0)
{
hardwareData
没有构造函数,因此硬件未初始化,可能包含垃圾。除非引起这种情况,否则它不会初始化为零,例如:
hardwareData hardware{};
接下来,id
未初始化,再次可能会造成垃圾。如果从cin读取失败,则id仍保留垃圾值。将ID初始化为零。
在那之后,如果seekg试图通过寻找文件中的无效位置而失败,则不会检测到该错误。相反,您从处于错误状态的流中读取,并且读取将失败,并且hardware
被保留为垃圾。 (解决此问题时,请勿检查EOF,检查流的故障位以检测错误,或在流上调用good()以检测其未处于错误状态。)
然后,您检查hardware.id
是否为零以表明该记录不存在,但是如果该记录存在垃圾,则无法从其任何成员中可靠地提取任何含义。
我看上去并不远,所以您可能还有其他问题,但这是重要的问题。