C++ ifstream is reading last line only - c++

I am working on a program that allows a user to register an account. When a user registers for an account, the username and password are output to a text file "database.txt".
There is also an option for a user to search for their password by inputing their username if they forget their password. I find that this works fine when there is only one user registered in the .txt file database. However, when there is more than one user, the forgot password function returns the password of the most recent registered user, no matter which username is searched.
database.txt looks like this:
user1 111
user2 222
user3 333
No matter which user is entered to find the password, the function will always return 333, which is the most recent registered user's password. How do I fix this so that whichever user is searched, their password will output?
Here is the function:
void forgot()
{
int ch;
system("cls");
cout << "Forgotten? We're here to help." << endl;
cout << "Choose one of the options below: " << endl;
cout << "1. Forgot my password" << endl;
cout << "2. Forgot my username" << endl;
cout << endl;
cout << "Enter your choice: ";
cin >> ch;
switch(ch)
{
case 1: // search for username to find password
{
int count = 0;
string searchUser, su, sp;
cout << "Enter your username: ";
cin >> searchUser;
ifstream searchUserName("database.txt");
while(searchUserName >> su >> sp)
{
if(su == searchUser)
{
count = 1;
}
}
searchUserName.close();
if(count == 1)
{
cout << "Account found!" << endl;
cout << "Your password is: " << sp;
cin.get();
cin.get();
system("cls");
menu();
}
else
{
cout << "Sorry, that user ID does not exist." << endl;
cout << "Please contact our service team for more details." << endl;
cin.get();
cin.get();
system("cls");
menu();
}
break;
}
case 2: // search for password to find username
{
int count = 0;
string searchPass, su2, sp2;
cout << "Enter your password: ";
cin >> searchPass;
ifstream searchPassword("database.txt");
while(searchPassword >> su2 >> sp2)
{
if(sp2 == searchPass)
{
count = 1;
}
}
searchPassword.close();
if(count == 1)
{
cout << "Your password has been found." << endl;
cout << "Your username is: " << su2;
cin.get();
cin.get();
system("cls");
menu();
}
else
{
cout << "Sorry, we couldn't find your password in our database." << endl;
cout << "Please contact our team for more information." << endl;
cin.get();
cin.get();
system("cls");
menu();
}
break;
}
default:
cout << "Invalid choice, please try again." << endl;
system("cls");
forgot();
}
}

You should break out of the while loop once you have found the user name here:
while(searchUserName >> su >> sp)
{
if(su == searchUser)
{
count = 1;
break; // add this
}
}
Now it will continue to overwrite a previously found user name until searchUserName >> su >> sp is no longer true which is once it encounters EOF in most cases.
The other part of the program has the same problem.
Personnally I would rewrite the code such that the condition whether a matching password has been found or not is part of the loop condition.

Related

Elephant SQL with c++ login system

i created a cleint that requires you to register and login to acces certain apps but txt is not a efficent idea especially when i gave it to my friends so am trying to use a online data base but have 0 experince on how to do so so any help would be appreciated try to make words as simple as possiible still a biggener i tried searching online and trying diffrent ways but coudnt find something i could understand ao am still not sure of how to implement this and if its even possible in c++
here is my initial code for login and registering
void login() {
system("color 0B");
int counts = 0;
string userid, password, id, pass;
system("cls");
cout << "\t\t\t Please Enter your username and password : " << endl;
cout << "\t\t\t USERNAME:";
cin >> userid;
cout << "\t\t\t PASSWORD:";
cin >> password;
ifstream input("records.txt");
while (input >> id >> pass) {
if (id == userid && pass == password) {
counts = 1;
system("cls");
}
}
input.close();
if (counts == 1) {
secret(userid);
}
else {
cout << "\nLOGIN ERROR \n Username or password is inccorect\n\n";
main();
}
};
void Register() {
system("color 0B");
system("cls");
string ruserid, rpassword, rid, rpass;
string choice_2;
cout << "\t\t\t Welcome to my application you can register below\n";
cout << "press 1 to register \n";
cout << "press 2 to get back to the main menu \n";
cout << "\t\t\t Enter your option : ";
cin >> choice_2;
if (choice_2 == "1") {
string lock;
cout << "Enter registration password\n";
cout << "input password : ";
cin>>lock;
if (lock == "register_2006") {
system("cls");
cout << "\t\t\t Enter The USERNAME : ";
cin >> ruserid;
cout << "\t\t\t Enter The PASSWORD : ";
cin >> rpassword;
ofstream f1("records.txt", ios::app);
f1 << ruserid << ' ' << rpassword << endl;
system("cls");
cout << "\n\t\t\t Registration is Successful \n";
main();
}
else { cout << "Wrong password please contact to get it\n"; }
main();
}
else if (choice_2 == "2") {
system("cls");
main();
}
else {
cout << "wrong choice try again";
Register();
}
}

