How would I have string validate just the ENTER key being hit? - c++

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;

Related

Getting error "code will never execute" when using do-while loop for password checking function in c++e

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 :)

How to display a specific error to the user, requiring him/her to provide input again using a loop?

using namespace std;
int main(){
// Variable declarations
string hours = "";
double empHours = 0;
bool cont = true;
do{
// Get input of how much employee worked in a week.
cout << "Enter hours worked in a week: " ;
getline(cin, hours);
// Convert the input using string stream for easier validation.
stringstream hours_input(hours);
for(int i = 0; i <= hours[i]; i++)
// Check if input contains any alphabets e.g 90abc, if yes than repeat loop and ask user for input again.
if(isalpha(hours[i]))
cont = true;
// If the input successfully converts to double type
else if(hours_input >> empHours)
// Check if values are values >= 0, if yes than exit the loop
if(empHours >= 0){
hours_input >> empHours; // Assign value to empHours and exit loop
cont = false;
}
// Check if input contains special characters or any other form of bad input, if yes than repeat loop and ask user for input again.
else
cont = true;
}while(cont);
cout << "Value is: " << empHours << endl;
return 0;
}
This is what I have got so far. I am just not sure on how to display the error "That is not a valid option, please try again." and ask for input again. The code works however instead displaying the error mentioned, it displays "Enter hours worked in a week: ".
Simply, keep looping the error "That is not a valid option, please try again." and asking for input, until a valid input is provided.
The valid input should be any integer or float number >= 0.
Invalid inputs are any special characters, alphabets and any form of negative numbers.
You could just use a while loop.
It could go something like this:
while(true){
cin>>foo;
if(check if foo is a valid input){
break; //if the input is valid
}
cout<<"error, try again";
}
Currently, your code doesn't contain anything to print your error message. You already seem to be handling the error scenario though, so adding it isn't that hard.
If you change the else case in your for loop like this, it should work:
for(int i = 0; i <= hours[i]; i++)
// Check if input contains any alphabets e.g 90abc, if yes than repeat loop and ask user for input again.
if(isalpha(hours[i]))
{
cout << "That is not a valid option, please try again." << endl;
cont = true;
}
// If the input successfully converts to double type
else if(hours_input >> empHours)
// Check if values are values >= 0, if yes than exit the loop
if(empHours >= 0){
hours_input >> empHours; // Assign value to empHours and exit loop
cont = false;
}
// Check if input contains special characters or any other form of bad input, if yes than repeat loop and ask user for input again.
else
{
cout << "That is not a valid option, please try again." << endl;
cont = true;
}
You should however consider refactoring your code a bit to prevent some duplication. If you validate the input in a separate function for example, you can have one clear place of error handling instead of the duplication you have now.

do while loop ignores my bool flag variable c++

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.

C++ user input restrictions

I'm currently working on a program and thinking if it is possible to implement another restrictions for the user input. The restrictions that I made as of now is that the user is only allow to input alpha and spaces, hitting enter without any input will not be also accepted.
cout<<"Input customer's lastname\t\t: ";
getline(cin,lname);
if(lname.find_first_not_of("abcdefghijklmnopqrstuvwxyz ")!=string::npos)
{
cout<<"You can only input alpha here!\n";
cin.clear();
goto p1;
}
else if(lname.empty())
{
cout<<"Please enter your lastname!\n";
cin.clear();
goto p1;
}
The another restrictions that I want is if the user input is all spaces, the program will also show a message. Second, I wonder if it's possible to detect the input if the user typed it properly like (de la Cruz) the words should be only separated by one space and if not another message will show. I cant think on how to do it, I already did some research but I couldn't found any similar to this with C++. I don't know if this is possible since I'm just starting to learn C++, or maybe I don't have enough logic at all. :(
A little help from me on checking for spaces.
bool has_only_spaces(const std::string& str)
{
return str.find_first_not_of (' ') == str.npos;
}
bool has_two_consecutive_spaces(const std::string& str)
{
for (unsigned int i = 1; i < str.length(); i++)
{
if ((str[i - 1] == str[i]) && (str[i] == ' '))
{
return true;
}
}
return false;
}
int main()
{
std::string lname;
std::cout << "Input customer's last name: ";
getline(std::cin, lname);
if (has_only_spaces(lname) || has_two_consecutive_spaces(lname))
{
std::cout << "Not a valid input" << std::endl;
std::cin.clear();
}
}
Create a function to check whether the input is valid. Use the function in a while loop.
bools isInputValid(std::string const& input)
{
// add all the checks
}
Use it as:
std::cout << "Enter input\n";
while ( getline(std::cout, line) )
{
if ( isInputValid(line) )
{
break;
}
std::cout << "Input is not vaild. Try again\n";
}

C++ function runs more than intended

When I run my program the user can log in, but if the enter in a wrong user name, it runs a check username loop again, saying that they did not enter in a valid user name. This work perfectly fine except for one thing. Say they attempt to log in in three times and the third attempt is correct and the get prompted for a password. Once they input it it ask for a second password and then a third. It seems like it is completing the function for the other attempts. I can not think of a way to check for this. Any ideas.
If you look at it you can see that I am calling UserCheck inside of getNameIndex. I am almost positive this is where the error is occurring.
The Function that checks the users:
void User_Psw::UserCheck()
{
// read from the database
ifstream fin("dataBase.txt", ios::in);
if( !fin.good() )
{
cout << "Failed to open database file." << endl;
return;
}
while (fin >> username >> password)
{
Usernames.push_back(username);
Password.push_back(password);
++sizeOfDatabase; // This may or may not be needed elsewhere.
}
// rest of the program
cout << "Username: ";
cin >> username;
getNameIndex();
cout << "Password: ";
cin >> password;
if(!PasswordMatches())
{
cout << "Access denied";
}
else
{
cout << "Success! You have logged in.";
}
}
This is the username check function
void User_Psw::getNameIndex()
{
userThere = false;
for(int i=0; i < sizeOfDatabase; i++)
{
if (Usernames[i] == username)
{
index = i;
userThere = true;
}
}
if (userThere == false)
{
cout << "\nThat user name does not exsist. \n";
cout << "Please try again. \n\n";
UserCheck();
}
}
The structure of your program is wrong.
Instead of getNameIndex calling UserCheck() again, you should have getNameIndex return a bool - true on success, false on failure. Run it inside of a loop, something like this:
bool success = false;
while (!success)
{
cout << "Username: ";
cin >> username;
success = getNameIndex();
}
Also, instead of having global variables, you should pass them to the function. Something like:
success = getNameIndex(username);
and getNameIndex() shouldn't do any I/O - the function that calls getNameIndex() should also be responsible for printing the error message. Imagine if you used getNameIndex() in a different context, such as when when the program is being run by another program or in an automated way - then printing to the console would be meaningless.