简体   繁体   English

(C ++)如何从二进制文件.dat中读取信息以存储在结构数组中?

[英](C++) How do i read info from a binary file .dat to be stored in an array of struct?

  • i'm not allowed to use vectors as its not taught in my syllabus 我不允许使用向量,因为它不在我的教学大纲中

i'm doing an assignment on read/write/store of students assignment marks. 我正在对学生作业标记的读/写/存储进行作业。

i'm using 2 struct below 我在下面使用2结构

struct assessTask
{
    char title [MAX];
    int weight;
    int markUpon;
    float mark;
};

struct subject
{
    char code [MAX];
    char title [MAX];
    int numTask;
    assessTask task [MAX];
    int finalMark;
    UNIGrade grade;
};

A short snip of my write function:(do tell me if this style is correct/wrong) 我的写函数的一小段代码:(请告诉我这种样式是否正确/错误)

// run if code is unique        
        strcpy(s[size].code, testcode);
        afile.write (reinterpret_cast <const char *>(&s[size].code), sizeof (s));   

        cin.clear();
        cin.ignore(MAX, '\n');

        cout << "Subject Name: ";
        cin.getline(s[size].title, MAX);
        afile.write (reinterpret_cast <const char *>(&s[size].title), sizeof (s));  

        cout << "No of assessment tasks: ";
        cin >> s[size].numTask;  
        afile.write (reinterpret_cast <const char *>(&s[size].numTask), sizeof (s));

Snippet of whats inside my binary file .dat 我的二进制文件.dat中的内容摘要

so, after i exit from the program, the .dat is stored for future uses. 因此,从程序退出后,.dat会存储以备将来使用。 everytime i open the program, it will check for the .dat file, which i can use to query or update through the program 每次我打开程序时,它将检查.dat文件,我可以用它来查询或更新程序

void checkBinary(fstream& afile, const char fileName [], subject s[])
{
    afile.open(fileName, ios::in | ios::binary);

    int g = 0;

    while (afile.read (reinterpret_cast <char *>(&s), sizeof (s)))
    {           
        g++;
    }

    cout << g << endl;

    if (g < 1)
    {
        createBinary (afile, "subject.dat", s); 
    } 
    else
    {
        readBinary (afile, "subject.dat", s);
    }

    afile.close();
}

void createBinary (fstream& afile, const char fileName [], subject s[])
{
    afile.open (fileName, ios::out | ios::binary);

    cout << "Begin the creation of binary file " << fileName << endl;

    afile.write (reinterpret_cast <const char *>(&s), sizeof (s));

    afile.close ();

    cout << "Binary file " << fileName
         << " successfully created"
         << endl;   
}

void readBinary (fstream& afile, const char fileName [], subject s[])
{
    afile.open (fileName, ios::in | ios::binary);

    afile.clear();

    afile.seekg(0, ios::end);
    int size = afile.tellg();
    int noOfRecords = size / sizeof (s);
    afile.seekg(0, ios::beg);   


    while (afile.tellg() < noOfRecords)
    {
        afile.read (reinterpret_cast <char *>(&s), sizeof (s));
        /*
        afile.read (reinterpret_cast <char *>(&s[start].code), sizeof (s));
        afile.read (reinterpret_cast <char *>(&s[start].title), sizeof (s));
        afile.read (reinterpret_cast <char *>(&s[start].numTask), sizeof (s));

        for (int i = 0; i < s[start].numTask; i++)
        {
            afile.read (reinterpret_cast <char *>(&s[start].task[i].title), sizeof (s));
            afile.read (reinterpret_cast <char *>(&s[start].task[i].weight), sizeof (s));
            afile.read (reinterpret_cast <char *>(&s[start].task[i].markUpon), sizeof (s));
        }
        */
    }

    afile.close();
}

for some reason, i have to afile.clear() in the readbinary(), otherwise the bytes returned to me is -1. 由于某种原因,我必须在readbinary()中使用afile.clear(),否则返回给我的字节为-1。

The problem i have now is that i need to copy the info from .dat file and store it somewhere so that during consecutive uses of the program, i will still be able to retrieve the data and display it when the s[].code is inputted. 我现在遇到的问题是,我需要从.dat文件中复制信息并将其存储在某个位置,以便在程序的连续使用期间,当s []。code是输入。

