Password

Hi, I'm trying to figure how to read a username and password from a file using a map. I was able to write to the file but I am having difficulties reading the information from the file. Could someone please help ? Please let me know if you have any questions. Thank you
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

#include <iostream>
#include <fstream>
#include <map>
using namespace std;
int main(int argc, const char * argv[])
{

    map<string,string>Login = {
                              {"Bill","Oakland"},
                              {"Jay","Berkeley"},
                              {"Bob","Sacramento"},
                              };
    ofstream write("password.txt",ios::out);
    ifstream read("password.txt",ios::in);
    string output;
    
    for(auto&it : Login){write << it.first << ' ' << it.second << endl;}
    write.close();
    
    string userName,
           passWord;
    bool flag = false;
    
    map<string,string>::iterator it = Login.find(userName);
    map<string,string>::iterator it2 = Login.find(passWord);
    
    do
    {
        cout << "Input Username: ";
        getline(cin,userName);
        cout << "\nInput Password: ";
        getline(cin,passWord);
        
    while((read >> userName >> passWord) && !flag)
    {
        if(it!=Login.end() && it2!=Login.end())
        {
            cout << "\nCongratulations, you have\nsuccessfully logged into you profile.\n\n";
            flag = true;
            break;
        }
        else if (it==Login.end() && it2==Login.end()) { cout << "\nInvalid login, please re-enter: \n\n";break;}
    }
        
    }while(!flag);
    read.close();
    
    return 0;
}
the point of a map is to not use find. should be able to just check the input as a key.

that aside, your find is outside the loop? should you not need to move 25 & 26 to 34?
Hey, I tried to take your advice but am still having trouble. Please let me know when I am doing wrong. Thank you


#include <iostream>
#include <fstream>
#include <map>
using namespace std;
int main(int argc, const char * argv[])
{

    map<string,string>Login = {
                              {"Bill","Oakland"},
                              {"Jay","Berkeley"},
                              {"Bob","Sacramento"},
                              };
    ofstream write("password.txt",ios::out);
    ifstream read("password.txt",ios::in);
    string output;
    
    for(auto&it : Login){write << it.first << ' ' << it.second << endl;}
    write.close();
    
    string userName,
           passWord;
    bool flag = false;
    
   
    
    do
    {
        cout << "Input Username: ";
        getline(cin,userName);
        cout << "\nInput Password: ";
        getline(cin,passWord);
        map<string,string>::iterator it = Login.find(userName);
        map<string,string>::iterator it2 = Login.find(passWord);
    while((read >> userName >> passWord) && !flag)
    {
        if(it!=Login.end() && it2!=Login.end())
        {
            cout << "\nCongratulations, you have\nsuccessfully logged into you profile.\n\n";
            flag = true;
            break;
        }
        else if (it==Login.end() || it2==Login.end()) { cout << "\nInvalid login, please re-enter: \n\n";break;}
    }
        
    }while(!flag);
    read.close();
    
    return 0;
}


this will work. but I don't really know what you want to do with that file.
now, for this code, if you put in a name not in the data, it will add it to the map. You can fix that, but first, need to know better what exactly you want to do. That may be where find comes in, but you don't use find on the password, only on the name. Find on a map works off the keys... i said that wrong above, find is fine, just not on the password.

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
#include <vector>
#include <iostream>

using namespace std;


#include <iostream>
#include <fstream>
#include <map>
using namespace std;
int main(int argc, const char * argv[])
{

    map<string,string>Login = {
                              {"Bill","Oakland"},
                              {"Jay","Berkeley"},
                              {"Bob","Sacramento"},
                              };
    ofstream write("password.txt",ios::out);
    ifstream read("password.txt",ios::in);
    string output;
    
    for(auto&it : Login){write << it.first << ' ' << it.second << endl;}
    write.close();
    
    string userName,
           passWord;
    bool flag = false;
    
    do
    {
        cout << "Input Username: ";
        getline(cin,userName);
        cout << "\nInput Password: ";
        getline(cin,passWord);		
		if(passWord == Login[userName])
		{
			  cout << "\nCongratulations, you have\nsuccessfully logged into you profile.\n\n";
			  flag = true;
		}
		  else
			  cout << "\nInvalid login, please re-enter: \n\n";
	}while(!flag);
   
    return 0;
}


