c++fstream

Trying to open file but instead getting pointer location C++


I am making a program that gets info about a Doom wad file.

Now, I have made the code to get the wad type (IWAD/PWAD) by checking the first byte. If it's I, it's an IWAD. If it's P, it's a PWAD.

Here is the code:

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdexcept>

using namespace std;

enum WadType
{
    iwad,
    pwad
};

class WadHeader
{
  public:
    WadType wadType;
    int lumpc;
    int dir;
    WadHeader(fstream& wadFile)
    {
        char x;
        unsigned int y;
        unsigned int z;
        wadFile.read(&x, 1);
        if (x == 0x49) // "I" didn't work
        {
            wadType = iwad;
        }
        else if (x == 0x50) // "P" didn't work
        {
            wadType = pwad;
        }
        else
        {
            cout << "Invalid wad byte: " << hex << showbase << static_cast<int>(x) << endl;
            throw runtime_error("not a valid wad");
        }
        wadFile.seekg(4);
        wadFile.read(reinterpret_cast<char *>(&y), 4);
        lumpc = y;
        wadFile.seekg(8);
        wadFile.read(reinterpret_cast<char *>(&z), 4);
        dir = z;
    }
};

class Wad
{
  public:
    Wad(string wn) : wadName(wn), headerInfo(wadFile)
    {
        wadFile.open(wn, ios::in |
                             ios::out |
                             ios::binary);
        if (!wadFile.is_open())
        {
            throw runtime_error("file not open");
        }
        cout << headerInfo.wadType << endl
             << headerInfo.lumpc << endl
             << headerInfo.dir;
    }
    ~Wad()
    {
        wadFile.close();
    }

  private:
    fstream wadFile;
    string wadName;
    WadHeader headerInfo;
};

int main(int argc, char *argv[])
{
    Wad wad("GOLDTESTS.wad");
}

However, it is giving me random bytes. I think that it is reading the pointer location instead of the value.

I also have a different version of the code:

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdexcept>

using namespace std;

enum WadType
{
    iwad,
    pwad
};

class WadHeader
{
  public:
    WadType wadType;
    int lumpc;
    int dir;

    WadHeader(fstream *wadFile)
    {
        unsigned char x;
        unsigned int y;
        unsigned int z;
        x = wadFile->get();
        if (x == 0x49)
        {
            wadType = iwad;
        }
        else if (x == 0x50)
        {
            wadType = pwad;
        }
        else
        {
            cout << "Invalid wad byte: " << hex << showbase << static_cast<int>(x) << endl;
            throw runtime_error("not a valid wad");
        }
        wadFile->seekg(4);
        wadFile->read(reinterpret_cast<char *>(&y), 4);
        lumpc = y;
        wadFile->seekg(8);
        wadFile->read(reinterpret_cast<char *>(&z), 4);
        dir = z;
    }
};

class Wad
{
  public:
    Wad(string wn) : wadName(wn), headerInfo(&wadFile)
    {
        wadFile.open(wn, ios::in | ios::out | ios::binary);
        if (!wadFile.is_open())
        {
            throw runtime_error("file not open");
        }
        cout << headerInfo.wadType << endl
             << headerInfo.lumpc << endl
             << headerInfo.dir;
    }

    ~Wad()
    {
        wadFile.close();
    }

  private:
    fstream wadFile;
    WadHeader headerInfo;
    string wadName;
};

int main(int argc, char *argv[])
{
    Wad wad("GOLDTESTS.wad");
    return 0;
}

This one instead just says the first byte is 0xFF.

Why is this happening?


Solution

  • The constructor body of Wad runs after the constructor of WadHeader, but you open file in Wad() and read it in WadHeader(). So, you are trying to read from an unopened file.

    To resolve it, you should rethink what's happening in Wad constructor, what in WadHeader constructor and when to open file (usually a constructor is not the place). An easy solution is to set the values to defaults or zeros in WarHeader constructor, and put the reading code in a method init(), read(), or similar.