我有这个c ++程序接受用户名和密码(被屏蔽)并将它们与预设值进行比较。如果它们相同,程序将关闭,否则它将循环回到开头
我在密码输入方面遇到了一些困难,特别是在模仿正常输入时。到目前为止,我已设法放入Enter和Backspace功能,但我似乎无法正确使用箭头键
使用下面的代码,程序部分正常工作,当然,当按下左键时,它会将光标向后移动两次。但是在这个过程中,它还用'alpha'符号和前一个带'K'的字母替换当前的字母。 (K和彼此相邻的alpha符号似乎是我的编译器,dev c ++与左箭头键关联的值)
此外,当我删除额外的'\ b'时,光标根本不移动,并且还用'K'替换前一个字母。我现在不知道该怎么办,所以我问你。提前谢谢!
#include <stdlib.h>
#include <conio.h>
#include <iostream.h>
#include <windows.h>
using namespace std;
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)
{
ch=getch();
if (ch=='\r') break;
if (GetAsyncKeyState(VK_LEFT)) cout<<'\b'<<'\b';
if (ch=='\b')
{
cout<<'\b';
while (i!=0) {--i;}
ch='\0';
parr[i]='\0';
cout<<' '<<'\b';
continue;
}
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();
}
答案 0 :(得分:1)
当您按特殊键(如箭头键,删除,主页,...)时,会向您发送两个字节程序。在这种特殊情况下,当您按左键时,会发送字节0xe0
和0x4b
。第二个值对应于ASCII表中的K
字符,第一个值取决于使用的扩展ASCII表的版本(可以是α
,还可以是à
)。< / p>
问题在于,在循环中,首先检查左键是否被按下。如果是这种情况,则将输出流的光标向后移动两次(通过将\b
发送到std::cout
)并继续正常执行程序,存储您获得的字符和下一个字符(0xe0
和0x47
数组中的parr
和Action BYTE SENT parr Comment
PRESS a 0x61 > a
PRESS b 0x62 > ab
PRESS LEFT 0xe0 0x4b > abα The first update of parr (0xe0)
> αbαK You enter directly in the loop
because there is another byte (0x4b)
waiting in the input stream
PRESS c 0x63 > αbαKc
}。从图形上看,这是发生的事情:
parr
实际上,由于您的目标是打印星形而不是密码,因此当您按左键时,您无需将光标移回控制台。实际上,要打印的字符数保持不变,并且由于您始终打印相同的字符,因此从控制台行的末尾开始打印下一个字符将产生相同的结果。
但是,按下左键时必须执行的操作是移动索引以指示Pressing Will display parr Pointer to the position
where to insert the new char
0
a * a 1
b ** b 2
c *** abc 3
0
a * a 1
LEFT * a 0
b ** ba 1
LEFT ** ba 0
c *** cba 1
数组中必须插入下一个输入字符的位置。
让我们考虑一下,例如以下两个序列:
{{1}}
是否按下左键不改变输出但更改索引。