密码输入中的光标移动c++\

Cursor movement in password input c++\

我有这个 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='[=10=]';
        parr[i]='[=10=]';
        cout<<' '<<'\b';
        continue;
      }

      parr[i]=ch;
      ch='*';
      cout<<ch;
      ++i;
    }

    parr[i]='[=10=]';
    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(); 
}  

当您按下 特殊 键(如箭头键、删除主页 , ...) 两个字节被发送到您的程序。在这种特殊情况下,当您按下左键时,将发送字节 0xe00x4b。第二个值对应于 ASCII table 中的 K 字符,第一个取决于扩展 ASCII 的版本 table 使用(它可以是 α 但也à).

你的问题是,在你的循环中,你首先检查是否按下了左键。如果是这种情况,您将输出流的光标向左移两次(通过将 \b 发送到 std::cout)并继续正常执行您的程序,存储您获得的字符和下一个字符(所以 0xe00x47)在你的 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

无论是否按下左键,都不会改变输出,但会改变索引。