First input prompt skipped, while the rest are fine

Here's the code in question. When I run the program, if I enter any number of users, the ability to enter the username of the first user is skipped, while I can enter the username of the rest and the code performs as expected.
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
cout << "We would be more than happy to set up an account for you." << endl;
cout << "You may set up to four users, how many would you like to set up?" << endl;
int new_users;
cin >> new_users;
if(new_users < 1 || new_users > 4)
{
cout << "Invalid number, please try again." << endl;
return 0;
}
int user_number = 1;
string user_name_1, user_name_2, user_name_3, user_name_4;
string password_1, password_2, password_3, password_4;
if(new_users == 4)
{
cout << "Please enter the name of user #" << user_number << ": " << endl;
getline (cin, user_name_1, '\n');
cout << "Please enter the password for user: " << user_name_1 << endl;
getline(cin, password_1);
user_number++;
new_users--;
}
if(new_users == 3)
{
cout << "Please enter the name of user #" << user_number << ": " << endl;
getline(cin, user_name_2, '\n');
user_number++;
new_users--;
cout << "Please enter the password for user: " << user_name_2 << endl;
getline(cin, password_2);
}
if(new_users == 2)
{
cout << "Please enter the name of user #" << user_number << ": " << endl;
getline(cin, user_name_3, '\n');
user_number++;
new_users--;
cout << "Please enter the password for user: " << user_name_3 << endl;
getline(cin, password_3);
}
if(new_users == 1)
{
cout << "Please enter the name of user #" << user_number << ": " << endl;
getline(cin, user_name_4, '\n');
user_number++;
new_users--;
cout << "Please enter the password for user: " << user_name_4 << endl;
getline(cin, password_4);
}
cout << "Thank you for setting up an account. Please login." << endl;
cout << "Enter user name: ";
string user, password_attempt;
getline(cin, user);
cout << "Enter password: ";
getline(cin, password_attempt);
if (user == user_name_1 && password_attempt == password_1)
{
cout << "login successful, welcome user: " << user << endl;
return 0;
}
else if (user == user_name_2 && password_attempt == password_2)
{
cout << "login successful, welcome user: " << user << endl;
return 0;
}
else if (user == user_name_3 && password_attempt == password_3)
{
cout << "login successful, welcome user: " << user << endl;
return 0;
}
else if (user == user_name_4 && password_attempt == password_4)
{
cout << "login successful, welcome user: " << user << endl;
return 0;
}
else
{
cout <<"User name or password is invalid, please try again." << endl;
}
cout << "Enter user name: ";
getline(cin, user);
cout << "Enter password: ";
getline(cin, password_attempt);
if (user == user_name_1 && password_attempt == password_1)
{
cout << "login successful, welcome user: " << user << endl;
return 0;
}
else if (user == user_name_2 && password_attempt == password_2)
{
cout << "login successful, welcome user: " << user << endl;
return 0;
}
else if (user == user_name_3 && password_attempt == password_3)
{
cout << "login successful, welcome user: " << user << endl;
return 0;
}
else if (user == user_name_4 && password_attempt == password_4)
{
cout << "login successful, welcome user: " << user << endl;
return 0;
}
else
{
cout << "Invalid user. Goodbye." << endl;
return 0;
}
}
/*Things it needs to do
. Take multiple user names
. Set password for each user name
. User able to "login"
. Prompt if user fails to login to login again.
OoO
Ask how many users it would like to set up, up to 4.
Take a user name
set the password for recently taken user name
If the user wishes to exit allow them to; if not repeat, we'll say up to 3 times.
Once all users are entered, they can login.
If the login fails they are offered another attempt.
*/
I've tried a different compiler and it still is showing up. I expected the first user to behave like the rest, not sure what's wrong.

