If userList[i].CheckUser(username, password) returns false then it enters the else condition and I get the output "User Does Not Exist! Try Again Enter username and password" that line then gets stuck in an infinite loop and I cant figure out why, I mean the program re-enters the do-while loop again so I don't see how the loop would carry over?
int main()
{
LoadUsersFromDatabase();
bool flag;
string username;
int password;
do{
cout << "Enter username and password: ";
cin >> username >> password;
for (int i = 0; i < numOfUsers; i++)
if (userList[i].CheckUser(username, password) == true)
{
if (userList[i].GetUserType() == 'A')
{
ProcessAssistantMenu();
}
else if (userList[i].GetUserType() == 'M')
{
ProcessManagerMenu();
}
}
else
cout << "\rUser Does Not Exist! Try Again! ";
flag = false;
} while(flag == false);
return 0;
}
You are always setting your flag = false.
I'm guessing you want to do this:
else{
cout << "\rUser Does Not Exist! Try Again! ";
flag = false;
}
And as Alex points out, you're not setting it true in the first place.
The flag is never set true in the loop.
Related
I am creating a password validation program and I want the password to contain the following:
* Password must be between 8 to 15 characters long...
* Password must contain at least one digit
* Password must contain at least one Uppercase
* Password must contain at least one number
* Password must contain at least one lowercase
* Password must contain at least one symbol
And if the user enters an invalid password, the program should ask the user to re-enter password. But I'm stuck on how to make the user re-enter the password if its wrong. I tried using 'goto' but its not working...
#include<ctype.h>
#include<stdbool.h>
using namespace std;
bool verify_password();
int main() {
char userName;
char password[15];
cout << "\n\t\t\t\tEnter User Name: ";
cin >> userName;
cin.clear();
cin.ignore(100, '\n');
cout << "\n\t\t\t\tEnter Password: ";
cin >> password;
bool result = verify_password();
if (result) cout<<"Verified password\n";
else {
cout<<"Invalid password\n";
cout<<result;
}
system("pause>0");
}
bool verify_password(){
int lenght = strlen(password);
if (lenght < 8 || lenght > 15) return false;
bool has_upper = false;
bool has_lower = false;
bool has_symbol = false;
bool has_digit = false;
for (int i = 0; i < lenght; i++){
if(isupper(password[i])) has_upper = true;
if(islower(password[i])) has_lower = true;
if(isdigit(password[i])) has_digit = true;
if(ispunct(password[i])) has_symbol = true;
}
if(!(has_upper && has_lower && has_digit && has_symbol)) return false;
}
I see a lot of issues with this code, but the things you should change to start:
Make your verify password function ONLY verify the password. It is currently doing more than that.
Get user input in the main() function. Once you get the password here, you can do something like:
int trys = 0;
while (trys < 3) {
cout << "Enter Password: ";
cin >> password;
if (verify_password(password)) {
cout << "valid!" << endl;
break;
}
cout << "invalid..." << endl;
++trys;
}
You can use recursion to execute the function again. Replace the following:
if(!(has_upper && has_lower && has_digit && has_symbol)){
goto checkPassword;
return false;}
With recursion, such as:
if(!(has_upper && has_lower && has_digit && has_symbol))
return verify_password();
Using goto statements is not a good practice for coding, it's much clearer to use other kind of loops like while and for.
For your problem here I would suggest to re-organize the code in smaller functions:
requestUsername() //Call it to ask user for the username
requestPassword() //Call it to ask user for password
verifyPassword() //Call it to verify the provided password
Then, you could structure your main like this:
username = requestUsername();
password = requestPassword();
while(!verifyPassword(password)) //Invalid password
{
password = requestPassword();
}
Or:
username = requestUsername();
do
{
password = requestPassword();
}while(!verifyPassword(password)) //Invalid password
Hope this helps!
I am working on Login/Registration system. So far I am getting the error that the variable "count" is used without being initialized.
bool count;
string userId, password, id, pass;
system("cls");
cout << "\t\t\n Please enter the username and password\n\n";
cout << "Username:";
cin >> userId;
cout << "Password:";
cin >> password;
//reads info from the file
ifstream readL("record.txt");
while (readL >> id >> pass) {
if (id == userId && pass == password) {
count = true;
}
else {
count = false;
}
}
readL.close();
if (count == true) {
cout << userId << " your LOGIN is successfull.\n\n";
main();
}
else {
cout << "\nLOGING error\n\nPlease check your username and password\n\n\n";
main();
}
I have second part of the code and same system works here. `
case 1: {
bool count;
string suserId, sId, spass;
cout << "\n\nEnter the username that you remember:";
cin >> suserId;
//reads the file
ifstream f2("records.txt");
while (f2 >> sId >> spass) {
if (sId == suserId) {
count = true;
}
else {
count = false;
}
}
f2.close();
if (count == true) {
cout << "\n\n\tYour account is found!\n\nYour password is " << spass << endl << endl;
main();
}
else {
cout << "\n\n\tSorry your account is not found." << endl << endl;
main();
}
break;
}
`
The only difference that in the first case it reads two variables during the while if statement, in second only Username.
But even if I am going to read only Username in the first case error is still appearing.
Your C++ compiler is smart enough to figure out that if the file could not be opened or is empty, the while loop never executes even once, and count remains uninitialized until its value is checked after the loop. That's what your C++ compiler is telling you.
Just because the input file exist or is not empty, and its contents are valid (because garbage in it will also result in the initial attempt to read it fail) is immaterial. It is logically possible for count to be uninitialized when its value gets used, hence your compiler's diagnostic.
P.S. the while loop's logic is also fatally flawed, for a different reason. But that's unrelated to the compiler diagnostic you asked about.
Maybe you should just initialize it with
bool count = false;
I have the following code and it somehow verify if the input is number, but the error occurs while looping back to ask the user for the second time to enter the number.
I can't figure it out.
#include <iostream>
#include <limits>
using namespace std;
void botVarification();
void userDecision();
bool isHuman(string humanInput);
int main()
{
botVarification();
return 0;
}
void botVarification()
{
string humanInput;
cout << "Enter the number to verify that you are not a bot: ";
cin >> humanInput;
bool isHuman = true;
do {
for (int humanInputvalidator; humanInputvalidator < humanInput.length() && isHuman; humanInputvalidator++) {
if (!(humanInput[humanInputvalidator] >= 48 && humanInput[humanInputvalidator] <= 57)) {
isHuman = false;
cout << "Not success, try again!";
cin >> humanInput;
}
else
cout << "Success" << '\n';
break;
}
} while (!(isHuman));
}
$ clang++-7 -Wall -o main main.cpp
main.cpp:23:39: warning: variable 'humanInputvalidator' is
uninitialized when used here [-Wuninitialized]
for (int humanInputvalidator; humanInputvalidator < hum...
^~~~~~~~~~~~~~~~~~~
main.cpp:23:37: note: initialize the variable 'humanInputvalidator' to
silence this warning
for (int humanInputvalidator; humanInputvalidator < hum...
^
= 0
1 warning generated.
So let's fix that.
Additionally, on the second iteration of getting input from the user, humanInputvalidator < humanInput.length() && isHuman will always be false. You'll want to reinitialize isHuman = true inside the do while loop.
Functions are a great way to simplify your code!
Use functions! It's a great way to simplify your code and decrease the number of variables in any single context.
bool isThisHumanInput(std::string data) {
for (int i = 0; i < data.length(); i++)
if (!(data[i] >= 48 && data[i] <= 57))
return false;
return true;
}
void botVarification()
{
string humanInput;
bool isHuman;
do {
cout << "Enter the number to verify that you are not a bot: ";
cin >> humanInput;
isHuman = isThisHumanInput(humanInput);
if (isHuman) {
cout << "Success" << '\n';
} else {
cout << "Not success, try again!\n";
}
} while (!isHuman);
}
There's several changes that are necessary to get this code functioning correctly. Here's one working version, with the functions and includes that you don't actually use yet removed and a typo corrected.
Highlights: We have to initialize humanInputvalidator, we have to reset isHuman to true at the beginning of the do-while loop, and the logic for exiting the inner for loop and printing "Success!" was all changed.
#include <iostream>
#include <string>
void botVerification();
int main()
{
botVerification();
return 0;
}
void botVerification()
{
std::string humanInput;
std::cout << "Enter the number to verify that you are not a bot: ";
std::getline(std::cin, humanInput); // getline to capture whitespace
bool isHuman;
do {
isHuman = true; // Reset to true at the beginning of each loop
// Initialize humanInputvalidator
for (int humanInputvalidator = 0; humanInputvalidator < humanInput.length() && isHuman; humanInputvalidator++) {
// Rewrite comparison using char literals for clarity
if (!(humanInput[humanInputvalidator] >= '0' && humanInput[humanInputvalidator] <= '9')) {
isHuman = false;
std::cout << "Not success, try again! ";
std::getline(std::cin, humanInput);
// No need to break since we test isHuman in the for loop
}
}
} while (!(isHuman));
// Print success after input is fully verified, not at some intermediate stage
std::cout << "Success!\n";
}
First of all, you need to initialize humanInputvalidator when you define it in the for loop. Variables in C++ do not have default values.
Also, in case you find an incorrect character in humanInput, you make the user input again. This happens while you are iterating over the characters in the string. This is not really good. In this particular case it does not break, but it may in some other one, so keep that in mind.
Moreover, in the for loop you alway break on the first iteration. Your break statement is just below the if-else and I think your intention was that it be inside the else branch.
All in all, I cannot pinpoint any specific reason for the infinite loop you are getting but these are at least a few things you can fix and then see what happens. I would also suggest to simplify your code and make it more readable, by splitting out the invalid input check to a separate function, like this:
bool isInputValid(const string& humanInput)
{
for (int humanInputvalidator = 0; humanInputvalidator < humanInput.length(); humanInputvalidator++) {
if (!(humanInput[humanInputvalidator] >= 48 && humanInput[humanInputvalidator] <= 57)) {
return false;
}
}
return true;
}
void botVarification()
{
string humanInput;
cout << "Enter the number to verify that you are not a bot: ";
cin >> humanInput;
do {
if (isInputValid(humanInput))
{
cout << "Success" << '\n';
break;
}
cout << "Not success, try again!";
cin >> humanInput;
} while (true);
}
I put a do/while loop in my password function but it doesn't work. I use xcode10 to code c++ and when I use a semicolon after the while statement it shows an error saying code will never execute
string password (string g)
{
string ch = "hello" ;
cout << "Enter password";
getline(cin, g);
do {
if (ch.compare(g) != 0) {
cout << " INCORRECT PASSWORD";
return (0);
} else {
cout << "correct password";
return (string(g));
}
} while (ch.compare(g) == 0); //this is where it shows the error that the code will never exec
}
I wanted to put this loop and a few other things so I can make this a infinite loop till you enter the correct password.
Well in your if statement you will return in both cases causing the function to stop so it will never get to the while condition to test it
string password(string g)
{
string ch = "hello";
cout << "Enter password\n";
do
{
getline(cin, g);
if (ch.compare(g) != 0)
{
cout << " INCORRECT PASSWORD\n";
}
else {
cout << "correct password";
return (string(g));
}
} while (ch.compare(g) != 0);
}
You need to check if you get input at all too, in case of EOF.
string password() { // you don't need g as parameters in, your overwriting it
string const ch = "hello"; // make ch const to show it not supposed to change
cout << "Enter password";
string g; // defining g here since now you need it
while (getline(cin, g)) { // check that the read from cin is OK
if (ch != g) { // simple notation for comparing two strings. There's also == available
cout << "INCORRECT PASSWORD. Please try again\n"; // no return if you want to try again
} else {
cout << "correct password";
return g; // you could also return ch here since they have the same content
}
}
cout << "Unable to read line. aborting\n"; // not really a lot you can do if there is no input to read.
return string(); // returning empty string.
}
There is Return statement in the "if" and also in the "else".
You can see that no matter what will be the result of ch.compare(g), the function will return to it's caller.
That's why it will never do the "while".
Try to set the Return statements in different place in the code :)
void Game::validate(string& str1)
{
bool exit = false;
int strLength = str1.length();
while (exit == false)
{
for (int i = 0; i < strLength; i++)
{
if(!isalpha(str1[i]) || isspace(str1[i])) //|| str1.empty())//?
{
cout << "Not a valid name, please try again: " << endl;
getline(cin, str1);
}
else if(isalpha(str1[i]))
{
exit = true;
}
}
}
I am passing down a string,i need to output the error message
if the user hits the Enter key only*. Ive tried using '\n' but isspace should take care of that(which it dosent). When i run the program and hit ENTER only, it freezes...whats wrong with it??? All other validation works except the ENTER key
Blockquote
try and print out your string before you start checking and you'll probably
see that the string is not empty even though enter key was the only input.
before you have the user input try and flush the stream.
try std::cout<<endl;