Writing variables to a text file

Apr 28, 2014 at 3:56pm
Hello,

I'm new to C++ and I'm trying to write two variables to a text file. They are basically a players name and their score but formatted as shown.

The text file consists of 3 tab spaces, then a name, a comma, a space, then a number. i.e:

Test1, 10
Test2, 30
Test3, 50

(tabs aren't showing for some reason)

perhaps something like this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "stdafx.h"
#include "math.h"
#include <Windows.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std; 

// Variables
string PlayerName="Name1";
int PlayerScore=200;

int main()
{
	ofstream HighScoreFile;
	HighScoreFile.open("highscores.txt");
	HighScoreFile.close();

return 0;
}


I'm not sure what the best way of doing this would be.

Thank you =)
Last edited on Apr 28, 2014 at 3:58pm
Apr 28, 2014 at 4:02pm
You could comfortably do that with the insertion operators, as if with std::cout.

1
2
HighScoreFile.seekp(0,std::ios::end); //to ensure the put pointer is at the end
HighScoreFile<<"\t\t\t"<<PlayerName<<", "<<PlayerScore;


Aceix.
Apr 28, 2014 at 4:05pm
I've just noticed it keeps overwriting what is already there, it doesn't seem to add to the end of the file each time i run the program... hmm...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "stdafx.h"
#include "math.h"
#include <Windows.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std; 

// Variables
string PlayerName="Name1";
int PlayerScore=200;

int main()
{
	ofstream HighScoreFile;
	HighScoreFile.open("highscores.txt");
	HighScoreFile << "\t\t\t" << PlayerName << ", " << PlayerScore << "\n";
	HighScoreFile.close();

	HighScoreFile.seekp(0,std::ios::end); //to ensure the put pointer is at the end
	HighScoreFile<<"\t\t\t"<<PlayerName<<", "<<PlayerScore;

return 0;
}
Last edited on Apr 28, 2014 at 4:16pm
Apr 28, 2014 at 4:17pm
Correct you got the opening of a file down now you just need to do the actual writing to the file.

First let me clarify, you want this format for your text file correct?

<tab><tab><tab><name>, <score>
<tab><tab><tab><name>, <score>
....
....


If so this is how you would go about accomplishing this. First let's go over opening up a text file and writing to it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main()
{
    std::ofstream highScoreFile("highscores.txt");
    
    // Always check to see if the file is open and for errors.
    if (highScoreFile.is_open())
    {
        // If it is open we can do our writing to the file.
        // Here is a example of this.
        highScoreFile << "I am writing to the file!";
    }
    else
    {
        // If the file isn't open something went wrong. Point that out.
        std::cout << "Something went wrong with opening the file!";
    }

    // After you are done with the file always close it.
    highScoreFile.close();
}
    


It is quite easy to write to a file. It is just like writing to the console with std::cout.

Though a important thing to note is that when you use the default ofstream constructor (Like I did above) it is in truncate mode which means it will discard anything in the file already and start over. This is why everything is being deleted.

In order for that not to happen open you file like this.

std::ofstream HighScoreFile("highscores.txt", std::ofstream::out | std::ofstream::app);

or with

open("highscores.txt", std::ofstream::out | std::ofstream::app);

