CPlayer * CPlayer::LoadSavedPlayer(string loadName)
{
ifstream loadPlayer("Players.dat", ios::in | ios::binary);
CPlayer * cmpPlayer;
loadPlayer.read((char *)&cmpPlayer, sizeof(CPlayer));
while(!strcmp(playerName.c_str(), loadName.c_str()))
{
if (loadPlayer.eof())
{
cout << endl << "That player was not found.";
getch();
loadPlayer.close();
return 0;
}
loadPlayer.read((char *)&cmpPlayer, sizeof(CPlayer));
}
// load the CPlayer class if match found
loadPlayer.close();
return cmpPlayer;
}
CPlayer * PromptNewPlayer()
{
CPlayer * pTempPlayer;
cout << endl << "Enter the name of the player you would like to load.";
cout << endl;
cin >> loadPlayer;
pTempPlayer = pTempPlayer->LoadSavedPlayer(loadPlayer);
return pTempPlayer;
}
Now, I don't think I have the file search/load class routine written correctly. How should I be doing this?
---
Joker2000
Stevie Ray Vaughan - The Legend
Edited by - Joker2000 on 7/24/00 10:08:56 PM
file i/o error and more
For some reason I get an application-defined exception when this line of my code executes.
while(!strcmp(playerName.c_str(), loadName.c_str()))
The purpose of the routine is to search a file for the name the user enters, then load the CPlayer class with that data. Here's a little more of the routine.
---Joker2000Stevie Ray Vaughan - The Legend
Come on, people...throw me a fricken bone here! This problem is really ticking me off!
---
Joker2000
Stevie Ray Vaughan - The Legend
---
Joker2000
Stevie Ray Vaughan - The Legend
---Joker2000Stevie Ray Vaughan - The Legend
a error,
CPlayer * PromptNewPlayer()
{
CPlayer * pTempPlayer;
.....
pTempPlayer = pTempPlayer->LoadSavedPlayer(loadPlayer); return pTempPlayer;
}
you dont allocate a object, you are using a uninitialized pointer.
CPlayer * pTempPlayer;
must (or can be)
CPlayer * pTempPlayer = new CPlayer;
CPlayer * PromptNewPlayer()
{
CPlayer * pTempPlayer;
.....
pTempPlayer = pTempPlayer->LoadSavedPlayer(loadPlayer); return pTempPlayer;
}
you dont allocate a object, you are using a uninitialized pointer.
CPlayer * pTempPlayer;
must (or can be)
CPlayer * pTempPlayer = new CPlayer;
Ries
one more, string compare returns zero when they are equal
while(!strcmp(playerName.c_str(), loadName.c_str()))
must be(can be)
while( strcmp(playerName.c_str(), loadName.c_str()) != 0 )
or simply
while( strcmp(playerName.c_str(), loadName.c_str()) )
while(!strcmp(playerName.c_str(), loadName.c_str()))
must be(can be)
while( strcmp(playerName.c_str(), loadName.c_str()) != 0 )
or simply
while( strcmp(playerName.c_str(), loadName.c_str()) )
Ries
Claus Hansen Ries:
Now in here, you try to write to loadPlayer which is openned for read and not write second, as Claus Hansen Ries was saying, your trying to write to an uninitialized pointers. Anyhow, this is what I can see at first hand. If that is not it, let us know...
Cyberdrek
Headhunter Soft
DLC Multimedia
while(!strcmp(playerName.c_str(), loadName.c_str()))[/source]this is a valid way of doing it also. It''s the exact same thing as doing[source] while( strcmp(playerName.c_str(), loadName.c_str()) != 0 )[/source]both methods are good but that not the problem. Joker2000: Here is where I get confused in reading your code:[source]CPlayer * PromptNewPlayer(){ CPlayer * pTempPlayer; cout << endl << "Enter the name of the player you would like to load."; cout << endl; cin >> loadPlayer; pTempPlayer = pTempPlayer->LoadSavedPlayer(loadPlayer); return pTempPlayer;}
Now in here, you try to write to loadPlayer which is openned for read and not write second, as Claus Hansen Ries was saying, your trying to write to an uninitialized pointers. Anyhow, this is what I can see at first hand. If that is not it, let us know...
Cyberdrek
Headhunter Soft
DLC Multimedia
[Cyberdrek | ]
You got me for a moment =), BUT
Yes it is a vaild way, BUT THEY ARE NOT EQUAL METHODS =)
while(!strcmp(playerName.c_str(), loadName.c_str()))
Is the same as saying "while strcmp returns zero" (!ZERO -> TRUE)
however
while( strcmp(playerName.c_str(), loadName.c_str()) != 0 )
Is saying "while strcmp is not returning zero" (NOT EQUAL ZERO -> TRUE)
strcmp return zero when "playerName.c_str() == loadName.c_str()"
So he jump out of the "while" when the names are not equal, but he want to continue in the loop when the names aren't equal.
Edited by - Claus Hansen Ries on July 25, 2000 6:30:37 AM
Yes it is a vaild way, BUT THEY ARE NOT EQUAL METHODS =)
while(!strcmp(playerName.c_str(), loadName.c_str()))
Is the same as saying "while strcmp returns zero" (!ZERO -> TRUE)
however
while( strcmp(playerName.c_str(), loadName.c_str()) != 0 )
Is saying "while strcmp is not returning zero" (NOT EQUAL ZERO -> TRUE)
strcmp return zero when "playerName.c_str() == loadName.c_str()"
So he jump out of the "while" when the names are not equal, but he want to continue in the loop when the names aren't equal.
Edited by - Claus Hansen Ries on July 25, 2000 6:30:37 AM
Ries
Problem 1 (though not really a problem) you are using stl::string
so why strcmp? while(PlayerName != LoadName) looks better, ain't confusing and *might* even be faster. Plus, it's safe string classes know thier own size, so they don't have to look for '\0'.
That being said, that ain't the problem. What happens when you do this?
The only tricky bit is you must now remeber to create a Copy_To_FileRec(PlayerFileRec &rec) that uses
strncpy and c_str as apropriate before writeing (using write(*,size)) to Player.dat.
Note also that the use of read((char *)this,sizeof(PlayerFileRec) might be a bit too hackish for some, and come to think of it, may not compile. The point is never use read and write on anything but pod (plain old data).
Edited by - Grib on July 25, 2000 1:54:27 PM
Edited by - Grib on July 25, 2000 1:56:10 PM
stupid tags, this time It'll work!
Edited by - Grib on July 25, 2000 1:58:58 PM
so why strcmp? while(PlayerName != LoadName) looks better, ain't confusing and *might* even be faster. Plus, it's safe string classes know thier own size, so they don't have to look for '\0'.
That being said, that ain't the problem. What happens when you do this?
class Dynamic { int *Data; int size;public: Dynamic(int s) : size(s), Data(new int[size]) {}};Dynamic a(20),b(30);out.write((char *)&a,sizeof(Dynamic));in.read((char *)&b, sizeof(Dynamic)); [/source] Answer, <strong>pain</strong>. The first line writes, not the contents of the memory Data points to, but the address stored inData. When you read b.Data points to the memory that a allocatedfor it's data. Chaging b changes a and vice versa.Now, what do you suppose string does after all the handwaving and char_traits and so forth. Yep, a pointer to the heap, just likeDyanamic above.The easyest way around this is to read/write your records as ascii and overload << and >>. This does get slow and wastefull eventually, so you want a file record structure. [source]struct PlayerFileRec { char playerName[80]; float x,y,x; int health;etc... bool LoadSavedPlayer(istream ∈,const string &loadName);};bool PlayerFileRec::LoadSavedPlayer(istream ∈,const string &loadname) { do { in.read((char *)this,sizeof(PlayerFileRec)); if(loadName == playerName) return true; } while(in.good()); return false;}// Add this method to CPlayerCPlayer & CPlayer::Copy_From_FileRec(const PlayerFileRec &r) { PlayerName = r.PlayerName; x = r.x; y = r.y; etc.. return *this;}// Your new CPlayer::LoadSavedPlayer now looks likebool CPlayer::LoadSavedPlayer(const string &loadName) { ifstream in("Players.dat",ios::in | ios::binary); PlayerFileRec rec; bool status = rec.LoadFromFile(in,loadName); if(status) { Copy_From_FileRec(rec); } else { cerr << "Player " << loadName << " Not Found" << endl; } in.close(); return status;}
The only tricky bit is you must now remeber to create a Copy_To_FileRec(PlayerFileRec &rec) that uses
strncpy and c_str as apropriate before writeing (using write(*,size)) to Player.dat.
Note also that the use of read((char *)this,sizeof(PlayerFileRec) might be a bit too hackish for some, and come to think of it, may not compile. The point is never use read and write on anything but pod (plain old data).
Edited by - Grib on July 25, 2000 1:54:27 PM
Edited by - Grib on July 25, 2000 1:56:10 PM
stupid tags, this time It'll work!
Edited by - Grib on July 25, 2000 1:58:58 PM
Ok, I''ve slightly edited my code to fix some of the minor issues, so below I have made a few changes. I am very interested in Grib''s solution, but I''m not exactly sure how to do it. I know he pretty much listed the exact code I need to use, but I''m still looking over it, trying to understand everything. So I''ll probably be sending Grib an email or two to help me straighten things out. In the meantime, please feel free to post any and all solutions. I need the help!
---
Joker2000
Stevie Ray Vaughan - The Legend
CPlayer * CPlayer::LoadSavedPlayer(string loadName){ ifstream loadPlayer("Players.dat", ios::in | ios::binary); CPlayer * cmpPlayer = new CPlayer("Empty", false, 0, 0, 0, 0, 0, 0); loadPlayer.read((char *)&cmpPlayer, sizeof(CPlayer)); while(playerName != loadName) { if (loadPlayer.eof()) { cout << endl << "That player was not found."; getch(); loadPlayer.close(); return 0; } loadPlayer.read((char *)&cmpPlayer, sizeof(CPlayer)); } // match found...load CPlayer data class loadPlayer.close(); return cmpPlayer;}void CPlayer::SavePlayer(CPlayer * thePlayer, CWeapon * theWeapon){ ofstream savePlayer("Players.dat", ios::out | ios::app | ios::binary); savePlayer.write((char *)&thePlayer, sizeof(CPlayer)); savePlayer.close();}CPlayer * PromptNewPlayer(void){ string loadPlayer; CPlayer * pTempPlayer; cout << endl << "Enter the name of the player you would like to load."; cout << endl; cin >> loadPlayer; pTempPlayer = pTempPlayer->LoadSavedPlayer(loadPlayer); break;}
---
Joker2000
Stevie Ray Vaughan - The Legend
---Joker2000Stevie Ray Vaughan - The Legend
quote: Original post by Joker2000
Ok, I''ve slightly edited my code to fix some of the minor issues, so below I have made a few changes. I am very interested in Grib''s solution, but I''m not exactly sure how to do it. I know he pretty much listed the exact code I need to use, but I''m still looking over it, trying to understand everything. So I''ll probably be sending Grib an email or two to help me straighten things out. In the meantime, please feel free to post any and all solutions. I need the help!
---
Joker2000
Stevie Ray Vaughan - The Legend
Ok you still have the problem that you are using read/write on
classes that have pointers. read/write will save the value of the pointer, not what that pointer points to.
string astr;ifstream in("filename.dat",ios::binary);in.read((char *)&astr,sizeof(string));
will NEVER work, even if string is a member of a
class. It only works for classes have no pointers/references/static members,
have no virtual functions, and all member classes are the
same way.
I strongly recomend that the first version of your players.dat
file should be simple ascii text. load each member with >>
save each member with << just put whitespace between each member that you output, newlines after each record/class.
You can now edit your data files with a text editor, and spot errors that much more easily.
You do realize that the whole point is to write the file in a format the user CANNOT read to prevent him from changing values and such, right? Will >> and << still "encrypt" them if I'm using ios::binary?
Well, I think I can pretty much say that the ios::binary won't do what I want as far as making the player data impossible to edit. I just tried it out using << and >> with straight ASCII text and it shows up normally. I know this is what Grib said I should do for my first version of Players.dat. So then I ask...what next?
---
Joker2000
Stevie Ray Vaughan - The Legend
Edited by - Joker2000 on July 25, 2000 5:58:51 PM
Well, I think I can pretty much say that the ios::binary won't do what I want as far as making the player data impossible to edit. I just tried it out using << and >> with straight ASCII text and it shows up normally. I know this is what Grib said I should do for my first version of Players.dat. So then I ask...what next?
---
Joker2000
Stevie Ray Vaughan - The Legend
Edited by - Joker2000 on July 25, 2000 5:58:51 PM
---Joker2000Stevie Ray Vaughan - The Legend
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement