输入缓冲和屏蔽密码输入C++



我使用的是cplusplus的一段代码,我不明白为什么这段代码跳过了密码的输入部分,直接跳到了电子邮件的输入部分。

//function to mask the input for password
string getpass(const char *prompt, bool show_asterisk=true)
{
const char BACKSPACE=127;
const char RETURN=10;
string password;
unsigned char ch=0;
//cout <<prompt<<endl;
while((ch=getch())!=RETURN)
{
if(ch==BACKSPACE)
{
if(password.length()!=0)
{
if(show_asterisk)
cout <<"b b";
password.resize(password.length()-1);
}
}
else
{
password+=ch;
if(show_asterisk)
cout <<'*';
}
}
cout <<endl;
return password;
}  

这里我称之为

void AgendaUI::userRegister(void)
{
string name, password, email, phone;
//cout << "n[register] [username] [password] [email] [phone]" << endl;
cout << "n[regist]";
cout << "n[username] ";
cin >> name;
cout << "[password] ";
password = getpass("Enter the password",true);
cout << "n[email] ";
cin >> email;
cout << "[phone] ";
cin >> phone;
}  

终端

因为当用户输入用户名时,他们也输入了Enter字符(这就是他们的终端如何提交行的(。cin >> name未读取该字符,该字符仍在缓冲区中。然后,getpass将其作为第一个字符读取,并立即停止。

请注意,您的代码与文章的代码不同,文章的代码不要求用户名,并且显示了一个相当脆弱的getpass(例如,当简单地添加您添加的基本代码时,它会崩溃,并且似乎依赖于您悄悄删除的termios黑客(。一般来说,尽量不要从网站上的文章中学习C++。不如从一本好书中学习!

您可以通过在cin >> name之后添加cin.ignore(256, 'n')来解决此问题,尽管坦率地说,这有点像黑客攻击,可以说使用std::getline提取用户名会更好。

我不明白为什么这段代码跳过了密码的输入部分

@Lightness在回答原因时提到了原因

要清除输入用户名后缓冲的换行符,需要清除输入流。

对于c,使用此fflush(stdin);

对于c++,请使用此std::cout.flush();

或者,你可以像我有时做的那样做另一件事,即在输入用户名后使用getchar();。这种方法不是一种标准的方法,但它是有效的。有时我们需要与getchar();一起冲洗流

根据您的代码示例,我认为您试图屏蔽用户输入的密码

为此,您可以在键入时禁用字符的回显。

当然,它不会打印任何花哨的星号或任何其他符号,相反,由于用户不断键入密码,输入字段将为空。

下面给出了我在这里使用的Windows&nix系统:

//Include other headers as well as per your program need
#ifdef WIN32
#include <windows.h>
#else
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#endif
void stdecho(bool enable = true)
{
#ifdef WIN32
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); 
DWORD mode;
GetConsoleMode(hStdin, &mode);
if( !enable )
mode &= ~ENABLE_ECHO_INPUT;
else
mode |= ENABLE_ECHO_INPUT;
SetConsoleMode(hStdin, mode );
#else
struct termios tty;
tcgetattr(STDIN_FILENO, &tty);
if( !enable )
tty.c_lflag &= ~ECHO;
else
tty.c_lflag |= ECHO;
(void) tcsetattr(STDIN_FILENO, TCSANOW, &tty);
#endif
}

代码用法如下:

cout<<"nLogin to begin :)";
cout<<"ntUsername : ";
cin>>username;
getchar();   // Here I am using `getchar();` to clear the new line remains in the input buffer
//you can also flush the input stream instead if this does not work or you can combine both
cout<<"tPassword : ";
stdecho(false);   //From now on I am disabling the echo from `std::cin`
getline(cin, password);  //No character will show up as you type your password
stdecho(true);    //From here the `std::cin` echo will be enabled again i.e., characters will start showing up again
pashash = hash(password); //Ignore from here...
password.erase();

有关更多详细信息和答案,请参阅"从std::cin读取密码"。

这个过程在控制台中的屏幕截图:图片01&图像02

最新更新