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

时间:2018-01-18 03:41:04

标签: c++ arrays data-structures struct binary

  • 我不允许使用载体,因为它没有在我的教学大纲中教授

我正在读取/写入/存储学生作业标记。

我正在使用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;
};

我写函数的简短说明:(请告诉我这种风格是否正确)

// 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以供将来使用。 每次我打开程序,它都会检查.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();
}

由于某种原因,我必须在readbinary()中使用afile.clear(),否则返回给我的字节是-1。

我现在遇到的问题是我需要从.dat文件复制信息并将其存储在某处,以便在连续使用程序时,我仍然能够检索数据并在s []时显示它.code已输入。

需要注意的一些事项:

  • 我追加.dat,而不是覆盖
  • 我有一个查询功能,用于在用户输入主题代码时回读数据
  • 我尝试在readbinary()中使用cout来查看它是否读取任何内容。它只是给了我一个空白
  • 我听说我需要将读取的信息存储回数组结构中,但我不知道如何

仍然是C ++的业余爱好者,如果我不理解某些背景,我会事先道歉

感谢任何帮助。 TKS!

1 个答案:

答案 0 :(得分:0)

一些事情:

  1. 您需要afile.clear()的原因是因为当您从流中读取时,您正在推进其正在读取的文件中的位置。你要做的第一件事就是阅读整个文件......所以任何进一步的读取当然都会在你读完文件后没有返回任何数据。在您使用clear()

  2. 重置阅读位置之前
  3. 这条线路错误:

    while (afile.read (reinterpret_cast <char *>(&s), sizeof (s)))
    
  4. sizeof(s)将等于sizeof(subject*)并且您正在阅读垃圾内存(我认为);这导致问题#3

    1. 不建议写这样的东西:

      void checkBinary(fstream& afile, const char fileName [], subject s[])
      
    2. 因为你正在丢失数组的大小!在C和C ++中,函数参数不是数组(即使它们看起来像它们),它们是指向第一个元素的指针!当你传递一个阵列时,它就会衰变。指针。

      为清楚起见,请注意以上行完全等于以下内容:

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

      最好像这样编写你的函数:

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

      注意:文件名作为std::string const引用传递,以避免不必要的副本。无需担心手动管理char数组的详细信息及其生命周期(如果它在堆上分配)。

      此外,返回vectorsubject个对象,因为此函数通过从文件中读取它们来生成主题。 vector知道它的大小,所以你永远不需要打扰sizeof

      之类的东西

      所以我可能会实现你的一个功能:

      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;
      }