Read username and password from a file output problem

my program of registration and login encountered a few problems during output :

1. I have to register a new user and pass first(even if i alrd have previous usernames and passwords stored in the text file im trying to retrieve it from), after that only i can login using previous username and passwords and this repeats after i close the debug window and start debugging again (if i directly choose to login upon running the program, it will output "invalid username or password")

2. when logging out from a newly registered username, the program jumps to the
int main() AND DISPLAY "1. Register...."
but logging out from previous usernames, it jumps to
void login() and display "Username:"


*note: the last function isn't complete yet but i think it doesn't affect it (?) (the program worked fine before i added the ```void accountPage()```tho)
*i am not supposed to use pointers plus i'm very new to c++

the code is a bit long but its just a lot of simple functions, i would rly appreciate it if someone can point out my mistake anywhere


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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
  #include <iostream>
#include <iomanip>
#include <cctype>
#include <fstream>
#include <string>

using namespace std;

//Global Variables
int Choice1;
int mobile, ic;
string user, pass, name, inUser, inPass;

//Function Prototypes
void register_user();
void login();
void bookRoom();
bool CheckCredentials(string, string);
void accountPage();

int main() 
{


	cout << "Welcome to Cozy Homes!\n";
	cout << "Operating hours: 11am - 10pm Tuesday - Sunday\n\n\n\n";

	do {
		cout << "\n1. Register\n";
		cout << "2. Log In\n";
		cout << "3. Exit\n";
		cout << "Please enter a number:";
		cin >> Choice1;

		if (Choice1 == 1)
		{
			register_user(); 
		}

		else if (Choice1 == 2)
		{
			login();
		}

		else if (Choice1 == 3)
		{
			cout << "Exiting now...\n";
			return 0;
		}

		else if (Choice1 < 1 || Choice1 > 3)
		{
			cout << "Please choose a number from the menu!" << endl;
		}

	} while (Choice1 != 3);

	system("pause");
	return 0;
}

//Register page
	void register_user()
	{
		cin.ignore();
		cout << "\n\n\n" << "New Username: ";
		getline(cin, user);
		cout << endl;
		cout << "New Password: ";
		getline(cin, pass);
		cout << endl;
		cout << "Full name: ";
		getline(cin, name);
		cout << endl;
		cout << "Mobile Number: ";
		cin >> mobile;
		cout << endl;
		cout << "Ic Number (without \" - \"): ";
		cin >> ic;
		cout << endl;
		cout << "Registered Successfully!" << endl;
		cout << endl;

		//Store username and password in login file
		ofstream l("login.txt", ios::app);
		if (!l.is_open()) {
			cout << "could not open file \n";
		}


		l << user << " " << pass << endl;
		l << endl;
		l.close();

		//Store other details in customer file
		ofstream c("customer.txt", ios::app);
		if (!c.is_open()) {
			cout << "could not open file \n";
		}

		c << user << endl;
		c << pass << endl;
		c << name << endl;
		c << mobile << endl;
		c <<  ic << endl;
		c << '\n';
	
		c.close();

	}

	//Log in page
	void login() 
	{
		do
		{
			cout << "\nUsername: ";
			cin >> inUser;
			cout << "Password: ";
			cin >> inPass;


			if (CheckCredentials(inUser, inPass) == true)
			{
				cout << "\nLogin sucessful!" << endl;
				cout << "Welcome, " << inUser << endl;
				cout << endl;
				accountPage(); // Redirects user to their account page after successfully logged in
			}
			else
			cout << "\nInvalid username or password. " << endl;

		} while (CheckCredentials(inUser, inPass) != true);
	}
	
	//Validate their username and password
	bool CheckCredentials(string inUser, string inPass)
	{
		string u;
		string p;

		bool status = false;

		ifstream f;
		f.open("login.txt");

		if (!f.is_open())
		{
			cout << "Unable to open file!\n";
		}
		else if (f)
		{
			while (!f.eof())
			{
				f >> u >> p;
				if (inUser == u && inPass == p)
				{
					status = true;
				}
				else
				{
					status = false;
				}
			}
		}

		f.close();
		return status;
	}
	
	//Account Page
	void accountPage()
	{
		int Choice2;

		do
		{
			cout << "1. Profile\n";
			cout << "2. Book a Room\n";
			cout << "3. Cancel Booking\n";
			cout << "4. Logout\n";

			cout << "Please enter a number: ";
			cin >> Choice2;

			if (Choice2 == 1)
			{

			}
			else if (Choice2 == 2)
			{
				
			}
			else if (Choice2 == 3)
			{

			}
			else if (Choice2 == 4)
			{
				cout << "Logging out.....\n\n\n\n";
				cout << endl;
			}
		} while (Choice2 != 4);
	}

	//Booking page
	void bookRoom() {
		cout << " ";
	}
Last edited on
A problem is that you are mixing >> with getline(). These 2 don't get on with each other without a nudge in the right direction.

>> will extract from the stream ignoring any initial white-space chars (space, tab, newline) and will stop the extraction when either a white-space char is found (which is not extracted) or a problem with the data extraction has occurred.

getline() does not ignore any initial white-space chars and will extract up-to and including the terminating char (default newline unless specified).

The problem is using getline() after >> as >> leaves the terminating white-space char (often the newline) which is treated as null input by getline()!

The solution is after the >> to remove the terminating newline using .ignore()

See http://www.cplusplus.com/reference/istream/istream/ignore/

Also note that when testing for no-more-data, the test has to be after the data has tried to be read, not before. eof is not set when the last record has been read but when the next record is tried to be read. So:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool CheckCredentials(const string& inUser, const string& inPass)
{
	bool status = false;

	ifstream f("login.txt");

	if (!f)
		cout << "Unable to open file!\n";
	else
		for (string u, p; !status && (f >> u >> p); )
			status = inUser == u && inPass == p;

	return status;
}

Last edited on
A problem is that you are mixing >> with getline(). These 2 don't get on with each other without a nudge in the right direction.


I'm sorry, in which line did I do this? I cant seem to find nor recall using ">>" with getline() hahaha


I tried your changes to my code (the CheckCredentials function) and it worked!!!!!! omg after three days! thank you so much!

May I ask why u used const string and why it has to be a reference parameter tho?
Last edited on
May I ask why u used const string and why it has to be a reference parameter tho?


With passing as a ref, it is passed by value - the contents of the passed string are copied. With ref, this copy is not done. As you don't want changes made to these in the function body which would be passed back to the calling function, they are passed as const. Unless a copy si really required, non POD data is passed as either ref (changes passed back to the calling function) or const ref where no changes are allowed.

I cant seem to find nor recall using ">>" with getline()


L67 - but you're got the .ignore() first which I missed on first scanning the code.
Ok got it thanks!
Topic archived. No new replies allowed.