2016-09-25 85 views
1

我有這個c + +程序接受用戶名和密碼(這是掩碼)並將它們與預設值進行比較。如果它們相同,則程序關閉,否則它將循環回到開頭。
我在輸入密碼時遇到了一些困難,尤其是模仿正常輸入。到目前爲止,我已經設置了輸入和退格功能,但我似乎不能正確地獲取箭頭鍵。
使用下面的代碼,程序的工作部分是正確的,當然,當按下左鍵時,它將光標向後移動兩次。但是在這個過程中,它也會用'alpha'符號和前面的字母替換爲'K'的當前字母。 (K和相鄰的字母符號似乎是我的編譯器,dev C++與左箭頭鍵關聯的值)
另外,當我刪除多餘的'\ b'時,光標根本不會移動,並用'K'取代之前的字母。我現在不知道該怎麼做,所以我問你。提前致謝!在密碼輸入光標移動C++

#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(); 
} 
+1

我認爲你應該先清理你的代碼,因爲很多東西並不適合它。例如,爲什麼執行'while(i!= 0){--i;}'而不是將'i'設置爲'0'。另外,在開始時,爲什麼在將'i'設置爲0之後創建一個大小爲'i + 1'的數組? 'char parr [i + 1]'聲明瞭一個大小爲1的數組'parr'。所以稍後執行'parr [i] = ...'會導致內存損壞。而且,'parr'和密碼之間的比較永遠不會是真的,你永遠不會打印出「Welcome!」 –

+0

@ThomasWilmotte沒有整個getasynckeystate行,該程序執行得很好。 –

回答

1

當你按下一個特殊關鍵(如箭頭鍵,刪除,...),兩個字節被髮送到你的程序。在這種特殊情況下,當您按左鍵時,會發送字節0xe00x4b。第二個值對應於ASCII表中的K字符,第一個值取決於使用的擴展ASCII表的版本(它可以是α,但也可以是à)。

你的問題是,在你的循環中,你首先檢查是否按下了左鍵。如果是這種情況,您將輸出流的光標向左移動兩次(通過發送\bstd::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 

無論您按下左鍵或者不是不改變輸出但不要更改索引。

+0

非常感謝你解釋得很好的答案! –

+0

嘿@Thomas Wilmote我剛剛檢查了輸出,看起來和你說的有點不一樣。此外,還有很多我想與大家分享的觀察結果。 (我對你如何解釋事情也很感動)因爲我不能在這裏告訴你所有這些,我想知道我們是否可以在別的地方說話。像Facebook或環聊。 –

+1

我邀請你來這個房間http://chat.stackoverflow.com/rooms/124411/solving-a-problem-with-anchith-acharya談談你的其他問題。我會留在那裏檢查你是否不時發佈新消息 –