Search code examples
c++console-applicationkeypressexitterminate

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


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);




}

Solution

  • 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;
    
    }