I am trying to read a pasword and while I read it , display ** .
cout << "\n Insert password : ";
loop1:
string passw1 = "";
char ch = _getch();
while (ch != 13) // enter = char 13
{
if (!isalnum(ch))
{
cout << "\n\n Invalid character! Please insert the password again! ";
goto loop1;
}
passw1.push_back(ch);
cout << "*";
ch = _getch();
}
If I press for example , BACKSPACE , or SPACE or something that is not alpha-numerical , everything goes as planned. The problem is when I press any F key , or DELETE , HOME , INSERT , END , PG UP , PG DOWN , when the program crashes . Could you help me avoid the crash ? I would like to show an error message if an invalid key is pressed , not to have my program crash.
Let's see if I understand what you're trying to do (in pseudocode):
Prompt the user for a password
Wait for the user to press any key
While the key pressed is not the enter key
If the entered key is an alphanumeric
Add the character to the password string
Print an asterisk on the screen
Accept another character
Else
Alert the user that they entered a non-alphanumeric
Clear out the string and have the user start over again
End If
End While
If that's not what you're after, then modify to taste.
What I think is happening is that you're not capturing all of the possible characters when you test what key was pressed. If DEL is giving you trouble, then figure out how to catch it or handle it (remove an asterisk from the screen, and delete a character from the string).
Good luck!
It crashes on my Win7 x64 VS2010 system as well. Turns out _gech() is returning 224 for the DEL key, which is -32 in a signed char. This is causing isalnum() to assert internally.
I changed the char to an int (which is what _getch() is returning and isalnum() takes for a parameter) and the overflow problem went away. unsigned char works as well.
int main( )
{
cout << "\n Insert password : ";
loop1:
string passw1 = "";
int ch = _getch();
while (ch != 13) // enter = char 13
{
if (!isalnum(ch))
{
cout << "\n\n Invalid character! Please insert the password again! ";
goto loop1;
}
passw1.push_back(ch);
cout << "*";
ch = _getch();
}
return 0;
}
Yields (pressing DEL each time):
Insert password :
Invalid character! Please insert the password again! *
Invalid character! Please insert the password again! *
Use the is alphanumeric function - isalnum(char c ) to check if the parameter c is either a decimal digit
or an uppercase or a lowercase letter.
And then filter out characters less than 32 or higher than 122 like this : if (c > 32 && c <122) { Get_Password(); }
This MS Windows specific code below is not portable. For Linux/*NIX/BSD see this : Hide password input on terminal
#include <iostream>
#include <string>
#include <conio.h>
int main()
{
std::string password;
char ch;
const char ENTER = 13;
std::cout << "enter the password: ";
while((ch = _getch()) != ENTER)
{
if (ch > 32 && ch<122)
{
if (isalnum(ch))
{
password += ch;
std::cout << '*';
}
}
}
std::cout <<"\nYour password is : " << password<<"\n\n";
return 0;
}
Related
I want to create a program that allows the user to create a password and username. However, the password must be between 6 and 10 characters. How would I limit the character input? Also, what if I want the password to include capital letters?
Here's a look at the program so far to give you an idea of what I am trying to do (NOTE: I know the program itself is obviously unfinished but I just want to give you a visual):
#include <iostream>
#include <string>
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "--------------------------------------------------------------\n";
std::cout << " Welcome to the ECE!! Password Proram!\n";
std::cout << "Username rules: must be 5-10 characters long with no space\n";
std::cout << "Password rules: must be 6+ characters long\n";
std::cout << "Must contain one uppercase letter and one number but no space\n";
std::cout << "--------------------------------------------------------------\n";
//Let's get our password!
std::string username;
std::string password;
const int
//use a do while loop for input validation
do {
std::cout << "Enter your username: ";
std::cin >> username; //add input validation
} while ();
std::cout << "Enter your password:";
std::cin >> password;
return 0;
}
Since you're using std::string, you can use password.size() after getting the user input and checking if the size is within the limits of 5 & 10. If it's not, simply re-query the user for another password. This would be best done in a while loop.
Here is an example of some code from a higher level:
do{
std::cout << "Enter your password:";
std::cin >> password;
}while (password.size() < 6 || password.size() > 10)
You're already doing a similar thing with username, so I was a bit confused on if you meant to be asking about password or not.
To limit character input, you would want to check if the input length is between 6 and 10 characters inclusive. (I don't know of a way to cut off input after 10 characters) You would do something like
start: // A label to direct where the program should go when goto is called.
while(password.length() > 10 || password.length() < 5)
{
std::cout << "The password must be between 5 and 10 characters inclusive." << endl;
std::cin >> password;
}
// To check if there is a capital letter
bool foundUpperLetter = false;
for(int i = 0; i < password.length(); i++)
{
if(foundUpperLetter == true)
break;
if('A' <= password[i] && password[i] <= 'Z')
foundUpperLetter = true;
}
if(!foundUpperLetter)
{
std::cout << "You did not include an uppercase letter in your input. Please try again." << endl;
goto start; // Will make the program go back to label start.
}
You could also add more code to the above section to check for other attributes that the password requires.
Source: 15 months of coding for school and personal enjoyment. Please add your own answer if there is a better way to do something or if you know a way to cut off input after 10 characters
On a conceptual level: you could take in a string input, check the length and other properties (i.e. contains one uppercase letter), use it for further operations. If it does not meet the following criteria, ask the user to re-enter the information.
I'm looking for a method to limit the visible user input using std::cin.
#include <iostream>
int main()
{
std::cout << "Enter your planet:\n";
string planet;
std::cin >> planet; // During the prompt, only "accept" x characters
}
What the user sees if they enter earth or any other word exceeding 4 characters before pressing enter:
Enter your planet:
eart
This is assuming the character limit is 4, note that the 'h' is missing. The console does not display any other character once it has exceeded the character limit. and this is before you press the enter key.
Kinda like typing in an input box like password fields, but it only allows 5 characters, so typing any other character goes unnoticed
A better analogy would be the maxlength attribute for text input in HTML.
That can't be achieved portably, because OS consoles aren't part of C++ standard. In windows, you could use <windows.h> header - it provides console handles etc., but since you didn't specify OS you are using, the is no point in posting windows-only code here (since it might not meet your needs).
EDIT:
Here is (not perfect) code that will limit visible input of the user:
#include <iostream>
#include <windows.h>
#include <conio.h>
int main()
{
COORD last_pos;
CONSOLE_SCREEN_BUFFER_INFO info;
std::string input;
int keystroke;
int max_input = 10;
int input_len = 0;
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
std::cout << "Input (max 10) characters, press ENTER to prompt:" << std::endl;
GetConsoleScreenBufferInfo(handle, &info);
last_pos = info.dwCursorPosition;
while(true)
{
if(kbhit())
{
keystroke = _getch();
//declare what characters you allow in input (here: a-z, A-Z, 0-9, space)
if(std::isalnum(keystroke) || keystroke == ' ')
{
if(input_len + 1 > max_input)
continue;
++input_len;
std::cout << char(keystroke);
input += char(keystroke);
GetConsoleScreenBufferInfo(handle, &info);
last_pos = info.dwCursorPosition;
}
else if(keystroke == 8) //backspace
{
if(input_len - 1 >= 0)
{
--input_len;
input.pop_back();
COORD back_pos {short(last_pos.X-1), last_pos.Y};
SetConsoleCursorPosition(handle, back_pos);
std::cout << ' ';
SetConsoleCursorPosition(handle, back_pos);
GetConsoleScreenBufferInfo(handle, &info);
last_pos = info.dwCursorPosition;
}
}
else if(keystroke == 13) //enter
{
std::cout << std::endl;
break;
}
}
}
std::cout << "You entered: " << std::endl
<< input << std::endl;
}
After a few days of experimenting, I found another solution that seems to be quite easy to grasp as it is somewhat beginner level and without requiring any knowledge of windows programming.
NOTE:
The conio.h library function _getch() could easily be replaced with the getchar() function;
I'm not saying the previous answer was not okay, but this solution is sort of aimed towards beginners with only basic knowledge of c++
char ch;
string temp;
ch = _getch();
while(ch != 13)// Character representing enter
{
if(ch == '\b'){ //check for backspace character
if(temp.size() > 0) // check if string can still be reduced with pop_back() to avoid errors
{
cout << "\b \b"; //
temp.pop_back(); // remove last character
}
}
else if((temp.size() > 0) || !isalpha(ch))// checks for limit, in this case limit is one
{ //character and also optional checks if it is an alphabet
cout << '\a'; // for a really annoying sound that tells you know this is wrong
}else {
temp.push_back(ch); // pushing ch into temp
cout << ch; // display entered character on screen
}
ch = _getch();
}
This could probably use some tweaks, because it's definitely not perfect, but I think it is easy enough to understand, at least I hope so
Following is the code for a login program that inputs the username, and then the password, while echoing '*' for every character entered, and then compares the username and password to preset values to see if they match and exits the program if it is true, else it goes back to the beginning.
int main()
{
int i = 0; string u; char parr[i + 1], ch;
while (1)
{
system("cls");
cout << "Enter username." << endl;
cin >> u;
system("cls");
cout << "Enter password." << endl;
i = 0;
while (1)
{
tag:ch = getch();
if (ch == '\r')
{
break;
}
if (ch == '\b')
{
cout << '\b';
--i;
ch = '\0';
parr[i] = '\0';
cout << ' ' << '\b';
goto tag;
}
parr[i] = ch;
ch = '*';
cout << ch;
++i;
}
parr[i] = '\0';
string p = "password";
if (u == "username" && parr == p)
{
system("cls");
cout << "Welcome!";
break;
}
else
{
system("cls");
cout << "Username and password entered does not match! Please try again.";
}
getch();
}
getch();
}
Now, here's the problem: Recently, I found out that this method of input (for the password) doesn't work as intended with Backspace, Delete, or the arrow keys. All of these keys input certain symbols instead of deleting characters or moving the cursor. So I tried out a workaround (currently only) for the backspace key. All worked fine- the previous character was deleted when I pressed backspace, but in the end, after the comparison with the preset values, it showed that the password doesn't match.
If you could please help me in the following:
*Working backspace functionality (and delete and arrow keys if possible)
*Pressing Esc at ANY point of the program quits it.
*I have used goto in this program, whose atrocities we all already know of. Please suggest me a way to avoid this, and also to make all this code neater than its current messy state.
Use continue instead of goto. In your case this will do the same: jump to the start of the loop.
Then run a debugger and watch what happens with your array if you input backspaces.
So I am creating a simple password program that asks you for an input but masks it with asterisks (*). The code I have works, but when I backspace the string returned is like I had never backspaced.
What I would Type:
12345
I would hit the backspace twice, and the string would look like this:
123
But when I hit enter, it returns this:
1234
Here is the code that I have.
#include <iostream>
#include <string>
#include <conio.h> //Regular includes.
using namespace std;
string Encrypted_Text(int a) { //Code for the password masker
string Pwd = " "; //Creates password variable.
char Temp; //Temporary variable that stores current keystroke.
int Length = 0; //Controls how long that password is.
for (;;) { //Loops until the password is above the min. amount.
Temp = _getch(); //Gets keystroke.
while (Temp != 13) { //Loops until enter is hit.
Length++; //Increases length of password.
Pwd.push_back(Temp); //Adds newly typed key on to the string.
cout << "*";
Temp = _getch(); // VV This is were the error is VV
if (Temp == 8) { // detects when you hit the backspace key.
Pwd.pop_back; //removes the last character on string.
cout << "\b "; //Deletes the last character on console.
Length--; //decreases the length of the string.
}
}
if (Length < a) { //Tests to see if the password is long enough.
cout << "\nInput Is To Short.\n";
Pwd = "";
Temp = 0;
Length = 0;
}
else {
break;
}
}
return Pwd; //Returns password.
}
And in my main function i have this:
string Test = Encrypted_Text(5);
cout << "you entered : " << Test;
In your code you push_back whatever character you get. Only after that you remove a character if it is a backspace. This is why it doesn't work.
You need to first check for special characters and only if it is not one of those you add the character.
Also there is no need to have the Length variable since std::string knows its length and you can get it from there.
void createAccount(){
int i=0;
cout<<"\nEnter new Username: ";
cin.ignore(80, '\n');
cin.getline(newUsername,20);
cout<<"\nEnter new Password: ";
for(i=0;i<10,newPassword[i]!=8;i++){
newPassword[i]=getch(); //for taking a char. in array-'newPassword' at i'th place
if(newPassword[i]==13) //checking if user press's enter
break; //breaking the loop if enter is pressed
cout<<"*"; //as there is no char. on screen we print '*'
}
newPassword[i]='\0'; //inserting null char. at the end
cout<<"\n"<<newPassword;
}
In function createAccount(); the user is entering char newUsername[20] and char newPassword[20]. However, to display the password as ****** I've implemented a different way for entering newPassword. However, when I try displaying newPassword the output has an extra letter that magically appears in the command box without me entering anything.
OUTPUT
Enter new Username: anzam
Enter new Password: ****** //entered azeez but the first * is already there in command box without user inputting anything
Mazeez //displaying newPassword
If someone could help me I'd be extremely grateful.
One problem might be that you intermix conio (getch) and iostream (cin), and they might not be synchronized. Try adding this line at the beginning of your program:
ios_base::sync_with_stdio ();
Also, you read password until you see 13, but, if I'm not mistaken, in reality in windows pressing enter produces first 10 and then 13, so you might want to check for both as a stop condition.
i has been incremented at the end of the loop. The easiest way to fix this is to initialize password to zero
char newPassword[20];
memset(newPassword, 0, 20);
for (i = 0; i < 10; )
{
int c = getch();
if (c == 13)
break;
//check if character is valid
if (c < ' ') continue;
if (c > '~') continue;
newPassword[i] = c;
cout << "*";
i++; //increment here
}