Issues figuring out readin/writeout for a bank program

I am trying to make a banking program that can read a username and password from a text file, and compare it to what the user enters. I have searched and tried a few different methods but I can't seem to get it to work. Im sorry if this is a re-post I just can't figure it out.
I am very new to coding so please forgive my mistakes.
The text file I have is called : "Account.txt"
It contains "username" on the first line then "userpassword" on the second line.
/*
Hunter Walker 11/10/2015
Banking Application with Input validation
Assignment 2
*/
//Headers
#include<iostream>
#include<string>
#include<cstdlib>
#include <fstream>
using namespace std;
//Variables
char input1, input2;
string username,userpassword, newusername, newuserpassword;
string customuser, custompass;
double amountin, amountout;
double total = 0;
//Function declarations
int bankingmenu();
int newaccount();
int login();
int main();
int mainmenu();
int deposit();
int withdraw();
int showbalance();
//Code to read from file
// The main menu for the banking application
int mainmenu()
{
cout << "Hi! Welcome to Future Computer Programmer ATM Machine!" << endl;
cout << "Please select an option from the menu below:" << endl;
cout << "l -> Login " << endl;
cout << "c -> Create New Account " << endl;
cout << "q -> Quit " << endl;
cin >> input1;
return 0;
}
// Function to allow the user to make a new account
int newaccount()
{
cout << "**********************************" << endl;
cout << "Welcome to the create an account menu!" << endl;
cout << "Please enter your desired username:" << endl;
cin >> newusername;
cout << "Please enter a password for your account:" << endl;
cin >> newuserpassword;
cout << "Thank you for creating an account with Future Computer Programmer ATM Machine!" << endl;
cout << "Your username is " << newusername << " and your password is " << newuserpassword << "." << endl;
cout << endl;
cout << "Reminder: Don't share your username or password with anyone." << endl;
cout << endl;
cout << "**********************************" << endl;
}
// Function to allow user to login to their account
int login()
{
cout << "Please enter username:" << endl;
cin >> username;
cout << "Please enter password:" << endl;
cin >> userpassword;
ifstream inputFile;
inputFile.open("Account.txt");
cout << customuser << " " << custompass << endl;
if (customuser == username && custompass == userpassword)
{
bankingmenu();
}
else
{
cout << "User name or password incorrect!" << endl;
cout << "Returning to main menu!" << endl;
return main();
}
inputFile.close();
return 0;
}
// The secondary menu for withdrawing/depositing/ or checking balance
int bankingmenu()
{
cout << "*******************************" << endl;
cout << "Please select an option from the menu below::" << endl;
cout << " d -> Deposit Money" << endl;
cout << " w -> Withdraw Money" << endl;
cout << " r -> Request Balance" << endl;
cout << " q -> Quit" << endl;
cin >> input2;
if (input2 == 'd')
{
deposit();
}
else if (input2 == 'w')
{
withdraw();
}
else if (input2 == 'r')
{
showbalance();
}
else if (input2 == 'q')
{
cout << "Returning to main menu! " << endl;
return main();
}
else
{
cout << "Please select a valid input and try again!" << endl;
return bankingmenu();
}
return 0;
}
// Function to allow to deposit to account
int deposit()
{
cout << "Please enter the amount of money you wish to deposit:" << endl;
cin >> amountin;
total = amountin + total;
cout << "The deposit was a success! Thanks for using Future Computer Programmer ATM Machine!" << endl;
return bankingmenu();
}
// Function to allow user to withdraw from account
int withdraw()
{
cout << "Please enter the amount you would like to withdraw:" << endl;
cin >> amountout;
if (total < amountout)
{
cout << "You can't withdraw more money than you have!" << endl;
cout << "Please select a different amount to withdraw." << endl;
return withdraw();
}
else
{
cout << "The amount has been withdrawn." << endl;
total = total - amountout;
return bankingmenu();
}
}
// Function to display the balance
int showbalance()
{
cout << "The balance in your account is $" << total << "." << endl;
return bankingmenu();
}
// The main function that calls all previous functions to run
int main()
{
mainmenu();
// Option to login
if (input1 == 'l')
{
login();
}
// Option to make a new account
else if (input1 == 'c')
{
newaccount();
}
// Option to exit program
else if (input1 == 'q')
{
cout << "Thanks for using the Future Computer Programmer ATM Machine! " << endl;
cout << "The program will now exit!" << endl;
return 0;
}
// Input validation
else
{
cout << "Please select a valid menu option and try again!" << endl;
return main();
}
return 0;
}
IN the newAccount function you will have to store the username and password with the following lines of code.
ofstream outfile;
outfile.open("Account.txt");
outfile<<newusername<<endl;
outfile<<newpassword<<endl;
outfile.close();
In your login function you will have to add the following two lines of code after you open the file 'Account.txt'
inputFile>>customuser;
inputFile>>custompass;
This would solve the present issue of getting the username and password of single user. But, you'll still have to figure out a way to get usernames and passwords for multiple users who'll use your application.
An easier adaptation to deal with multiple users would be to simply append username and password to the file and search for the username and password sequentially.
An alternative to the above approach is to use a database to store username and password.

