Code Newbie
News     Forums     Search     Members     Sign Up    

My Code Newbie
Username

Password

Articles/Snippets
ASP Classic
ASP.NET
C
C#
C++
HTML / CSS
Java
Javascript
Linux / BSD
Perl
PHP
Python
Ruby
SQL
VB 6
VB.NET

C.N. Friends
  Planet Rome

Link to Us!
Code Newbie
  Code Newbie
    forums
Old 04-25-2005, 05:26 PM   #1 (permalink)
Dragon9219
Registered User
 
Join Date: Apr 2005
Posts: 3
Dragon9219 is on a distinguished road
Question Help with saving highscores.

Hi, I've been trying to save highscores in the games that I have been trying to make (Simple games like hangman and word jumble in the console application). So far I have been able to save the scores, but not the names. I do not know how to save anything but numbers. What I have been trying to use is:
Code:
vector<int> highscores(10, 0); //The top 10 scores.

vector<string> highnames(10, "Default"); //The top 10 names.

//Loading the scores and names.
ifstream fin("data.dat", ios::binary);
for (int i = 0; i < 10; ++i)
{
    fin.read((char *)(&highscores[i]), sizeof(highscores[i]));
    fin.read((char *)(&highnames[i]), sizeof(highnames[i]));
}

//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.write((char *)(&highnames[i]), sizeof(highnames[i]));
}
fout.close();
This works fine with the scores, but I am not sure what to do with the names. Keep in mind I am VERY new to C++, so any suggestions would also help. Any help would be appreciated.

Last edited by redhead; 04-25-2005 at 11:38 PM.
Dragon9219 is offline   Reply With Quote
Old 04-25-2005, 11:50 PM   #2 (permalink)
redhead
Newbie
 
redhead's Avatar
 
Join Date: Jun 2002
Location: Denmark
Posts: 1,726
redhead is on a distinguished road
Why are you using a binary file ? That might introduce some error in bit swapping ntohl()/htonl()
For this kind of thing I would use a strict text file, then it would be easy to hold a line with name, then a line with score, then a line with name and so on.
Or perhaps a line with name <tab> score, or something simular...
__________________
Don't worry Ma'am, We're university students, We know what We're doing.
-----
If you pull the pin, Mr.Grenade would no longer be your friend.
-----
01000111 01101111 00100000 01000011 00100000 00100001
redhead is offline   Reply With Quote
Old 04-26-2005, 11:44 AM   #3 (permalink)
Valmont
[code][/code] enforcer
 
Valmont's Avatar
 
Join Date: Mar 2003
Location: Netherlands
Posts: 1,544
Valmont is on a distinguished road
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;
  }
}
__________________
Valmont is offline   Reply With Quote
Old 04-26-2005, 02:47 PM   #4 (permalink)
Dragon9219
Registered User
 
Join Date: Apr 2005
Posts: 3
Dragon9219 is on a distinguished road
Thanks, I'm making a lot of progress now, but still one problem. I tryed many different ways but I ended up doing this:

Code:
//Loading
  ifstream fin("data.dat", ios::binary);
  highscores.clear();
  highnames.clear();
  int score;
  string name;
  while(fin.read((char *)(&score), sizeof(score) ) && getline(fin, name))
  {
    highscores.push_back(score);
    highnames.push_back(name);
  }
  fin.close();
  fin.clear();

//Saving.
  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();
If I take out the highscores.clear(), or the highnames.clear() they end up not saving. If I only leave only the highscores.clear() then the scores save but the names go back to default. If I leave both in, ALL the names change to whatever the one name is. Sorry if I missed something, or did something wrong. Could be my highscore code I'm testing it on, if I'm not doing anything wrong here, tell me and I'll post that. Thanks.
Dragon9219 is offline   Reply With Quote
Old 04-26-2005, 03:10 PM   #5 (permalink)
Valmont
[code][/code] enforcer
 
Valmont's Avatar
 
Join Date: Mar 2003
Location: Netherlands
Posts: 1,544
Valmont is on a distinguished road
Mind that the "data.dat" file format has changed with my setup.
So before you load data from file, make sure you saved it my way to file.
__________________
Valmont is offline   Reply With Quote
Old 04-26-2005, 05:11 PM   #6 (permalink)
Dragon9219
Registered User
 
Join Date: Apr 2005
Posts: 3
Dragon9219 is on a distinguished road
Thank you very much! I finally got it working! I had been trying to do this for quite a few days (I'm really new to C++). Thanks again.
Dragon9219 is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
Cleaning up posted variables before saving. Admin PHP 3 05-14-2004 10:41 AM


All times are GMT -8. The time now is 06:13 AM.


Powered by vBulletin® Version 3.7.0
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.0.0 RC8





Copyright © 2000-2008, Milano Interactive
Web Hosting provided by Portal 360 Web Hosting