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
}
}
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 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'm trying to build a simple password validator:
Program prints
"Very weak" if password has less than 8 characters and all numbers.
"Weak" if password has less than 8 characters and all alphabets.
"Strong" if password has 8 or more characters and contains numbers and alphabets.
"Very strong" if password has 8 or more characters and contains numbers, alphabets and special characters.
As you can see, I know how to check if a string has either one of the three types of characters.
How can I check if a string has two or all three?
#include <iostream>
#include <ctype.h>
#include <cstring>
int main()
{
std::cout << "Enter your new password: ";
std:: string password{};
std::cin >> password;
bool veryweak;
bool weak;
bool strong;
bool verystrong;
if (password.length() < 8)
{
for (int i = 0; i < password.length(); i++)
{
if (isdigit(password[i]))
{
veryweak = true;
}
else if (isalpha(password[i]))
{
weak = true;
}
}
}
else if (password.length() >= 8)
{
for (int i = 0; i < password.length(); i++)
{
//if (password has digits and alphabets)
//strong = true;
//if (password has digits and alphabet and special characters)
//verystrong = true;
}
}
else
{
std::cout << "Password is invalid.";
}
//---------------------------------------------------------------------------------------------------------------------
if (veryweak)
{
std::cout << "Your password is very weak.";
}
else if (weak)
{
std::cout << "Your password is weak.";
}
else if(strong)
{
std::cout << "Your password is strong.";
}
else if (verystrong)
{
std::cout << "Your password is very strong.";
}
return 0;
}
I would introduce the booleans:
isShortPassword
containsNumbers
containsAlphabet
containsSpecialCharacters
than you can write
std::string passwortStrengt () {
if (isShortPassword && !containsAlphabet && !containsSpecialCharacters) {
return "weak";
//forumlate all cases as you did in prosa up above
} else if (...) {
} else if (...) {
}
return "weak"; // just in case you missed a case above
}
Why don't you use some counter like weakness_counter or something. For each property that is fulfilled, the counter is incremented by one. And at the end you check how much properties are fulfilled and rate the password strength after this.
Further I would recommend you to write an own function for each of your properties, like:
bool containsNumbers(string pw);
bool containsLetters(string pw);
And so on. In this case it's more easy to read, change and extend the code by new properties etc..
I hope I could help you.
Regards :)
My assignments requires me to keep accepting input from the user and output whether or not it is a palindrome until the word DONE is inputed.
Also, words like Bob must have an output of true because we must disregard case (upper/lower.)
This is my first time using C++.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string wordInput;
while (wordInput != "DONE")
{
cout << "Please enter a word: ";
cin >> wordInput;
int wordLength = wordInput.length();
int wordHalf = (wordLength / 2);
bool flag = false;
for (int i = 0; i <wordHalf; i++)
{
if (tolower((wordInput[i]) == tolower(wordInput[wordLength-1-i])))
{
flag = true;
}
else
{
flag = false;
break;
}
}
if (flag == true)
{
cout << "true"<<endl;
}
else
{
cout << "false"<<endl;
}
}
return 0;
}
It might have something to do with 'wordInput' being declared twice, once right before the while loop and once within it. It is mixing up what the while loops condition is looking at.
Your issue with words not being correctly identified comes from this line:
if(tolower((wordInput[i]) == tolower(wordInput[wordLength-1-i])))
If you look carefully, you set the parentheses incorrectly. Try this instead:
if(tolower(wordInput[i]) == tolower(wordInput[wordLength-1-i]))
I can't get my password verify program to work. My loop seems to only iterate once, I just put "it" as output to see if it's constantly iterating, but its not. I'm not sure why, the booleans are working, but it just iterates once, and if my first letter is a lowercase, then it'll say I need an uppercase and a digit, and vice-versa if my first character is a digit or uppercase. This is a homework assignment, but I'm a little lost. Any help would be greatly appreciated.
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int main()
{
const int LENGTH = 20;
char pass[LENGTH];
cout << "Enter a password, that's at least 6 characters long, one uppercase, one lowercase letter ";
cout << " and one digit." << endl;
cin.getline(pass,LENGTH);
bool isdig = true;
bool isdown = true;
bool isup = true;
bool correct = false;
for(int index = 0; correct == false; index++)
{
cout << "it" << endl;
if(isupper(pass[index]) == 0)
{isup = false;}
if(islower(pass[index]) == 0)
{isdown = false;}
if(isdigit(pass[index]) == 0)
{isdig = false;}
if(isdig == true && isup == true && isdown == true)
{correct = true;}
if(index = LENGTH - 1)
{
if(isdig == false)
{cout << "Your password needs a digit." << endl;}
if(isup == false)
{cout << "Your password needs an uppercase letter." << endl;}
if(isdown == false)
{cout << "Your password needs a lowercase letter." << endl;}
cout << "Re-enter another password. " << endl;
cin.getline(pass,LENGTH);
index = 0;
isdown = true;
isup = true;
isdig = true;
}
}
system("pause");
return 0;
}
The problem is probably this line:
if(index = LENGTH - 1)
Here you assign the value of LENGTH - 1 to index, so you are always asked to re-enter your password as that expression always is true.
You should enable your compiler warning (-Wall if you are using g++) and pay attention to the warnings:
es.cpp:52:30: warning: suggest parentheses around assignment used as truth value
This tells you that some condition (a==b) as probably been written as (a=b) which is an assignment. And indeed
if(index = LENGTH - 1)
should be written
if (index == LENGTH - 1)
Also for readability
if(isdig == true && isup == true && isdown == true)
could be replaced by
if (isdig and isup and isdown)
and
if(isdig == false)
by
if (not isdig)