通过直接访问C ++从文件读取

时间:2018-10-24 11:36:57

标签: c++

初始任务:创建一个程序以添加产品及其特征。功能可以更新。货物本身可以删除并显示所有产品的列表。

我有一个带有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;
}

错误:当我第一次单击文件中所有数据的输出时,所有内容都按标称工作,而下一次,未知字符将无限次显示。 Infinity loop

1 个答案:

答案 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是否为零以表明该记录不存在,但是如果该记录存​​在垃圾,则无法从其任何成员中可靠地提取任何含义。

我看上去并不远,所以您可能还有其他问题,但这是重要的问题。