C++ how do I terminate my programm using ESC button

11,173

Here are solution for Windows

First solution:

Esc will not be handled when user starts to type till pressing enter. While idle Esc will be handled

#include <Windows.h>
#include <iostream>
#include <conio.h>
#include <vector>
int main(int argc, char **argv)
{
    int value=0;
    std::vector<int> mylist; 
    do
    {   
        //check if any input.
        if (_kbhit()){
            //probable user started to type 
            //block to read till the user press Enter. If you want to handle Esc here .
            //then you should manually do input reading . I will write that solution later
            std::cin>>value; 
            //if success
            if(std::cin.good()){ 
                mylist.push_back(value); 
            }else{
                //firstly, clear error flag 
                std::cin.clear();
                //ignore 
                std::cin.ignore(10000,'\n');

            }

            //print  list
            std::cout<<"new list: { " ;
            for(int i=0;i< mylist.size();i++){
                std::cout<<mylist[i]<<'\t';
            }
            std::cout<<" }"<<std::endl;
        }

        //check if Esc Pressed
    }while(GetAsyncKeyState(VK_ESCAPE)==0);

    return 0;
}

Second Solution:

Esc will be handled always in another thread. Immediate exit can be undesirable on some cases

DWORD WINAPI CheckEscape( LPVOID lpParam ) {
        while(GetAsyncKeyState(VK_ESCAPE)==0){
            //sleep 
            Sleep(10);
        }
        exit(0);

}



int main(int argc, char **argv)
{
    int value=0;
    std::vector<int> mylist; 
    //create thread for handling ESC key
    CreateThread( NULL, 0, CheckEscape,NULL  , 0, NULL);

    //loop infinitely
    while(true)
    {    
            std::cin>>value; 
            //if success
            if(std::cin.good()){ 
                mylist.push_back(value); 
            }else{
                //firstly, clear error flag 
                std::cin.clear();
                //ignore 
                std::cin.ignore(10000,'\n');

            }

            //print  list
            std::cout<<"new list: { " ;
            for(int i=0;i< mylist.size();i++){
                std::cout<<mylist[i]<<'\t';
            }
            std::cout<<" }"<<std::endl;
        }  
    return 0;
}

Third Solution and the Best one .Do everything manually

Handling keypress manually. Exit will be called when Esc is Pressed. You can change it to handle more right way

bool keypress( char &key){
    INPUT_RECORD IR[1];
    DWORD read;
    static HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
    while(PeekConsoleInputA(h,IR,1,&read)){
        if(read!=0){
            //check if it was Key Event
            if(IR[0].EventType==KEY_EVENT){
                key=IR[0].Event.KeyEvent.uChar.AsciiChar; 
                ReadConsoleInputA(h,IR,1,&read);
                FlushConsoleInputBuffer(h);
                return true;
            }
            if(ReadConsoleInputA(h,IR,1,&read)){
                continue; 
            }
        }else{
            return false;
        }
    }
}

//getnumber
int cinnumb( ){
    char buffer[32];
    buffer[0]='\0';
    int count=0;
    DWORD key=-1;
    while(true){

        Sleep(100);
        do{
            //here I make it nonblockin keypress
            //but actually we do not need it 
            //we can use blocking ReadConsoleInputA(h,IR,1,&read);
            //this way we not even need sleep() and 
            //our keypress function will be simple
            //anyway im posting nonblocking one

            //nonblocking keypress
            char key=0;
            bool isOk=keypress(key );

            if(!isOk ){ 
                Sleep(20);
                continue;
            }

            if(key>='0' && key<='9'){
                buffer[count]=key; 
                std::cout<<key;
                ++count;
                if( count==31)break;

            }

            // check Enter key and  enough symbol
            if(  key==13 && count>0  ){  
                std::cout<<std::endl;
                break;
            }

            //for windows 

            //check if Esc pressed
            if(key==27) exit(0); 


        }while(true);

        buffer[count]='\0';

        int value=atoi(buffer);
        return value;
    }
}
int main(int argc, _TCHAR* argv[])
{
    std::vector<int> mylist; 
    int value; 
    char buffer[100];
    //infinite loop
    while(true)
    {   
        //get number 
        value=cinnumb(); 
        mylist.push_back(value);
         //print  list
        std::cout<<"new list: { " ;
        for(int i=0;i< mylist.size();i++){
                std::cout<<mylist[i]<<'\t';
            }
        std::cout<<" }"<<std::endl;
        //sleep a little
        Sleep(10); 
    } ;


    return 0;

}
Share:
11,173
Constantine
Author by

Constantine

Updated on June 04, 2022

Comments

  • Constantine
    Constantine almost 2 years

    Here is my main function i use visual studio 2012 express and the code works fine. My question is how will i terminate this loop when the user Presses the ESC button instead of -1. Although i would prefer a solution that works both in unix and windows, if it is not possible i am most interested in it working for windows.

    int _tmain(int argc, _TCHAR* argv[])
    {
    list mylist;
    
    int value;
    cout<<"Give the numbers you want to insert to the list, press -1 to stop\n";
    do
    {
        cin>>value;
        mylist.insertf(value);
        mylist.sort_list();
        mylist.print();
    }while(value!=-1);
    
    
    
    
    }
    
    • chris
      chris almost 11 years
      Nothing in standard C++ will do that.
    • Constantine
      Constantine almost 11 years
      what do you mean by standard. sorry i am mostly new in C++
    • chris
      chris almost 11 years
      Anything you can do by only using standard C++ libraries and language features with no third party ones. Basically the ones that should ship with every implementation.
    • Constantine
      Constantine almost 11 years
      do you know how it can happen with a third party library?
    • qwr
      qwr almost 11 years
      @Kostas check i posted working solution
  • Constantine
    Constantine almost 11 years
    so how would it be implemented in my code. cin.get() will read a character my insertf function needs an int and above all i think cin.get cannot read the esc button
  • qwr
    qwr almost 11 years
    @Kostas mm just checked cin.get() as not giving escape character . so you have to do with winapi
  • Constantine
    Constantine almost 11 years
    just edited the original question so you can see what i understand from what you said
  • Constantine
    Constantine almost 11 years
    edited GetAsyncKeyState(27)==0 to GetAsyncKeyState(VK_ESCAPE)==0 and it now seems to work THANK YOU
  • Constantine
    Constantine almost 11 years
    although on the first run i have to enter a list value before it closes any suggestion on how to solve that?
  • Constantine
    Constantine almost 11 years
    ok first i will have to understand how that works and if i don't solve it i will ask you, thanks again!
  • qwr
    qwr almost 11 years
    @Kostas posted you another two solutions check
  • chris
    chris almost 11 years
    That should be GetAsyncKeyState(vk) & 0x8000