Question

In an array like int a[5] we can store 5 values from a[0] to a[4]. not this..?

I have a char mobile[10] variable in my class and I was storing exactly 10 character long string in this variable. But when I am reading it from file, a few characters from the next variable (declared just after this variable in class) are being appended in variable mobile. It took hours to investigate what is wrong.

I tried everything I could by changing the order of variable etc.

At last I'd set the size of mobile to 11 (char mobile[11]) and then store it into the binary file. Then everything goes well.

Here I have created a demo program that can demonstrate my study:

#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <fstream.h>
#include <stdio.h>

class Test
{
    public:
    char mobile[10], address[30];
};

void main()
{
    clrscr();
    Test t;
    // uncoment below to write to file
    /*strcpy(t.mobile, "1234567890");
    strcpy(t.address, "Mumbai");

    fstream f("_test.bin", ios::binary | ios::out | ios::app);
    f.write((char*)&t, sizeof(t));*/

    // uncomment below to read from file
    /*fstream f("_test.bin", ios::binary | ios::in);
    f.read((char*)&t, sizeof(t));
    cout << t.mobile << "\t" << t.address;*/

    f.close();

    getch();
}

Is my assumption correct that I can not store n characters in an array like char[n] when working with files more specifically with binary files..?

Should I always take 1 extra size of required size..??

My compiler is Turbo C++ (may be 3.0). It is very old and discontinued product.

Was it helpful?

Solution 2

character pointers in C/C++ must be null terminated. That means you must allot another character with value of '\0' at the end.

Also note, strcpy function copies all the characters from one string to another, until \0 is encountered, unless its a const string(an example is "hello world") which is stored as "hello world\0" during compilation.

Try this code:

#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <fstream.h>
#include <stdio.h>

class Test
{
    public:
    char mobile[11], address[30];
};

void main()
{
    clrscr();
    Test t;
    // uncoment below to write to file
    strcpy(t.mobile, "1234567890");
    strcpy(t.address, "Mumbai");
    t.address[10] = '\0';
    fstream f("_test.bin", ios::binary | ios::out | ios::app);
    f.write((char*)&t, sizeof(t))

    // uncomment below to read from file
    fstream f("_test.bin", ios::binary | ios::in);
    f.read((char*)&t, sizeof(t));
    cout << t.mobile << "\t" << t.address;

    f.close();

    getch();
}

OTHER TIPS

C-style strings (char arrays) are null terminated. You do not need to store the null terminator in your file, but you need it when printing the string.

In your example you use strcpy to copy a 10-character string into a char[10]. This is undefined behavior because strcpy appends a null terminator to the destination string. You need to use a char[11].

In your example you read 10 characters from the file and print them using cout. cout determines the length of the string by the null terminator. Since you don't have one, cout reads past the end of your string. This is also undefined behavior, but happens to work in most cases by reading characters from the next field in the struct. You need a null terminator on this array, which means you would need to increase your array size to 11 for this as well.

The string literal "1234567890" occupies 11 bytes, not 10!

printf("%d", sizeof("1234567890"));
// 11

This is because the compiler silently adds a \0 character - end of string marker - at the end of string literals. This marker is used by various string manipulation functions, including strcpy.

Now, the following line:

strcpy(t.mobile, "1234567890");

attempts to copy the string - the 10 characters plus the \0 - into t.mobile. Since t.mobile is 10 bytes long, the \0 will overflow into the space used by other variables' space (or worse).

In your example:

  • strcpy(t.mobile, "1234567890") copies the string as expected but the \0 overflows into the space used by t.address
  • strcpy(t.address, "Mumbai") copies the string as expected, the \0 gets overwritten
  • The result of printing t.mobile should be "1234567890Mumbai"

Moral of the story: always account for the \0 byte when using C string functions. Failing to do so will cause unexpected problems including variable corruption, run time errors, or worse (e.g. data execution).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top