开发者

C++: How to read dynamic data elegantly into a struct?

开发者 https://www.devze.com 2023-02-04 07:55 出处:网络
Lets say i store headers in some file, but some part of the header is dynam开发者_JAVA百科ic length, something like this it would look:

Lets say i store headers in some file, but some part of the header is dynam开发者_JAVA百科ic length, something like this it would look:

struct HeaderTest {
    int someparam;
    int more;
    int arrsize;      // how big array, read arrsize elements into arr:
    int arr[arrsize]; // not valid
};

Is there some elegant way for reading dynamic data into a struct?


Instead of having arr and arrsize variables in your struct, you can define your struct like this:

struct HeaderTest 
{
    int someparam;
    int more;
    std::vector<int> data;
}

No arr, no arrsize. Just use std::vector, and std::vector::size(). That is elegant!

And if you want to read binary data from a file, then you can write like this:

struct HeaderTest 
{
    int someparam;
    int more;
    int size;
    char *data;
}

Otherwise, go with the first struct!


An Advice:

Reading your comments everywhere, I feel that I should suggest you to get a good book, and study it first. Here is list of really good books:

The Definitive C++ Book Guide and List


Well, if you don't want to use a container class (not sure why you wouldn't) you can declare arr as a pointer to int and leave it to the client to initialize the pointer to a valid memory location as well as correctly initialize arrsize.

That said, you should just use a vector. Why make things more difficult than they need to be?


This answer is more C than C++, but, you can easily make use of realloc() to resize a buffer to be as large as you need it. As demonstrated in this pseudo code.

struct HeaderTest {
  int someparam;
  int more;
  int arrsize;
  int arr[];
};

HeaderTest* pkt = (HeaderTest*)malloc(sizeof(HeaderTest));
read(&pkt,sizeof(pkt));
pkt = (HeaderTest*)realloc(pkt,sizeof(HeaderTest)+sizeof(pkt->arr[0])*pkt->arrsize);
read(pkt->arr,sizeof(int)*pkt->arrsize);


I don't think there is a very elegant way. You should probably make that dynamic member a pointer, then read all other members first, allocate memory for the last one, and then read the remainder of the data.

Since you're in C++, you can nicely encapsulate this in a class so that you don't have to worry about this detail in your code anymore. Also, as other have said, a std::vector would be a more C++-like approach than a simple pointer and manually allocated memory. It would also be more resistant to memory leaks.


No one was able to give you the solution you wanted, but I have devised it for you. This function takes a C-string filename, opens the file and reads the contents for you. It returns an int*, which can be assigned to t.container. Enjoy.

int* read(char* filename)
{
    // open file
    ifstream f;
    f.open(filename, ios::binary);
    // get file size
    f.seekg (0, ios::end);
    int length = f.tellg();
    f.seekg (0, ios::beg);
    // allocate new int*
    length = (length -(sizeof(int)*2)) / sizeof(int);
    int* buf = new int[length];
    for(int i = 0; i < length; ++i)
    {
        // create byte array to hold bytes
        unsigned char* temp = new char[sizeof(int)];
        stream.read((char*)temp, sizeof(int));
        // convert byte array to int
        for(int j = 0; j < sizeof(int); ++j)
        {
            buf[i] = buf[i] + (temp[j] << (j*8));
        }
        delete[] temp;
    }
    f.close();
    return buf;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消