fstream files as true

I was writing a program to check if a username has already been logged on a separate file. I saw somewhere that using getLine with fstream will return the file variable true if the file line is not empty. I ran into a few errors but after solving them I noticed that the while loop which runs if the file variable is true runs even without the getLine before it. Since I'm new I want to understand why the file is seen as true?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 bool userCheckFunction()
{
    std::string UserInfo;
    std::ifstream file;

    file.open("UserInfo.txt");

    while (file)
    {
        getline(file, UserInfo);

        if (UserInfo == userName)
        {

            return true;
            file.close();
        }
        else if (UserInfo != userName && !file)//runs only if the file is not true as to not trigger everytime the while loop runs
        {
            return false;
            file.close();
        }
    }
}
See operator bool() https://en.cppreference.com/w/cpp/io/basic_ios/operator_bool

This operator makes it possible to use streams and functions that return references to streams as loop conditions, resulting in the idiomatic C++ input loops such as while(stream >> value) {...} or
while(getline(stream, string)){...}. Such loops execute the loop's body only if the input operation succeeded.


This would be more idiomatic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool userCheckFunction( const std::string& UserName )
{
    static const std::string file_name = "UserInfo.txt" ;

    if( std::ifstream file{file_name} ) // if the file was opened for input
    {
        std::string UserInfo ;

        // return true if UserInfo could be read and it matches UserName
        return std::getline( file, UserInfo ) && UserInfo == UserName ;
    }

    return false ;
}

1
2
3
4
5
6
7
8
9
bool userCheckFunction(const std::string& userName)
{
	if (std::ifstream file {"UserInfo.txt"})
		for (std::string userInfo; getline(file, userInfo); )
			if (userInfo == userName)
				return true;

	return false;
}

Hello Krish100,

To answer your question let us start with:
1
2
3
4
if ()
while()
do/while()
for (init-statement (optional); condition; iteration_expression(optional))

For lines 1 - 3 and the "condition" in line 4. What is between the () is evaluated and converted to a bool variable. The same is true for the condition in a for loop.

Knowing that these end up with a bool variable of (0)zero meaning (false) or (1) meaning (true). You can make use of this.

Now while (file) is a little different. "file" returns the good bit status. My understand is that there is no "good" bit it is just checking the status of the "bad", "fail" and "eof" bits and returns (true) if none of these bits are set (false) otherwise.


See http://www.cplusplus.com/reference/ios/ios/good/ for a table.
See https://en.cppreference.com/w/cpp/language/if
See https://en.cppreference.com/w/cpp/language/for in regards to line 4.

The problem with:
1
2
3
while (file)
{
    getline(file, UserInfo);

Is that you are doing the read after "while" has checked the status on the stream. So you would set the "eof" bit after you have entered the loop and there may be nothing in the "UserInfo" variable to check.

Early 2011 standards would retain the information from the last read. Then I noticed in the 2014 standards "string" variables would be set to empty and numeric variables would be set to (0)zero.

Not having your full code to compile and test along with the input file I came up with this:
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
#include <iostream>
#include <iomanip>
#include <limits>
#include <string>

#include <fstream>

bool userCheckFunction(const std::string& userName)
{
    const std::string inFileName{ "UserInfo2.txt" };  // <--- Put File name here.

    std::ifstream inFile(inFileName);

    if (!inFile)
    {
         return std::cout << "\n\n     File " << std::quoted(inFileName) << " did not open.\n", 0;  // <--- Requires header file "<iomanip>".
        //return std::cout << "\n\n     File \"" << inFileName << "\" did not open.\n", 0;
    }

    std::string UserInfo;

    while (getline(inFile, UserInfo))
    {
        if (UserInfo == userName)
        {
            return true;
            //file.close();  // <--- Not required as the dtor will close the file when the function looses scope. Also never reached because of the "return".
        }
    }

    return false;
}

int main()
{
    if (!userCheckFunction("name to find"))
    {
        // Do something
        std::cout << "\n     Name not found!\n";
    }
    else
    {
        std::cout << "\n Name Found!\n";
    }

    return 0;  // <--- Not required, but makes a good break point for testing.
}


And for the input file:

Etienne Navarre
Isabeau d'Anjou
Father Imperius
name to find
Arya Dr”ttningu
Saphira Dragon

For "Arya" The fancy (”) double quotes in the file turn into (ö) in the console window. To get the odd letters like (ö) you have to play around with what you enter in your code or enter the correct ASCII value which may not display properly in the source code.

In the functions while loop the "else if" is not needed. If you read each line of the file and no match is found the only thing left to do is return false. This also avoids the warning " that not all control paths return a value".

This should get what you have working. From there you could incorporate JLBorges's or seeplus's suggestions.

Andy
> it is just checking the status of the "bad", "fail" and "eof" bits
> and returns (true) if none of these bits are set (false) otherwise.

It checks the status of the failbit and badbit (it returns !fail())
Specifically, it can evaluate to true even if the eofbit is set;
ie, if the last input operation succeeded, but in the process the stream has reached an end of file state.
Table: https://en.cppreference.com/w/cpp/io/basic_ios/operator_bool#See_also
Topic archived. No new replies allowed.