so to do the same with find, maybe try
// if(passWord == Login[userName])
auto something = Login.find(userName);
if(something != Login.end() && passWord == something->second)

Last edited on
Hey jonnin, thank you for your help. But what I want to do is determine if the key and value of the map is located in the file. So I hoping to find a way to read the file to see if the key and value is present. Please let me know if there is a way to do this. Thank you
Hey here's a technique I used to solve it. I don't think this is the cleanest way to do it but got the job done. Please let me know if you have any suggestions. Thank you again for your help.

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
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
using namespace std;
int main(int argc, const char * argv[])
{

    map<string,string>Login = {
                              {"Bill","Oakland"},
                              {"Jay","Berkeley"},
                              {"Bob","Sacramento"},
                              };
    ofstream write("password.txt",ios::out);
    
    string output;
    
    for(auto&it : Login){write << it.first << ' ' << it.second << endl;}
    write.close();
    
    string userName,
           passWord,
           information;
    bool flag = false;
    bool valid = false;
    vector<string>Data;
    ifstream read("password.txt",ios::in);
    do
    {
        cout << "Input Username: ";
        getline(cin,userName);
        cout << "\nInput Password: ";
        getline(cin,passWord);
        map<string,string>::iterator it = Login.find(userName);
        
        while(read >> information)
        {
            string temporary;
            
            for(auto&info : information){temporary += info;}
            
            Data.push_back(temporary);
        }
        
        for(int i = 0; i < Data.size(); i++)
        {
            if((Data[i].find(userName) != string::npos) && (it->first == userName))
            {
                
                flag = true;break;
            }
                
        }
        
        if(flag)
        {
        for(int i = 0; i < Data.size(); i++)
        {
            if(Data[i].find(passWord) != string::npos && (it->second == passWord))
            {
                
                valid = true;break;
            }
                
        }
        }
        if(valid){cout << "\nCongratulations, you have successfully\nlogged into you profile.\n\n";}
        else{cout << "\nInvalid login, please re-enter: \n\n";flag = false;}

    }while(!valid);
 
    read.close();
    
    return 0;
}
Please explain what exactly you are trying to do. You write the map to a file, then ask for username/password and then use a mix of finding in the map and from data read from the file to validate the entered name/password.

Do you want to validate the entered data against the contents of the map - or against the contents of the file?

L36 - 43 . All you are doing here is setting temporary to information and then adding this to Data - which will be an alternate of name and password???

So a username can be a password and a password can be a username

Is this what you want?

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
#include <iostream>
#include <fstream>
#include <map>
#include <string>

int main()
{
	const std::map<std::string, std::string>Login {
							  {"Bill","Oakland"},
							  {"Jay","Berkeley"},
							  {"Bob","Sacramento"}
	};

	std::ofstream write("password.txt");

	for (const auto& it : Login)
		write << it.first << ' ' << it.second << '\n';

	write.close();

	bool valid {};
	std::ifstream read("password.txt");

	do {
		read.clear();
		read.seekg(0);
		std::string userName, passWord;

		std::cout << "Input Username: ";
		std::getline(std::cin, userName);

		std::cout << "\nInput Password: ";
		std::getline(std::cin, passWord);

		for (std::string id, pass; !valid && (read >> id >> pass); )
			if (id == userName && pass == passWord)
				valid = true;

	} while (!valid && (std::cout << "\nInvalid login, please re-enter: \n\n"));

	std::cout << "\nCongratulations, you have successfully\nlogged into you profile.\n\n";
}

Last edited on
Hello kdrewes,

I have be working on and testing all morning while thinking about what is wrong.