Some things to take note: 注意事项:

  • i'm appending to the .dat, not overwriting 我要附加到.dat,而不是覆盖
  • i've a query function to read back the data when the user input the subject code 当用户输入主题代码时,我具有查询功能以读取数据
  • i've tried using cout in the readbinary() to see if it reads anything. 我试过在readbinary()中使用cout来查看它是否读取任何内容。 it just gives me a blank line 它只是给我一个空白行
  • i heard that i need to store the read info back into a struct of arrays but i dunno how 我听说我需要将读取的信息存储回数组的结构中,但我不知道如何

Still an amateur in C++, i apologise in advance if i do not understand some context 还是C ++的业余爱好者,如果我不了解某些情况,我会提前道歉

Any help is appreciated. 任何帮助表示赞赏。 Tks! Tks!

A few things: 一些东西:

  1. The reason why you need the afile.clear() is because when you read from the stream, you are advancing where in the file it is reading from. 之所以需要afile.clear()是因为当您从流中读取文件时,您正在推进文件在其中读取的位置。 The very first thing you do is you read the whole file... so any further reads are of course going to return no data since you are done reading the file. 您要做的第一件事就是读取整个文件...因此,既然您已经完成了文件的读取,那么任何进一步的读取当然都不会返回任何数据。 Until you reset the read location with clear() 直到使用clear()重置读取位置

  2. This line is buggy: 这行是越野车:

     while (afile.read (reinterpret_cast <char *>(&s), sizeof (s))) 

sizeof(s) will be equal to sizeof(subject*) and you are reading into junk memory (I think); sizeof(s)将等于sizeof(subject*)并且您正在读取垃圾内存(我认为); which leads to issue #3 导致问题#3

  1. it is not recommended write things like this: 不建议这样写:

     void checkBinary(fstream& afile, const char fileName [], subject s[]) 

Because you are losing the size of the array! 因为您正在丢失数组的大小! in C and C++, function parameters aren't arrays (even if they look like them), they are pointers to the first element! 在C和C ++中,函数参数不是数组(即使它们看起来像数组一样),它们是指向第一个元素的指针! And when you pass an array, it "decays" to a pointer. 当您传递数组时,它会“衰减”到指针。

To make this clear, note that the above line is exactly equal to the following: 为了清楚起见,请注意上述行与以下行完全相同

void checkBinary(fstream& afile, const char *fileName, subject *s)

It would be better to write your functions like this: 最好这样编写函数:

std::vector<subject> checkBinary(const std::string &fileName);

NOTE: the filename is being passed as a std::string and by const reference to avoid unnecessary copies. 注意:文件名将作为std::stringconst引用传递,以避免不必要的复制。 No need to worry about manually managing the details of a char array and its lifetime if it is allocated on the heap. 如果将char数组的详细信息及其寿命分配在堆上,则无需手动进行管理。

Also, The vector of subject objects is returned because this function is producing the subjects by reading them from a file. 另外,返回subject对象的vector ,因为此函数通过从文件中读取来生成主题。 The vector knows its size, so you never need to bother with things like sizeof vector知道它的大小,因此您无需理会sizeof东西

So I might implement one of your functions like this: 因此,我可能会像这样实现您的功能之一:

std::vector<subject> checkBinary(const std::string &fileName) {

    // why pass the ifstream if you just open/close it in this function
    // do it locally!
    std::ifstream afile(fileName, ios::in | ios::binary);

    subject s;
    std::vector<subject> subjects;

    // read each subject and then add them to the result array!
    while (afile.read (reinterpret_cast <char *>(&s), sizeof (s))) {           
        subjects.push_back(s);
    }

    cout << subject.size() << endl;

    // these will obviously need to be reworked as well to support the 
    // different methodology
    if (subject.empty()) {
        createBinary ("subject.dat", subjects); 
    } else {
        // do we even NEED a readBinary? we just read them above!
    }

    // NOTE: since we made the ifstream locally, no need to close it
    // explicitly! research the concept of RAII and make your code even simpler
    // :-)
    return subjects;
}

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

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