I want to take 8 char password from user and then when she/he wanted to enter, I wanted it to be whatever size she/he enter. However, the code doesn't stop until it reaches 8 char, even I press 'enter', it takes it as a char and create '*'. I want its size to be whatever user write and then user press 'enter', it will take these characters as password to see if it is matched with registered password. For example;
- User register password as 'wellcode'
- After that, user write in login screen 'well' then enter(in my code it lasts until I reach 8 characte
- 'Login failed! will be written
Is there a way to do that in C ?
bool CheckCredentials(string);
char pass[8], inPass[8];
int main()
{
fstream encrypted;
bool done = false;
while (!done)
{
cout << "1. Register a password" << endl;
cout << "2. Login your password" << endl;
cout << "3. Exit" << endl;
int menuChoice;
cin >> menuChoice;
if (menuChoice == 1)
{
ifstream ifile;
ifile.open("password.txt");
if (ifile){}
else
{
cout << "New password must contain only 8 characters: ";
for (int i = 0; i < 8; i )
{
pass[i] = _getch(); _putch('*');
}
ofstream l("password.txt", ios::out);
if (!l.is_open()) {
cout << "could not open file \n";
}
for (int i = 0; i < 8; i )
{
l << pass[i];
}
l.close();
cout << "\n\n";
}
}
else if (menuChoice == 2)
{
cout << "Password: ";
for (int i = 0; i < 8; i )
{
inPass[i] = _getch(); _putch('*');
}
if (CheckCredentials(inPass) == true)
{
cout << "\nLogin sucessful!" << "\n\n";
}
else
{
cout << "\nLogin failed!"
}
}
else if (menuChoice == 3)
{
done = true;
break;
}
}
return 0;
}
bool CheckCredentials(string inPass)
{
string s;
bool status = false;
ifstream f;
f.open("password.txt");
if (!f.is_open())
{
cout << "Unable to open file!\n";
}
else if (f)
{
while (!f.eof())
{
f >> s;
if (inPass == s)
{
status = true;
}
else
{
status = false;
}
}
}
f.close();
return status;
}
CodePudding user response:
Your code is
for (int i = 0; i < 8; i )
{
inPass[i] = _getch();
_putch('*');
}
Obviously that loops exactly eight times, doesn't matter what you type.
If you want to stop the loop early then you must write the code to test for that possibility. Something like
int inPassLength = 0;
for (int i = 0; i < 8; i )
{
char ch = _getch();
if (ch == '\n') // quit loop if enter is pressed
break;
inPass[inPassLength ] = ch;
putch('*');
}
You also need to add a variable to record how long the password is (since it may not be exactly 8 characters any more) that's what inPassLength
is in the code above.
CodePudding user response:
Your loop for (int i = 0; i < 8; i )
runs exactly eight times so you read exactly eight characters.
Instead you need to discover the user completing the password by pressing enter key and break the loop in that case. Additionally you need to consider the real number of characters the user entered, not again iterate exactly eight times to output the characters.
Then you haven't considered at all the user deleting input again! It would be pretty unhandy to see additional asterisks appear on pressing backspace key!
To cover all this I recommend using std::string
instead and iterate endlessly, such as follows:
std::string pw;
for(;;)
{
char c = getch();
if(c == '\n')
{
break;
}
if(c == '\b')
{
putch('\b'); // remove character from screen
pw.resize(pw.length() - 1); // remove character from storage
}
else
{
putch('*');
pw = c;
}
}
if(pw.length() > 8)
{
// too long!
}
else
{
std::ofstream l /*...*/;
l << pw; // just output the entire string at once...
}
Note: This is entirely untested code! If you find a bug, please fix yourself.
Note, too, that this answer does not cover every potential user behaviour (pressing backspace is just the most prominent one), e.g. pressing the arrow keys to move the cursor, del
button (even at input end), ... To cover some of these you might fall back to even more low level API (GetKeyState
and similar).