std::ofstream::out means you want to output to the file (Write to it) and std::ofstream::app means you want to append to the file (don't overwrite everything).

Here is some more about the different flags http://www.cplusplus.com/reference/fstream/ofstream/ofstream/

HighScoreFile.open(
Now next up we need to know how to get the formatting right on your text file. As mentioned before you want <tab><tab><tab><name>, <score> for the format I believe.

All you will need to do is write them to the file in that order. Here is some pointers for how to write tabs and newlines (Creates a new line) if you didn't know already.

<tab> = "\t"
<newline> = "\n"

So your format would be like this. playerName = the variable which holds the name, playerNumber is the variable which holds that players number.
highScoreFile << "\t\t\t" << playerName << ", " << playerNumber << "\n";

Hopefully that helps a bit. Let me know if you have any specific questions or if anything is confusing.
Last edited on Apr 28, 2014 at 4:22pm
Apr 28, 2014 at 4:24pm
What about opening it this way: HighScoreFile.open("highscores.txt",ios::app|ios::ate);

Aceix.
Apr 28, 2014 at 4:35pm
Thank you both for you help, it's been really useful =)

What I have ended up with is :-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "stdafx.h"
#include "math.h"
#include <Windows.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std; 

// Variables
string PlayerName="Name1";
int PlayerScore=200;

// Functions
void SaveScore()
{
	ofstream HighScoreFile;
	HighScoreFile.open("highscores.txt",ios::app|ios::ate);
	HighScoreFile << "\t\t\t" << PlayerName << ", " << PlayerScore << "\n";
	HighScoreFile.close();

	HighScoreFile.seekp(0,std::ios::end); //to ensure the put pointer is at the end
	HighScoreFile<<"\t\t\t"<<PlayerName<<", "<<PlayerScore;
}

int main()
{
	SaveScore();

return 0;
}


However with the 'using namespace std; ' does it need the std:: parts? I'm not entirely sure what they mean.
Last edited on Apr 28, 2014 at 4:39pm
Apr 28, 2014 at 4:42pm
OP wrote:
However with the 'using namespace std; ' does it need the std:: parts? I'm not entirely sure what they mean.


No. The std is a namespace for the standard C++ library. Doing something like std::xxx means, use xxx in std. So using std doesn't need std::xxx anymore, just xxx.

Aceix.
Last edited on Apr 28, 2014 at 4:42pm
Apr 28, 2014 at 4:47pm
Hmm, when I remove the 'std::' it only overwrites what is in the text file again, not adding to the end of it... Sorry but I'm still a little confused.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "stdafx.h"
#include "math.h"
#include <Windows.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std; 

// Variables
string PlayerName="Name1";
int PlayerScore=200;

// Functions
void SaveScore()
{
	ofstream HighScoreFile;
	HighScoreFile.open("highscores.txt",ios::app|ios::ate);
	HighScoreFile << "\t\t\t" << PlayerName << ", " << PlayerScore << "\n";
	HighScoreFile.close();

	HighScoreFile.seekp(0,ios::end); //to ensure the put pointer is at the end
	HighScoreFile<<"\t\t\t"<<PlayerName<<", "<<PlayerScore;
}

int main()
{
	SaveScore();

return 0;
}
Last edited on Apr 28, 2014 at 4:50pm
Apr 28, 2014 at 4:53pm
it only overwrites what is in the text file

That's because the default mode (2nd parameter to open) is truncate.

Try this to append to the file as Aceix suggested:
 
  HighScoreFile.open ("highscores.txt", ios::app);


Lines 20 and 21 won't work because the file is closed at line 18.


Last edited on Apr 28, 2014 at 4:54pm
Apr 28, 2014 at 5:14pm
Ok I think I have stumbled into waters a little too deep for me at the moment. For the sake of my learning I went with: -

1
2
3
4
5
6
7
void SaveScore()
{
	ofstream HighScoreFile;
	HighScoreFile.open("highscores.txt",ios::app);
	HighScoreFile<<"\t\t\t"<<PlayerName<<", "<<PlayerScore<<"\n";
	HighScoreFile.close();
}


Probably not the cleanest way of doing it but I'll revisit this another time.

Thank you very much for your help =)
Last edited on Apr 28, 2014 at 5:16pm
Apr 28, 2014 at 5:22pm
Not the most efficient, but it works.

Keep in mind that the open of the file can fail.
Apr 28, 2014 at 5:51pm
AbstractionAnon wrote:
Keep in mind that the open of the file can fail.

This is definitely something that you should always check for. The open can fail from something as little as the text file not being in the right spot to even more rare causes. So you should always be checking to see that it opened correctly before continuing.

In you example it would look something like this (Heavy commenting).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void SaveScore()
{
	ofstream HighScoreFile;
	HighScoreFile.open("highscores.txt",ios::app);

	// This is how you check to make sure there was no errors while 
	// opening the file. Always do this check and then just put the
	// operation you wish to do inside the if brackets.
	if (HighScoreFile.is_open())
	{
		HighScoreFile<<"\t\t\t"<<PlayerName<<", "<<PlayerScore<<"\n";
		HighScoreFile.close();
	}
	else // What to do if we do fail to open the file
	{
		// In here you can do whatever you want to do when the file
		// fails to open. It might just be as simple as printing something 
		// simple to the console like this.
		cout << "Failed to open the file!";

		// Or you could go into much deeper error handling like trying to 
		// fix the problem (Find the correct path to the file, or other things).
	}		
}


Usually it is just a simple if statement like that to check if the open worked and to handle any errors (You can also get into exceptions but that is a bit more advanced).
Topic archived. No new replies allowed.