Welcome to our boards Dragon.
I'll provide you the solution, but first a few lessons.
Ok, you're going quite well, but there are two key issues:
1) You forgot to close the file, before you re-opened it.
This is the easy part.
2) One shall not use
write()/read() with STL based strings (std::string).
The latter needs an explanation.
Suppose you have an existing file with names. The file doesn't care whether they are
char* or
std::string strings. And now you would like to retreive the names. Question:
If the names were written with
write(), how does your variable that waits for the retreival know the size of the incoming name?
True, you could use something like this:
Code:
char* buffer = new char[SomeSize];
fin.read(buffer, strlen(myNameVector[i].c_str()) + 1);
As you can see, this is highly depressing code. And if the buffer size is too small after all, you're in trouble. But then again, you could write even so-called smarter code that keeps track of all the name lengths. Now even more depressing code will arise. Talking about esoteric code huh?
So let's use a simple rule:
Quote:
|
'We shall use the familiar std::getline() or >> or << and std::endl code only for std::string types in binary files!'
|
Phew, a mouth full. I can't believe I just wrote that. So anyway, observe my code below. It will:
1) Create two vectors with some default names/scores.
2) Store these two vectors in a file (overwriting it if it exists).
3) Reopens the file and loads the data in the vectors again, just for inspection.
4) Overwrites the vectors with completely new data.
5) Reopens the file again, and overwrites the file with new names and scores.
6) We clear the vectors.
7) Reopens the file again for reading. Store the data in the cleared vectors.
8) Inspect the vectors again.
Also observe how I close the file, each time I am done with it! And I reset the state of the
ifstream object as well each time.
Just read the comments in the code below:
Code:
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
void generate_data(vector<int>& scores, vector<string>& names);
int main()
{
vector<int> highscores(10, 0); //The top scores.
vector<string> highnames(10, "Default"); //The top names.
//Saving the highscores and names.
ofstream fout("data.dat", ios::binary);
for (int i = 0; i < 10; ++i)
{
fout.write((char *)(&highscores[i]), sizeof(highscores[i]) );
fout <<highnames[i]<<endl;
}
fout.close();
//Loading the scores and names.
ifstream fin("data.dat", ios::binary);
int score;
string name;
while(fin.read((char *)(&score), sizeof(score) ) && getline(fin, name))
{
highscores.push_back(score);
highnames.push_back(name);
}
fin.close();
//IMPORTANT: fin is in error state because it went in an EOF state!
//so reset its state. Otherwise future opening with the "fin object" will fail!
fin.clear();
//Let's inspect what we got.
for(unsigned i = 0; i < 10; ++i)
{
cout<<highnames[i]<<" : "<<highscores[i]<<endl;
}
//Let's overwrite the default data with some random data.
generate_data(highscores, highnames);
//Saving the highscores and names.
fout.open("data.dat", ios::binary);
for (int i = 0; i < 10; ++i)
{
fout.write((char *)(&highscores[i]), sizeof(highscores[i]) );
fout <<highnames[i]<<endl;
}
fout.close();
//Let's open it again to reload it's contents.
fin.open("data.dat", ios::binary);
//First we clear the vectors. So everything that is stored in the vector now
//truly comes from the file, and not from "generate_data()"!
highscores.clear();
highnames.clear();
while(fin.read((char *)(&score), sizeof(score) ) && getline(fin, name))
{
highscores.push_back(score);
highnames.push_back(name);
}
fin.close();
fin.clear();
//Let's inspect what we got.
for(unsigned i = 0; i < 10; ++i)
{
cout<<highnames[i]<<" : "<<highscores[i]<<endl;
}
cin.get();
return 0;
}
//--------------------------------------
void generate_data(vector<int>& scores, vector<string>& names)
{
string AName("");
for (int i = 0; i < 10; ++i)
{
scores[i]=i+1;
AName += "a";
names[i]=AName;
}
}