How to stop a while loop

This while loop never ends. For example, when i enter a wrong password it will keep on going to the "incorrect password" part over and over again.
Logo();
inFile.open("UsernamePassword.txt");
if (!inFile)
cout << "Unable to Open File";
else
{
cout << endl << endl << endl;
cout << " Please enter username: ";
cin >> user;
cout << " Please enter password: ";
cin >> pass;
while (username != user)
{
inFile >> username >> password;
if (user == username && pass == password)
{
cout << endl;
cout << "Welcome to CherryLunch!" << endl;
system("pause");
system("cls");
MainMenu();
}
else
{
cout << endl;
cout << " Invalid Username or Password!" << endl << endl;
system("pause");
system("cls");
}
}
}
inFile.close();
The while loop is infinite because you never allow the user to input a new password or username. When the if statement fails, it will return to loop header (where it will still be wrong) and continue onwards.
Give the user a chance to enter in a new user/pass combo and then the loop can still be finite (provided the user eventually provides the correct credentials).
move the cout and cin statements inside the while loop:
else
{
while (username != user)
{
cout << endl << endl << endl;
cout << " Please enter username: ";
cin >> user;
cout << " Please enter password: ";
cin >> pass;
inFile >> username >> password;
if (user == username && pass == password)
{
cout << endl;
cout << "Welcome to CherryLunch!" << endl;
system("pause");
system("cls");
MainMenu();
}
else
{
cout << endl;
cout << " Invalid Username or Password!" << endl << endl;
system("pause");
system("cls");
}
}
}
inFile.close();
It keeps on an infinite loop because you never ask if you reached the end of the file, so, if the file does not contain a username/password combination that matches the pair entered by the user, when the end of the file is reached, the line:
inFile >> username >> password;
Fails and username and password will contain the last entries seen on UsernamePassword.txt and the loop goes forever.
The following implementation of your program will test for the eof in the inFile file object:
#include <fstream>
#include <iostream>
#include <string>
#include <cstdlib>
int main() {
std::ifstream inFile;
std::string user, pass;
std::string username, password;
inFile.open("UsernamePassword.txt");
if (!inFile) {
std::cout << "Unable to Open File";
} else {
std::cout << std::endl << std::endl << std::endl;
std::cout << " Please enter username: ";
std::cin >> user;
std::cout << " Please enter password: ";
std::cin >> pass;
while (username != user && !inFile.eof()) {
inFile >> username >> password;
if (user == username && pass == password) {
std::cout << std::endl;
std::cout << "Welcome to CherryLunch!" << std::endl;
// Equivalent to the 'pause' command in linux
system("read -p 'Press any key to continue...' key");
// Equivalent to the 'cls' command in linux
system("clear");
// MainMenu();
} else {
std::cout << std::endl;
std::cout << " Invalid Username or Password!" << std::endl << std::endl;
system("read -p 'Press any key to continue...' key");
system("clear");
}
}
}
inFile.close();
}
You are trying to check for the username and password from the user and compare with all the usernames and passwords in the file.
Your approach seems fine. But you are printing "Invalid username..." after each comparison, not comparing all the usernames in the file. Hence move this output outside else block and place it in the while loop.
infile checks each line separately.
And also check the end of file.If the username and password are not found till the end of file, then print "Invald username" and provide the user to enter another set of name and password
Hope this helps!!
First, read the correct usernames and passwords from the file and save them in memory. That way, if the username/password validation fails the first time, you don't have to reopen or seek-to-beginning-in the file before checking on the next username/password typed by the user....
std::map usernames_passwords;
std::string username, password;
if (ifstream in("UsernamePassword.txt"))
while (in >> username >> password)
usernames_passwords[username] = password;
else
{
std::cerr << "Unable to open username/password file\n";
exit(EXIT_FAILURE);
}
Then prompt for login details until they're valid:
bool logged_in = false;
while (!logged_in &&
std::cout << "\n\n\n Please enter username: " &&
std::cin >> username &&
std::cout << " Please enter password: " &&
std::cin >> password)
{
// look for a match in the earlier-read login details...
auto it = usernames_passwords.find(username);
logged_in = it != std::end(usernames_passwords) && it->second == password;
}
// the while loop could also exit because "cin >>" failed, indicating EOF
// that could be because the user typed e.g. ^D (UNIX) or ^Z (Windows), or
// input was from a redirected file or pipe or over a network connection...
if (!logged_in)
{
std::cerr << "error reading login details from stdin\n";
exit(EXIT_FAILURE);
}
...ok - we know the username/password are good - do whatever else...

