0

I have a homework and I have to write an object into a binary file. Then I have to read that object from the binary file. Everything works fine,except a variable of type char*. I read it, but at the end of the text i got some random characters. I think the problem is the string terminator /0 ,but i don't know how to handle it. Can someone help me?

This is the code I used to write in the file:

        size_t n = strlen(input);// input is declared as char* input
        f.write((char*)&n, sizeof(n+1));
        f.write(input, n);

And this is how I tried to read this variable from the binary file:

        size_t n;
        f.read((char*)&n, sizeof(n));
        delete[] buffer;// buffer is also a char*
        buffer = new char[n];
        f.read(buffer, n);

I got the text from variable input, but at the end i got some random characters

4
  • 5
    sizeof(n+1) doesn't do what you think it does, but I dont think that relates to your problem Commented Dec 28, 2022 at 21:47
  • The variable was initialized with a text. My code is a lot bigger, I took only this part where I got a problem. @MooingDuck Commented Dec 28, 2022 at 21:51
  • sizeof(n+1) -- No need to read any further. This is totally wrong. Commented Dec 28, 2022 at 21:56
  • f.write((char*)&n, sizeof(n+1)); you broke file by writing extra byte with unknown content Commented Dec 28, 2022 at 23:09

1 Answer 1

1

C-strings must be nul-terminated

C-strings have length elements plus a terminating nul character. You do in fact write the nul to file, but you fail to allocate space for and read it from file. Make sure things match.

size_t n;
f.read( (char *)&n, sizeof n );
char * s = new char[n+1];
f.read( s, n+1 );

UPDATE: You have changed your code (as per commentary below) to not write the nul-terminator to file. Make sure to initialize it as such when you read it:

...
char * buffer = new char[n+1];
f.read( buffer, n );
buffer[n] = '\0';

Endianness nonsense you can totally ignore

As an aside, you are not considering endianness issues with your size_t. I would personally make functions specifically for reading and writing integers in a file-specific endianness.

size_t n = read_integer( f, 4 );
char * s = new char[n+1];
f.read( s, n+1 );

Supposing a little-endian file, we could have:

size_t read_integer( std::istream & f, int n )
{
  size_t result = 0;
  while (n--)
    result = (result << 8) | ((unsigned char)f.get() & 0xFF);
  return result;
}

A corresponding function to write a little-endian value:

std::ostream & write_integer( std::ostream & f, size_t n, size_t value )
{
  while (n--)
  {
    f.put( value & 0xFF );
    value >>= 8;
  }
  return f;
}

(Untested. I might have goofed something.)

Oh, also:

write_integer( f, 4, strlen(s) );
f.write( s, strlen(s)+1 );
Sign up to request clarification or add additional context in comments.

7 Comments

I change the code like this and now it's working, but i want to see if it's correct like this size_t n = strlen(input)+1; // input is declared as char* input f.write((char*)&n, sizeof(n)); f.write(input, n); And for reading size_t n; f.read((char*)&n, sizeof(n)); delete[] buffer;// buffer is also a char* buffer = new char[n]; f.read(buffer, n);
Yes... but... you then have the same problem you started with: a non-terminated C-string. Re-read the very first part of my answer.
ok, so i should initialize like this: buffer=new char[n+1] and in this way i will have enough space for the string terminator?
Yes, that is correct.
ok, thank you very much for your help. I am sorry that I didn't understand your answear really well. I am still learning:))
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.