1

While running this section, my .dat file gets some random characters. I don't get it, what am I doing wrong?

fstream file("trial1.dat", ios::app | ios::in | ios::out);
file.seekg(0, ios::end);
login obj1;     //Pre-loaded accounts
login obj2;
login obj3;
login obj4;
login obj5;
strcpy(obj1.password, "wr100m1234");
strcpy(obj1.userid, "creative");
strcpy(obj2.password, "pass123400");
strcpy(obj2.userid, "logitech");
strcpy(obj3.userid, "microsof");
strcpy(obj3.password, "coolermast");
strcpy(obj4.userid, "lenovo12");
strcpy(obj4.password, "surface103");
strcpy(obj5.userid, "hewlett1");
strcpy(obj5.password, "packard999");
cout << obj1.userid;
file.write((char *)&obj1, sizeof(obj1));     //writing all the userids and passwords to file
file.write((char *)&obj2, sizeof(obj2));
file.write((char *)&obj3, sizeof(obj3));
file.write((char *)&obj4, sizeof(obj4));
file.write((char *)&obj5, sizeof(obj5));
int z;
cout << "Do you want to use existing id or create new id?(1/2) \n";
cin >> z;

if(z == 2)
{
    file.seekg(0, ios::end);
    login a;
    cout << "Enter id \n";
    cin >> a.userid;
    cout << "Enter pass \n";
    cin >> a.password;
    file.write((char *)&a, sizeof(a));
    z = 1;
}

int l;

if(z == 1)
{
    login a1, a2;
    cout << "Enter id \n";
    cin >> a1.userid;
    cout << "Enter password \n";
    cin >> a1.password;

    while(!file.eof())
    {
        file.read((char *)&a2, sizeof(a2));                   //reading of object from file
        if(strcmp(a1.userid, a2.userid) == 0 && strcmp(a1.password, a2.password) == 0)
        {
            cout << "Login Successful \n";
            l = 1;
            break;
        }
        else
        {
            cout << "Login failed \n";
            l = 0;
            break;
        }
    }
}

file.close();

This is the code for the password checking. I wanted to have some pre-defined logins as well as to create new login ids. While executing this code, the trial1.dat has some random characters.

  • login is defined with char userid[10] and char password[10].
LogicStuff
  • 19,397
  • 6
  • 54
  • 74
  • See [Why is iostream::eof inside a loop condition considered wrong?](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) please. – πάντα ῥεῖ Nov 16 '15 at 13:24
  • @Aditya Are you expecting `file.write` to call something like `file << member` for each of your (presumed) `char*`s? It just writes the bytes. This can be done nicely using operator overloading for `login`. – LogicStuff Nov 16 '15 at 13:30
  • No. I just want file.write to write the data in the file. The file will store the data. When the user inputs his userid and password, i will check the file for the userid and password. – Aditya Petety Nov 16 '15 at 13:42
  • You're writing an addresses to your file. The data are lost. – LogicStuff Nov 16 '15 at 13:44
  • How is `login` defined? If it has char pointers then you'll get the addresses written to the file. If they are char arrays then everything after the strings will contain uninitialized data that is still written to the file. Either way, `file.write` is the wrong way to do it. – Kevin Nov 16 '15 at 13:45
  • login is defined as char userid[10] and char password[10]. How can I write the members of a class into a file if i cannot use this. @LogicStuff i didnt get what you did in that code. – Aditya Petety Nov 16 '15 at 13:53
  • It looks like all of your passwords are 10 characters long. For a valid c-string you need an extra byte of space for the null byte. You should really use `std::string` instead of `char` arrays as it avoids this problem. @LogicStuff overloaded the `<<` operator so you can just write `file << obj1` to write the data for `obj1` to the file. – Kevin Nov 16 '15 at 13:56
  • @Kevin now i got what he is trying to do, but i still haven't learnt operator overloading. How do i use the data type std::string? How can i write object in file without using operator overloading? Sorry for noob questions. Am still new to c++. – Aditya Petety Nov 16 '15 at 14:06
  • Google around for `std::string` examples. Basically in your code you can replace your `strcpy` calls with `obj1.password = "...";`. Overloading the `<<` operator for your struct just makes it fit in easier with how you normally output data in C++. Notice that you wrote `cout << obj1.userid;` in your code - that uses operator overloading, you just didn't write the overload yourself. – Kevin Nov 16 '15 at 14:10
  • Thanks for the help guys!! – Aditya Petety Nov 16 '15 at 15:11

1 Answers1

3

You can not expect file.write to call something like file << member for each of your (presumed) char arrays. It just writes the addresses chopped into bytes i.e. you're not writing any data.

This can be done nicely using operator overloading for login structure (whatever it is):

struct login
{
    char password[10]; // these should really be 'std::string's
    char userid[10];

    // in case you decide to make password and userid private
    friend std::ostream &operator<<(std::ostream &os, login const& l);
    friend std::istream &operator>>(std::istream &is, login &l);
};

std::ostream &operator<<(std::ostream &os, login const& l) // for output
{
    return os << l.userid << std::endl << l.password << std::endl;
}

std::istream &operator>>(std::istream &is, login &l) // for input
{
    return is >> l.userid >> l.password;
}

And you can proceed to cleaner C++ with this. You will be using it like this:

login l;
inputfile >> l;
// do something
outputfile << l;
Community
  • 1
  • 1
LogicStuff
  • 19,397
  • 6
  • 54
  • 74