How to read multiple text lines [duplicate]

This question already has answers here:
How to stop a while loop
(5 answers)
Closed 8 years ago.
In my text file ("UsernamePassword.txt"), there are multiple lines of Usernames and Passwords. When I tried logging in using the Username and Password on the 2nd line or 3rd line, it brings me to the "invalid username or password" part. Only the 1st line of username and password works.
Any suggestion on how to read the multiple lines?
{
fstream inFile;
string user, pass, username, password;
int choice;
Logo();
cout << endl << endl << endl;
inFile.open("UsernamePassword.txt");
if (!inFile)
cout << "Unable to Open File";
else
{
while (username != user)
cout << endl << endl << endl;
cout << " Please enter username: ";
cin >> user;
cout << " Please enter password: ";
cin >> pass;
{
inFile >> username >> password;
if (user == username && pass == password)
{
system("cls");
cout<<endl<<endl<<endl<<endl<<endl<<endl<<endl<<endl<<endl;
cout << "\t ****************************************** " << endl;
cout << "\t ** !!! Welcome to CherryLunch !!! ** " << endl;
cout << "\t ****************************************** " << endl;
cout<<endl<<endl<<endl<<endl<<endl;
system("pause");
system("cls");
MainMenu();
}
else
{
cout<<endl<<endl<<endl<<endl<<endl;
cout << "\t !!! Invalid Username or Password !!!" << endl<<endl;
cout << "\t *** Please try again ***" << endl;
cout<<endl<<endl<<endl<<endl<<endl;
system("pause");
system("cls");
}
}
}
inFile.close();
}
You haven't given us the whole code - but I have placed comments in your code (various places) to indicate whether you wanted to do this willingly or did it by mistake:
{
fstream inFile;
string user, pass, username, password;
int choice;
Logo();
cout << endl << endl << endl;
inFile.open("UsernamePassword.txt");
if (!inFile)
cout << "Unable to Open File";
else
{
while (username != user) // Only the following run will repeat ( if this is the intention?)
cout << endl << endl << endl;
cout << " Please enter username: ";
cin >> user;
cout << " Please enter password: ";
cin >> pass;
{ // This is scoped operation
inFile >> username >> password;
if (user == username && pass == password)
{
system("cls");
cout<<endl<<endl<<endl<<endl<<endl<<endl<<endl<<endl<<endl;
cout << "\t ****************************************** " << endl;
cout << "\t ** !!! Welcome to CherryLunch !!! ** " << endl;
cout << "\t ****************************************** " << endl;
cout<<endl<<endl<<endl<<endl<<endl;
system("pause");
system("cls");
MainMenu();
}
else
{
cout<<endl<<endl<<endl<<endl<<endl;
cout << "\t !!! Invalid Username or Password !!!" << endl<<endl;
cout << "\t *** Please try again ***" << endl;
cout<<endl<<endl<<endl<<endl<<endl;
system("pause");
system("cls");
} // End of inner else
} // This is the end of scoped operation
} // End of Outer else
inFile.close();