A little revision of your code to start with:
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <iostream>
#include <fstream>
#include <string>  // <--- Added. Needed for "std::getline" and for output, (cout or File Stream).
#include <vector>  // <--- Is there a point to this?
#include <map>

using namespace std;  // <--- Best not to use.

int main(/*int argc, const char * argv[]*/)  // <--- If you do not use them you do not need them.
{
    map<string, string>Login
    {
        {"Bill","Oakland"},
        {"Jay","Berkeley"},
        {"Bob","Sacramento"}  // <--- Comma not needed here.
    };

    ofstream outFile("password.txt"/*, ios::out*/);  // <--- Changed.

    if (!outFile)  // <--- Added.
    {
        return std::cerr << "\n     File \"password.txt\" did not open\n\n", 1;
    }

    //string output;  // <--- Not used.

    for (auto& it : Login)
    {
        outFile << it.first << ' ' << it.second << endl;
    }

    outFile.close();

    string userName,
        passWord,
        information;
    bool flag{};
    bool done{};  // <--- Added;
    bool valid{};
    vector<string>Data;  // <--- Not really needed.

    ifstream inFile("password.txt"/*, ios::in*/);

    if (!inFile)  // <--- Added.
    {
        return std::cerr << "\n     File \"password.txt\" did not open\n\n", 2;
    }
    
    do
    {
        cout << "Input Username: ";
        getline(cin, userName);

        cout << "\nInput Password: ";
        getline(cin, passWord);

        map<string, string>::iterator it{ Login.find(userName)};

        if (it != Login.end())
        {
            std::cout << "\n     User name found!\n";
        }
        else
        {
            std::cerr << "\n     User name not found!\n";
        }

        while (inFile >> information)
        {
            string temporary;

            for (auto& info : information)  // <--- Why are you reading 1 character at a time?
            {
                temporary += info;
            }

            Data.push_back(temporary);
        }

        for (size_t i = 0; i < Dsta.size(); i++)
        {
            if ((Data[i].find(userName) != string::npos) && (it->first == userName))
            {
                flag = true;
                
                break;
            }
        }

        if (flag)
        {
            for (size_t i = 0; i < Data.size(); i++)
            {
                if (Data[i].find(passWord) != string::npos && (it->second == passWord))
                {
                    valid = true;
                    
                    break;
                }
            }
        }

        if (valid)
        {
            cout << "\nCongratulations, you have successfully\nlogged into you profile.\n\n";

            done = true;
        }
        else
        {
            cout << "\nInvalid login, please re-enter: \n\n";
            
            flag = false;
        }

    } while (!done);

    inFile.close();  // <--- Not required as the dtor will close the file when the function looses scope.

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

From the top I add the header file "<string>" because you need this for "std::getline()" and also when send a "std::string" to output, either the screen or a file.

In line 9 you are creating storage space for variables that you do not use. Maybe you have some idea for using command line arguments in the future. If so you can uncomment it later otherwise the compiler will just see
int main().

Defining the map this way makes it much easier to read than with all that indenting. Also you do not need the (=) when using the uniform initializer, the {}s.

On line 18 the "o" in "ofstream" implies that the stream will be for output. What is commented out can be removed because it is redundant and I believe it is ignored by the compiler. The same is true for "ifstream".

The lines that follow is to check that there is problem with opening the stream. Both input and output streams should be checked especially the input stream.

Using the file stream names of "read" and "write" are misleading. When I first looked at the code I had a different idea of what you were trying to do.

Now that that is covered, and once the file is created, writing the "map" to a file should be done at the end of the program and reading the file to create the "map" should be at the beginning.

I added line 38 because it is a chance to have a little fun with the code. You will see this in line 116.

Lines 42 - 47 are updated, but you do not need this here because you already have a populated "map" to use.

Line 57 works, but I would not be using it this way.

Lines 59 - 66 I added to deal with a name being found or not. Even with that the rest of the code still works.

Lines 68 - 78. You are really over doing this here. while (inFile >> information). The formatted input here will up to the first white space or new line it finds, so "information" ends up with "Bill" then you use a for loop to create a temporary string of what you already have just to add the temporary string to a vector that you do not need.

Lines 80 - 88 and again with lines 92 - 100 you are using the for loops to read the vector, but "it" already has the address in the "map" that it needs. Creating and checking the vector is not needed.

The last if/else works although I did add line 107.

When I rework you code to just what you need I put that in the next post.

Andy
Hello kdrewes,

This is my 1st revision. A little smaller, but not what it should be:
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
78
79
80
#include <iostream>
#include <fstream>
#include <string>  // <--- Added. Needed for "std::getline" and for output, (cout or File Stream).

#include <map>

using namespace std;  // <--- Best not to use.

int main()  // <--- If you do not use them you do not need them.
{
    //std::map<std::string, std::string> login;  // <--- Should use a lower case letter for the variable name.
    // Once the file is created this make testing easier. But after the above line you should be
    // reading the file to populate the the "map" here.

    map<string, string> Login
    {
        {"Bill","Oakland"},
        {"Jay","Berkeley"},
        {"Bob","Sacramento"}  // <--- Comma not needed here.
    };

    // Writing to the file should be moved to the end of the program. In case there are any
    // changes or additions to the "map".

    string userName,
        passWord,
        information;
    bool flag{};
    bool done{};  // <--- Added;
    bool valid{};

    do
    {
        cout << "Input Username: ";
        getline(cin, userName);

        cout << "\nInput Password: ";
        getline(cin, passWord);

        map<string, string>::iterator it{ Login.find(userName)};

        if (it != Login.end())
        {
            std::cout << "\n     User name found!\n";
        }
        else
        {
            std::cerr << "\n     User name not found!\n";
        }

        if (it->first == userName)
        {
            flag = true;
        }

        if (flag)
        {
            if (it->second == passWord)
            {
                valid = true;
            }
        }

        if (valid)
        {
            cout << "\nCongratulations, you have successfully\nlogged into you profile.\n\n";

            done = true;
        }
        else
        {
            cout << "\nInvalid login, please re-enter: \n\n";
            
            flag = false;
        }

    } while (!done);

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


Then after looking at the program for a bit 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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include <fstream>
#include <string>  // <--- Added. Needed for "std::getline" and for output, (cout or File Stream).

#include <map>

using namespace std;  // <--- Best not to use.

int main()  // <--- If you do not use them you do not need them.
{
    //std::map<std::string, std::string> login;  // <--- Should use a lower case letter for the variable name.
    // Once the file is created this make testing easier. But after the above line you should be
    // reading the file to populate the the "map" here.

    map<string, string> Login
    {
        {"Bill","Oakland"},
        {"Jay","Berkeley"},
        {"Bob","Sacramento"}
    };

    string userName,
        passWord,
        information;
    bool flag{};
    bool done{};  // <--- Added;
    bool valid{};

    do
    {
        cout << "Input Username (Enter to quit): ";
        getline(cin, userName);

        if (userName.empty())
        {
            done = true;

            continue;
        }

        cout << "\nInput Password: ";
        getline(cin, passWord);

        map<string, string>::iterator it{ Login.find(userName) };

        if (it != Login.end())
        {
            if (it->second == passWord)
            {
                //valid = true;
                cout << "\nCongratulations, you have successfully\nlogged into you profile.\n\n";

                done = true;
            }
            else
            {
                cout << "\nInvalid login, please re-enter: \n\n";
            }
        }
        else
        {
            std::cerr << "\n     User name not found!\n\n";
        }
    } while (!done);

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


See what you think.

Andy
Seeplus and Andy thank you both for all your help. This all helps a lot because some of these techniques I didn't even know existed so this will be really helpful for me in the future. Again, thank you for taking your time to help me out with this and I will experiment with both codes.

Kyle
Topic archived. No new replies allowed.