CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Nov 2011
    Posts
    10

    [RESOLVED] null terminating character removed

    Hi,
    I am reading a binary file to string to update it and write it back again. When I add (append) user profiles in the binary file and read it again, every thing is oki because a null terminating character is generated after every user profile.

    My problem is when I have for example 3 users and update the first one. When I update the first or second user profile, the null terminating character is removed and the rest of the contents are shifted backward ruining my data when read in binary mode again.

    To update a user profile I am using this to modify my string:

    Code:
    buff.replace((rec*sizeof(sPlayer))-sizeof(sPlayer.szLastword), sizeof(sPlayer.szLastword), word.data());

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,430

    Re: null terminating character removed

    Quote Originally Posted by trojsi View Post
    To update a user profile I am using this to modify my string:
    Code:
    buff.replace((rec*sizeof(sPlayer))-sizeof(sPlayer.szLastword), sizeof(sPlayer.szLastword), word.data());
    And what are all these operands, objects, etc (well, we know what sizeof is)
    Victor Nijegorodov

  3. #3
    Join Date
    Nov 2011
    Posts
    10

    Re: null terminating character removed

    Quote Originally Posted by VictorN View Post
    And what are all these operands, objects, etc (well, we know what sizeof is)
    Okay, this is a hangman game and at the end of each game I want to update the last word guessed not to be chosen next time the user plays in his profile selected.

    I am declaring a global struct:

    Code:
    struct PlayerInfo
    {
    	char	szName[20];
    	short		  nAge;
    	int			nScore;
    	char	szLastword[20];
    };
    sPlayer.szLastword is updated everytime after each game.

    When user profiles (new users) are added one after each other, the data is updated properly and (null termination applied correctly) and therefore it is written correctly in the binary file so that when it is read again by putting each entry in the correct struct member, the data is displayed perfectly. However when I select a user profile at the beginning of the game, and after I go to modify only the szLastword, in the string (by string replace) - for some reason, the null terminated character is ommited and my data shifts backward causing the fread to view mixed data. I used a function to add white space to the guessedword in order to resize it to sizeof(sPlayer.szLastword). I could observe that the rest of the user profiles all of them shifted by 1 character which I assume is the null terminator because I saw it from the debugging.

    Most probably, the string replace is not leaving the null terminator.

  4. #4
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,430

    Re: null terminating character removed

    Quote Originally Posted by trojsi View Post
    I am declaring a global struct:

    Code:
    struct PlayerInfo
    {
    	char	szName[20];
    	short		  nAge;
    	int			nScore;
    	char	szLastword[20];
    };
    And what is buff, replace, sPlayer, word, data?

    Quote Originally Posted by trojsi View Post
    ... when I select a user profile at the beginning of the game, and after I go to modify only the szLastword, in the string (by string replace) - for some reason, the null terminated character is ommited and my data shifts backward causing the fread to view mixed data. I used a function to add white space to the guessedword in order to resize it to sizeof(sPlayer.szLastword). I could observe that the rest of the user profiles all of them shifted by 1 character which I assume is the null terminator because I saw it from the debugging.
    If you saw it from the debugging then you should find a way to fix your code!
    Note that we cannot do it for you because we have no idea about your file structure.
    Victor Nijegorodov

  5. #5
    Join Date
    Nov 2011
    Posts
    10

    Re: null terminating character removed

    This is update part in the main:

    Code:
     int main() {
    
    fstream fread; // read and write streams
    	
    	fread.open(pszFileName, ios_base::in | ios_base::out | ios_base::binary);
    	
    	string buff;
    	char tempChar;
    
    	while ( !fread.eof() ) 
    	
    	{
    	    fread.get(tempChar);
    		buff += tempChar;
    	}
        
        fread.clear(); // clear eof flag
    
    	fread.close();
    
    	test = sizeof(sPlayer.szLastword) - iLength;
    
    	for(int i = 0; i < (test-1) ; i++)
    	
    	{
    		word.append(" ");
    		
    	}
    
    	buff.replace((rec*sizeof(sPlayer))-sizeof(sPlayer.szLastword), sizeof(sPlayer.szLastword), word.data());
    	
    	fstream fupdate;
    
    	fupdate.open(pszFileName, ios_base::out | ios_base::binary);
    	
    	if (fupdate.is_open() == true)
    	{
    		
    		fupdate.write(buff.data(), buff.length()) << flush;
    		
    	}
    	
    	else
    	{
    		cout << "Failed to open file " << pszFileName << endl;
    	}
    	
    
    	if (fupdate.fail())
    
    	{
    		cerr << "Error on attempted write" << endl;
    		exit(EXIT_FAILURE);
    	}
    
    	word.erase(0);
    
    
    	
    	
    	return 0;
    
    
    }
    this is the select user function :

    Code:
     void SelectUser()
    
    {
    	
    	
    	// show initial contents
    	fstream finout; // read and write streams
    	finout.open(pszFileName, ios_base::in | ios_base::out | ios_base::binary);
    	
    
    	int ct = 1;
    	
    	if (finout.is_open())
    	{
    		finout.seekg(0); // go to beginning
    		cout << "Here are the current contents of " << pszFileName << endl << endl ;
    	
    		while (finout.read((char *) &sPlayer, sizeof(sPlayer)))
    		{
    			
    			cout << ct++ << ": " << sPlayer.szName << " "
    			<< sPlayer.nAge << " " << sPlayer.nScore << " "
    			<< sPlayer.szLastword << " "<< endl;
    		}
    
    	
    		if (finout.eof())
    			finout.clear(); // clear eof flag
    
    		else
    		{
    			cerr << "Error in reading “ << file << “.\n";
    			exit(EXIT_FAILURE);
    		}
    	}
    	else
    	{
    		cerr << pszFileName << "could not be opened -- bye.\n";
    		exit(EXIT_FAILURE);
    	}
    
    	cout << "Please Select a User Profile." << endl << endl;
    
    	// change a record
    	
    	cin >> rec;
    	eatline(); // get rid of newline
    
    	if (rec < 0 || rec >= ct)
    	{
    
    		cerr <<"Invalid record number -- bye\n";
    		exit(EXIT_FAILURE);
    	}
    
    	streampos place = rec * sizeof(sPlayer); // convert to streampos type
    	finout.seekg(place); // random access
    
    	
    
    	if (finout.fail())
    	{
    		cerr << "Error on attempted seek\n";
    		exit(EXIT_FAILURE);
    	}
    
    	finout.read((char *) &sPlayer, sizeof(sPlayer));
    	
    	cout << "Your selection:\n";
    	cout << rec << ": " << sPlayer.szName << " "
    	<< sPlayer.nAge << " " << sPlayer.nScore << " "
    	<< sPlayer.szLastword << " "<< endl;
    	
    	if (finout.eof())
    	finout.clear(); // clear eof flag
    
    	finout.close();
    	
    	
    }

    and this is the adduser function :

    Code:
     void Adduser()
    
    {
    	
    //USER INPUT //
    
    	cout << "Enter your Name: ";
    	cin >> sPlayer.szName;
    	cout << endl;
    	cout << "Enter your Age: ";
    	cin >> sPlayer.nAge;
    	cout << endl;
    	//cout << "Enter your Score: ";
    	//cin >> newPlayer.nScore;
    	//cout << endl;
    	//cout << "Enter your Lastword: ";
    	//cin >> newPlayer.szLastword;
    
    	cout << "The size of Infowrite is " << sizeof(sPlayer) << endl;
    	
    	
    
    	ofstream addFile;
    
    	addFile.open(pszFileName, ios::out | ios::app | ios_base::binary);
    
    	if (addFile.is_open() == true)
    	{
    		//addFile.seekg(0, ios::end);
    		addFile.write((char*) &sPlayer, sizeof(sPlayer));
    		
    	}
    	else
    	{
    		cout << "Failed to open file " << pszFileName << endl;
    	}
    
    	addFile.close();
    
    	ifstream inf(pszFileName);
    	
    	if (!inf)
       {
            // Print an error and exit
            cerr << "Sry, Test.dat could not be opened for reading!" << endl;
            exit(1);
       }
    	
    	inf.seekg(0, ios::end); // move to end of file
    	rec = ((inf.tellg())/sizeof(sPlayer));
    	cout << rec << endl;
    	system("pause");
    }

  6. #6
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,725

    Re: null terminating character removed

    1) string::data() does not necessarily append a null character

    2) the version of string::replace() you are using does not copy the NULL character.
    You need to explicitly do that.

    3) One solution (assuming I did the arithmetic correctly) ...
    Code:
    const int n1 = rec*sizeof(sPlayer)-sizeof(sPlayer.szLastword);
    const int n2 =  sizeof(sPlayer.szLastword);
    
    buff.replace( n1 , n2 , word.c_str() );
    
    if (word.size() < n2)
      buff[n1+word.size()] = 0;
    else
      buff[n1+n2-1] = 0;

  7. #7
    Join Date
    Nov 2011
    Posts
    10

    Re: null terminating character removed

    Quote Originally Posted by VictorN View Post
    And what is buff, replace, sPlayer, word, data?

    If you saw it from the debugging then you should find a way to fix your code!
    Note that we cannot do it for you because we have no idea about your file structure.
    Do you think my method is correct and suitable for what I want to do, or do you suggest another technique to update profiles in a binary file please?

  8. #8
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,430

    Re: null terminating character removed

    Quote Originally Posted by trojsi View Post
    Do you think my method is correct and suitable for what I want to do, or do you suggest another technique to update profiles in a binary file please?
    I have no idea how you are going to use these user profiles, but you could consider using registry rather than a binary file.
    Or, perhaps, some simple database like MS Access...
    Victor Nijegorodov

  9. #9
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: null terminating character removed

    Quote Originally Posted by VictorN
    Or, perhaps, some simple database like MS Access...
    Or SQLite!
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  10. #10
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,637

    Re: null terminating character removed

    I don't understand why you're replacing the last word instead of just overwriting it. Use strcpy to write to szLastWord and the NULL will be put there for you.

  11. #11
    Join Date
    Nov 2011
    Posts
    10

    Re: null terminating character removed

    Quote Originally Posted by GCDEF View Post
    I don't understand why you're replacing the last word instead of just overwriting it. Use strcpy to write to szLastWord and the NULL will be put there for you.
    Cheers, that did the trick

    Thanks everyone who gave other suggestions. I would have looked into the database thing if I had more time ..

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured