输入缓冲和屏蔽密码输入 C++
Input Buffering and masking password input C++
我正在使用 cplusplus 中的一段代码,但我不明白为什么这段代码只是跳过密码输入部分并直接跳转到 EMAIL 的输入部分。
//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;
}
Terminal
因为当您的用户输入用户名时,他们还输入了 Enter 字符(这就是他们的终端知道提交该行的方式)。此字符未被 cin >> name
读取,并且仍存在于缓冲区中。然后,getpass
将其作为第一个字符读取,并立即停止。
请注意您的代码与文章的代码有何不同,文章的代码不要求输入用户名,并且显示 getpass
相当脆弱(例如,仅添加您创建的基本代码时它就会中断添加,并且似乎依赖于您悄悄删除的 termios hack)。一般来说,尽量不要从网站上的文章中学习 C++。而是向 a good book 学习!
您可以通过 adding cin.ignore(256, '\n')
after cin >> name
解决此问题,但坦率地说,这有点乱七八糟,使用 std::getline
提取用户名可能会更好。
i can't get it why this code just skips the input part for password
原因是提到的是什么原因
要清除输入 用户名 后缓冲的换行符,您需要清除输入流。
对于 c 使用此 fflush(stdin);
对于 c++ 使用此 std::cout.flush();
或者您可以像我有时做的那样做另一件事,即在将 用户名 作为输入后使用 getchar();
。此方法不是执行此操作的标准方法,但它有效。有时我们需要与 getchar();
一起刷新流
根据您的代码示例,我认为您正试图掩盖用户输入的密码。
为此,您可以在键入时禁用字符回显。
当然它不会打印任何花哨的星号或任何其他符号,而是输入字段将是空的,因为用户不断输入密码。
我在 'here' 中使用的代码示例在下面针对 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<<"\n\tUsername : ";
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();
查看此 'Reading a password from std::cin' 了解更多详细信息和答案。
此过程在控制台中的截图:Image 01 & Image 02
我正在使用 cplusplus 中的一段代码,但我不明白为什么这段代码只是跳过密码输入部分并直接跳转到 EMAIL 的输入部分。
//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;
}
Terminal
因为当您的用户输入用户名时,他们还输入了 Enter 字符(这就是他们的终端知道提交该行的方式)。此字符未被 cin >> name
读取,并且仍存在于缓冲区中。然后,getpass
将其作为第一个字符读取,并立即停止。
请注意您的代码与文章的代码有何不同,文章的代码不要求输入用户名,并且显示 getpass
相当脆弱(例如,仅添加您创建的基本代码时它就会中断添加,并且似乎依赖于您悄悄删除的 termios hack)。一般来说,尽量不要从网站上的文章中学习 C++。而是向 a good book 学习!
您可以通过 adding cin.ignore(256, '\n')
after cin >> name
解决此问题,但坦率地说,这有点乱七八糟,使用 std::getline
提取用户名可能会更好。
i can't get it why this code just skips the input part for password
原因是提到的是什么原因
要清除输入 用户名 后缓冲的换行符,您需要清除输入流。
对于 c 使用此 fflush(stdin);
对于 c++ 使用此 std::cout.flush();
或者您可以像我有时做的那样做另一件事,即在将 用户名 作为输入后使用 getchar();
。此方法不是执行此操作的标准方法,但它有效。有时我们需要与 getchar();
根据您的代码示例,我认为您正试图掩盖用户输入的密码。
为此,您可以在键入时禁用字符回显。
当然它不会打印任何花哨的星号或任何其他符号,而是输入字段将是空的,因为用户不断输入密码。
我在 'here' 中使用的代码示例在下面针对 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<<"\n\tUsername : ";
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();
查看此 'Reading a password from std::cin' 了解更多详细信息和答案。
此过程在控制台中的截图:Image 01 & Image 02