dimanche 31 juillet 2016

Reading contents of file into dynamically allocated char* array- can I read into std::string instead?

I have found myself writing code which looks like this

// Treat the following as pseudocode - just an example

iofile.seekg(0, std::ios::end); // iofile is a file opened for read/write
uint64_t f_len = iofile.tellg();

if(f_len >= some_min_length)
{
    // Focus on the following code here
    char *buf = new char[7];
    char buf2[]{"MYFILET"}; // just some random string
                            // if we see this it's a good indication
                            // the rest of the file will be in the
                            // expected format (unlikely to see this
                            // sequence in a "random file", but don't
                            // worry too much about this)
    iofile.read(buf, 7);

    if(memcmp(buf, buf2, 7) == 0) // I am confident this works
    {
        // carry on processing file ...
        // ...
        // ...
    }
}
else
    cout << "invalid file format" << endl;

This code is probably an okay sketch of what we might want to do when opening a file, which has some specified format (which I've dictated). We do some initial check to make sure the string "MYFILET" is at the start of the file - because I've decided all my files for the job I'm doing are going to start with this sequence of characters.

I think this code would be better if we didn't have to play around with "c-style" character arrays, but used strings everywhere instead. This would be advantageous because we could do things like if(buf == buf2) if buf and buf2 where std::strings.

A possible alternative could be,

// Focus on the following code here
std::string buf;
std::string buf2("MYFILET"); // very nice
buf.resize(7); // okay, but not great
iofile.read(buf.data(), 7); // pretty awful - error prone if wrong length argument given
                            // also we have to resize buf to 7 in the previous step
                            // lots of potential for mistakes here,
                            // and the length was used twice which is never good
if(buf == buf2) then do something

What are the problems with this?

  • We had to use the length variable 7 (or constant in this case) twice. Which is somewhere between "not ideal" and "potentially error prone".
  • We had to access the contents of buf using .data() which I shall assume here is implemented to return a raw pointer of some sort. I don't personally mind this too much, but others may prefer a more memory-safe solution, perhaps hinting we should use an iterator of some sort? I think in Visual Studio (for Windows users which I am not) then this may return an iterator anyway, which will give [?] warnings/errors [?] - not sure on this.
  • We had to have an additional resize statement for buf. It would be better if the size of buf could be automatically set somehow.

Aucun commentaire:

Enregistrer un commentaire