1

I have this c++ program to accept the username and the password(which is masked) and compare them to preset values. If they are same, the program closes, otherwise it loops back to the beginning.
I have had some difficulty with the password input, especially in mimicking a normal input. So far I have managed to put the Enter and Backspace functionality, but I just cant seem to get the arrow keys right.
With the code below, the program does work partly right, and of course, it moves the cursor back two times when the left key is pressed. But in the process, it also replaces the current letter under which it is with the 'alpha' symbol and the previous letter with 'K'. (K and the alpha symbol next to each other seems to be the value which my compiler, dev c++ associates with the left arrow key)
Also, when I remove the extra '\b', the cursor just doesnt move at all, and also replaces the previous letter with 'K'. I don't know what to do now, so I ask you. Thanks in advance!

#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(); 
}  
Thomas W.
  • 460
  • 3
  • 9
Anchith Acharya
  • 369
  • 1
  • 4
  • 16
  • 1
    I think you should first clean your code, because a lot of things doesn't _seem_ to make sense in it. For instance, why executing `while (i!=0) {--i;}` instead of setting `i` to `0`. Also, in the beginning, why do you create an array of size `i+1` just after setting `i` to 0? `char parr[i+1]` declares an array `parr` of size 1. So executing `parr[i]=...` later can lead to memory corruption. Moreover, the comparison between `parr` and password will never be true and you'll never print "Welcome!" – Thomas W. Sep 26 '16 at 09:54
  • @ThomasWilmotte The program executes just fine for me without the whole getasynckeystate line. – Anchith Acharya Sep 26 '16 at 12:12

1 Answers1

1

When you press a special key (like the arrow keys, delete, home, ...) two bytes are sent to your program. In this particular case, when you press the left key, the bytes 0xe0 and 0x4b are sent. The second value correspond to the K character in the ASCII table and the first one depends on the version of the extended ASCII table is used (it can be α but also à).

Your problem is that, in your loop, you start by checking if the left key is pressed. If it's the case, you move back the cursor of your output stream twice to the left (by sending \b to std::cout) and you keep executing your program normally, storing the character you got and the next ones (so 0xe0 and 0x47) in your parr array. Graphically, here is what happens :

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

Actually, as your goal is to print stars instead of the password, when you press the left key, you don't need to move the cursor back in the console. Indeed, the number of characters to print remains the same and, as you always print the same character, printing the next starting at the end of your console line will produce the same result.

However, what you have to do when the left key is pressed, is to move an index to indicate where in your parr array the next entered characters must be inserted.

Let's consider, for example the two following sequences:

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

Whether you pressed the left key or not do not change the output but do change the index.

Thomas W.
  • 460
  • 3
  • 9
  • Thank you very much for that well explained answer! – Anchith Acharya Sep 28 '16 at 02:58
  • Hey @Thomas Wilmote I just checked the output now, and it seems a bit different from what you said. Also,there are a whole lot of observations that I want to share with you. ( I also am mega-impressed with how you explain things) And because I can't tell all of that to you here, I wonder if we could talk someplace else. Like facebook or hangouts. – Anchith Acharya Sep 28 '16 at 10:34
  • 1
    I invite you to come the this room http://chat.stackoverflow.com/rooms/124411/solving-a-problem-with-anchith-acharya to talk about your other issues. I'll stay there and check if you posted new messages from time to time – Thomas W. Sep 28 '16 at 11:58