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!
Related
This question already has answers here:
Breaking out of an infinite loop
(2 answers)
do ... while loop not breaking c++
(2 answers)
Closed 6 months ago.
This post was edited and submitted for review 6 months ago and failed to reopen the post:
Duplicate This question has been answered, is not unique, and doesn’t differentiate itself from another question.
I'm just starting C++ and creating a simple password validation program. [edit] My goal is to display each messages if there is a lack of uppercase, lower case, digits, and/or special characters.
If there is only special character the output will be like this:
Enter your password: !
Password must contain a lower case!
Password must contain an upper case!
Password must contain a digit!
Enter your password:
what i want if all the requirements are met:
Enter your password: 1qQ+
your password is created
program is finished
But what i got is infinite loop of "your password is created".
Any solution or alternative to make my code better/efficient?
Sorry for bad intendation.
#include <iostream>
#include <string>
using namespace std;
void passcheck(string& password)
{
bool hasUpper = false, hasLower = false, hasDigit = false, hasSpecialchar = false;
for (int i = 0; i < password.length(); ++i)
{
if (islower(password[i]))
{
hasLower = true;
}
else if (isupper(password[i]))
{
hasUpper = true;
}
else if (isdigit(password[i]))
{
hasDigit = true;
}
else if (password.find(" !#$%&'()*+,-.:;<=>?#[]^_`{|}~"))
{
hasSpecialchar = true;
}
}
do
{
if (!hasLower)
{
cout << "Password must contain a lower case!"<< endl;
}
if (!hasUpper)
{
cout << "Password must contain an upper case!"<< endl;
}
if (!hasDigit)
{
cout << "Password must contain a digit!"<< endl;
}
if(!hasSpecialchar)
{
cout << "Password must contain special char!"<< endl;
}
else
{
cout << "your password is created" << endl;
}
}while(hasSpecialchar && hasDigit && hasLower && hasUpper);
}
int main(int argc, char const *argv[])
{
string password;
do{
cout << "Enter your password: ";
getline(cin, password);
passcheck(password);
}while(true);
cout << "program is finished" << endl;
cin.get();
return 0;
}
You want to execute the loop until all the boolean expressions are true I assume. This would evaluate to
do{
//your stuff
} while(!(hasSpecialchar && hasDigit && hasLower && hasUpper))`
But depending on what exactly you're trying to do there's probably a better approach then a do-while loop. Where do you set these booleans? If you're using a single thread, then this values aren't gonna change inside the loop and the whole loop doesn't make any sense.
you can use break keyword, like this
while (1) {
...
if (cond) {
break
}
}
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.
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;
I finally figured out how to make the function I was looking for, however the issue I am having is I would like to have it only repeat asking for the password input, instead of both the username and password.
#include "stdafx.h"
#include <iostream> // library that contains basic input output functions
#include <string> // library for c++ strings
using namespace std;
int main()
{
//Username and Password to validate credentials
const string USERNAME = "myself";
const string PASSWORD = "stanley";
const string USERNAME2 = "otherperson";
const string PASSWORD2 = "otherpassword";
//strings in which user will enter username and password
string username, password;
int passattempts = 0;
do{
// Prompting user to input username
cout << "Enter Username : ";
cin >> username;
//Checking if username length is less than 4 characters then display an error message
if (username.length() < 4)
{
cout << "Username length must be atleast 4 characters long.";
}
else //if username length is greater than 3
{
//promprting user for password
cout << "Enter Password : ";
cin >> password;
//Checking if password length is less than 6 characters then display an error message
if (password.length() < 6)
{
cout << "Password length must be atleast 6 characters long.";
}
else //if password length is greater than 5
{
//Checking if user's entered credentials are equal to actual USERNAME and PASSWORD
if (username == USERNAME && password == PASSWORD || username == USERNAME2 && password == PASSWORD2)
{
cout << "User credentials are correct!!!" << endl;
break;
}
else
{
cout << "Invalid login details" << endl;
++passattempts;
}
}
}
} while (passattempts != 3);
system("pause");
return (0);
}
Then put the entry (and check on) the username outside the password do loop.
You can always put those inside another do loop if you want to allow the user to re-enter a username that is too short. There's no rule that says you're only allowed one loop :)
something like (pseudo code)
do
{
prompt for username
read username
} while (username invalid)
do
{
prompt for password
read password
} while (password invalid)
There's a philosophical argument to be had about whether or not you tell the user why their data is invalid. I'm not being drawn into that, security people can get a bit... intense.
I have a struct called users containing username information:
struct User{
string name;
string type;
int credit;
bool loginState;
};
My program reads in a txt file and creates an array of User struct types called "users" to store all the data. Im trying to create a function that deletes a user, so in the for loop below I'm searching for the string
userName
in the users array. If the user name exists then all the information of that user account is stored in the User temp. Otherwise an error is generated stating that the user entered does not exist.
string userName;
User temp;
cout<<"Please enter a username to delete:";
cin >> userName;
for(int i=0; i<usersSize; i++){
if((users[i].name).compare(userName) == 0){
temp.name = users[i].name;
temp.type = users[i].type;
temp.credit = users[i].credit;
temp.loginState = users[i].loginState;
}else{
cout << "Error: User does not exist";
}
}
I've tested my program and no matter what the input is, whether the user exists or not, the if statement always outputs the second condition. How can I fix this?
You need to first check if the user exists and then process the user which was found. The problem in your code is that the for loop checks all users and shows a message for all users but the one that matches (if any).
Check this code:
bool userWasFound = false;
int i;
for(i=0; i<usersSize; i++){
if((users[i].name).compare(userName) == 0){
userWasFound = true;
break;
}
}
// If no user was found, 'userWasFound' will still be 'false' at this point
if(userWasFound){
temp.name = users[i].name;
temp.type = users[i].type;
temp.credit = users[i].credit;
temp.loginState = users[i].loginState;
}else{
cout << "Error: User does not exist";
}
Use a flag to indicate that user found or not.. e.g;
bool flag=false;
for(int i=0; i<usersSize; i++){
if((users[i].name).compare(userName) == 0){
temp.name = users[i].name;
temp.type = users[i].type;
temp.credit = users[i].credit;
temp.loginState = users[i].loginState;
flag=true;
break;
}
}
if(!flag){
cout << "Error: User does not exist";
}
Hope it helped...