issue with fstream

Please help. As a test I called a function to read a txt file and display it. It doesnt work. Here is the code,
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

#include <iostream>
#include <istream>
#include <fstream>
#include <sstream>
#include <string>


using namespace std;

string command1;
string maincommand;
string exitcommand;


int GameStart()
{
string stringtest;
  ifstream teststring ("C:\\Users\\Jacodi\\Desktop\\LEMONADE EMPIRE\\ini folder\\SampleTxt.txt");
  if (teststring.is_open())
  {while (!teststring.eof());
  {getline(teststring, stringtest);
  cout << stringtest;}}
  cin.get();
}


int commandsys()
{
    //Command: GameStart
    if (maincommand == "/GameStart")
    {GameStart();}
    //Command: Help
    if (maincommand == "/help")
    {helpscreen();}
    //Command : Command List
    if (maincommand == "/commandlist") 
    {commandlist();}
    //Main Menu
    if (maincommand == "/back to start")
    {}


}





    









int main()

{    loop:
     cout << "Intro text"<< endl;
     loop2:
     getline (cin,maincommand);
     commandsys();
     
     if (maincommand == "/back to start")
        {goto loop;}
        
        else {goto loop2;}

     
    cin.get();
    return 0;
}



What i want it to do is type the custom command "/GameStart" and have it display what is in the txt file.

I copy pasted the file location into RUN.exe and it worked and displayed txt in the file. But when I load my program and type "/GameStart" It doesnt do anything.

I have left out the functions that pertain to other commands. However, the other commands all work correctly.

So I feel like im missing something or doing something wrong in the GameStart function.
You should not really loop on teststring.eof() because that flag will not be set until *after* the failed read. That means that your last getlin()e will fail, but go unchecked.

Its better to write it something like this:
1
2
3
4
5
6
7
8
9
10
11
int GameStart()
{
string stringtest;
  ifstream teststring ("C:\\Users\\Jacodi\\Desktop\\LEMONADE EMPIRE\\ini folder\\SampleTxt.txt");
  while (getline(teststring, stringtest))
  {
    // this will only happen if file is open and getline() was successful
    cout << stringtest;
  }
    cin.get();
}
Last edited on
Your actual error is on line 21:
 
 {while (!teststring.eof()); // the semicolon ';' is completing your while loop 

Because of the semicolon after the while() statement, the while() is not recognising the body { } as part of the loop. Remove the semicolon like this:
 
 {while (!teststring.eof()) // no semicolon ';'  

With while() you can have either a semicolon ';' *or* a body { } but not both.
Last edited on
thank you galik, but i'm not sure I understand the first reply. Im not understanding the logic of it. As in, i don't know how to process that in my head.

I think of the while statement as a precursor matching a condition to execute a specific code. So in the one i used, {while (!teststring.eof()) ... } I think of it as, While the following condition is met [string called by "teststring" is NOT at the end of it's field.] then do the following. (which was to repeat and feed it piece by piece to cin)

I can tell that it is unorganized and looks etchy. And I can see that your way seems much cleaner, and more organized. (Also has less code)

So if you could, Could you expain how you did that while statment and why you didnt need an If?
Oh and also, why is it not needed to do the while that i used? Will the code you sugested read all the parts of a text file (from beginning to end)?
Let me comment your code explaining what can go wrong:
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
int GameStart()
{
	string stringtest;
	ifstream
		teststring(
			"C:\\Users\\Jacodi\\Desktop\\LEMONADE EMPIRE\\ini folder\\SampleTxt.txt");

	if(teststring.is_open())
	{
		while(!teststring.eof())
		{
			// now we know that the eof flag is not set.
			// BUT we still could have finished reading the file.
			// That is because the EOF flag is only set AFTER we try
			// to read and discover there is nothing remaining in the file.

			getline(teststring, stringtest);
			// that getline() above will eventually trigger the EOF condition
			// when it does it will have failed to read anything from the file
			// and therefore the contents of 'stringtest' will be undefined

			// so this instruction will execute after the EOF
			// condition has been triggered by the previous read.
			cout << stringtest;
		}
	}
	cin.get();
}


If you look at std::getline() it returns the input stream that it was called with. And we can do an if() test on any input stream to test if it is in a readable state.

For example, we can do:
1
2
3
4
5
6
std::ifstream ifs("myfile.txt");

if(ifs)
{
	// file must be open and EOF is not set.
}

So we can use that to our advantage and test the returned input stream from the std::getline() function like this:
1
2
3
4
5
6
7
8
9
10
std::ifstream ifs("myfile.txt");

std::string line;

while(std::getline(ifs, line))
{
	// file must be open and EOF is not set.
	
	// ALSO line MUST contain valid data
}

That will indeed read *every* line because std::getline() will only return false if it fails to read the line, most likely because of EOF.
Last edited on
Okay i think the last thing that is confusing me so much is the std:: form of statments.
I'm thinking that you use it to specify where in the included lbrary to look. because thats what i learned to use "using namespace std;" for. So do i still use the std:: type names when I have "using... std" ? or is it like an either or? (put the std:: on the parts that need it OR issue "using namespace std;" in the beginning and thereby don't need to use (std::)" ?
I use std:: because its the right thing to do ;o)

Having using namespace std; is strongly discouraged for anything other than trivial example programs. It introduces an unknown number of symbols into the global namespace and can cause subtle hard to discover bugs.
Ok so, its like std being a book, and by using "namesapce std;" you tell it to use that specific book.

but that means that more is input that isnt covered or noticed.

So using std::string etc etc tells it exactly what page of the book to look for and besides that, the rest of the book is ignored until another "specific page" is called upon?
Yes, its a bit like that.

There are a lot of common names in the std namespace like count(), find(), sort() ... etc and they can easily clash with other headers that your program might include or the symbols you use in your program.
Topic archived. No new replies allowed.