2015-02-24 2 views
0

Я не уверен точно, как фразы, что я пытаюсь спросить; в C++, используя заголовок stdio.h вместо iostream, как бы я сделал это так, чтобы, если клавиша escape нажата в любой момент, программа прекращается? Есть ли что-то, что я мог бы добавить один раз в верхней части программы, или я должен добавить его в каждый цикл/условный отдельно? Ниже мой код (функция сна() только для визуальной нагрузки/расчета эффекта):Обработка невводных нажатий клавиш?

#include <stdio.h> 
#include <math.h> 
#include <windows.h> 

void repeat(); 
void quadratic() 
{ 
    double a, b, c; 
    double ans[2]; 
    printf("-Arrange your equation in the form aX^2+bX+c \n-Enter the value of a: "); 
    scanf("%lf", &a); 
    printf("-Enter the value of b: "); 
    scanf("%lf", &b); 
    printf("-Enter the value of c: "); 
    scanf("%lf", &c); 
    double radical=((b*b)-(4*a*c)); 
    double root=sqrt(radical); 
    double negB=(-1)*b; 
    double denominator=2*a; 
    if(denominator==0) 
    { 
     printf("Calculating"); 
     Sleep(100); 
     printf("."); 
     Sleep(100); 
     printf("."); 
     Sleep(100); 
     printf("."); 
     Sleep(100); 
     printf("\nError: Denominator must be non-zero.\n \n \n"); 

    } 
    else if(radical==0) 
    { 
     ans[0]=negB/denominator; 
     printf("Both roots are equal: both values are X=%lf\n \n \n", ans[0]); 

    } 
    else if(radical<0) 
    { 
     printf("Calculating"); 
     Sleep(100); 
     printf("."); 
     Sleep(100); 
     printf("."); 
     Sleep(100); 
     printf("."); 
     Sleep(100); 
     double r,i; 
     radical*=-1; 
     r=negB/(2*a); 
     i=sqrt(radical)/(2*a); 
     printf("\nBoth roots are imaginary numbers.\n"); 
     printf("Non-real answer(s): X=%lf+%lfi X=%lf-%lfi\n \n \n",r,i,r,i); 

    } 
    else 
    { 
    ans[0]=(negB+root)/denominator; 
    ans[1]=(negB-root)/denominator; 
    printf("Calculating"); 
     Sleep(100); 
     printf("."); 
     Sleep(100); 
     printf("."); 
     Sleep(100); 
     printf("."); 
     Sleep(100); 
     printf("\nX=%lf, X=%lf\n \n", ans[0], ans[1]); 
    } 
    repeat(); 

} 
void repeat() 
{ 
    quadratic(); 
} 
int main(void) 
{ 
    quadratic(); 
    return 0; 
} 
+3

Не лучше ли использовать 'Ctrl + C' вместо' esc'? – ForceBru

+0

Проверьте значение, возвращаемое 'scanf', и выйдите, если оно меньше ожидаемого. –

+0

@AustinMullins: 'scanf' остановится для ввода. – musiphil

ответ

0

Есть ли что-то я мог бы добавить один раз в верхней части программы, или я должен добавить его для каждого цикла/условно индивидуально?

Я думаю, вы можете добавить что-то один раз и использовать его, чтобы легко поймать ключевые события удара во всей программе.

Ниже приведен фрагмент кода, показывающий функцию, которую я использовал для обработки событий штриховки в консольном приложении. Он использует GetAsyncKeyState(). Включен раздел, который показывает, как захватить ключ CTRL, и как вы можете сделать что-то, как только увидите его. (Фрагмент кода показано, показывает, как я захватить ключевую последовательность <ctrl><shift><h> для отображения меню справки для использования этой конкретной подпрограммы

. Примечание: В описании delay_x(float delay) просто обычай, неблокирующая сон, или задержка функция, которая включает в себя вызов в следующем фрагменте Это вызывается из основной цикл программы while(1){...} Выход из программы осуществляется в одном из комбинации клавиш:.. <CTRL><SHIFT><K>

фрагмент кода:

///////////////////////////////////////////////////////////////////////// 
///////////////////////////////////////////////////////////////////////// 
// 
// SetAppState() is called continuously from within delay_x() 
// to capture keystroke combinations as they occur asynchronously 
// with this application, Keystroke combinations are listed below 
// 
// Note: GetAsyncKeyState() can maintian information regarding the 
//  state of a key instantaineously by use the MSB, 
//  and recently by using the LSB. 
//   
//  For this application 
//  only instantaineous information will be kept, minimizing 
//  conflicts with other keyboard shortcut definitions 
//  defined by other applications that may be running 
//  simultaineously. 
// 
///////////////////////////////////////////////////////////////////////// 
///////////////////////////////////////////////////////////////////////// 

void SetAppState(void) 
{ 
    short state=0; 
    short state1=0; 

    state = GetAsyncKeyState(VK_CONTROL); 
    if (0x80000000 & state) //check instantaineous state of key 
    { 
     state = GetAsyncKeyState(VK_SHIFT); 
     if (0x80000000 & state) //check instantaineous state of key 
     { 
      state = GetAsyncKeyState('h'); 
      state1 = GetAsyncKeyState('H'); 
      if ((0x80000000 & state) || 
       (0x80000000 & state1)) 
      { sprintf(gTempBuf, "Usage - keystrokes to access and control the PaAutoStartSlot application:\n\n" 
            "<CTRL><SHIFT> H (H)elp - \n" 
            "<CTRL><SHIFT> V o(V)erride - \n" 
            "<CTRL><SHIFT> S (S)tatus - \n" 
            "<CTRL><SHIFT> K (K)ill - \n" 
            "<CTRL><SHIFT> N (N)o -  \n" 
            "<CTRL><SHIFT> I (I)Inside - \n" 
            "<CTRL><SHIFT> O (O)Outside- \n" 
            "\nSee log file at this location for runtime errors: \n\n%s", LOGFILE); 
       MessagePopup("Usage Menu",gTempBuf); 
      } 

///// ... more code ... 
End of snippet 

Редактировать - ответ на вопросы в комментариях как позвонить GetAsyncKeyState()

Есть много способов, вы могли бы назвать GetAsyncKeyState() в то же время другого материал происходит. Нитки - хороший способ. Вы также можете сделать все это в строю, используя комбинацию while()/switch(){}. Вот очень простой пример того, как вы могли бы сделать это (в псевдокоде)

int gRunning = 1; 
int state = 1; 

int main(void) 
{ 

    //create variables, initialize stuff 
    while(gRunning)//this is your main program loop 
    { 
     delay_x(1.0);//check for keystrokes 
     switch(state) { 
      case 1: 
       //do some stuff here 
       //and experiment with values passed to delay_x(n) 
       delay_x(10000);//check for keystrokes 
       state++; 
       break; 
      case 2: 
       //do some different stuff here 
       delay_x(10000);//check for keystrokes 
       state++; 
       break; 
      ... Add as many cases as you need for your program. 
      case n://last case, set execution flow to top 
       //do some more different stuff here 
       delay_x(10000);//check for keystrokes 
       state = 1;//loop back to top 
       break; 
     } 
    } 
    return 0; 
} 
void delay_x (float delay) 
{ 
    static clock_t time1; 
    static clock_t time2; clock();  

    time1 = clock();  
    time2 = clock();  

    while ((time2 - time1) < delay) 
    {  
     time2 = clock();   
     SetAppState(); //see partial definition in my original answer above. 
    }  
} 

Примечание: Используя этот метод, вы можете иметь много, или как мало, cases, как вам нужно, то Важно поддерживать постоянный поток вызовов до GetAsyncKeyState(). Это делает это по вызову delay_x().

Примечание2: Вот сегмент (добавляются к приведенному выше определению), что приведет к вашей программе выхода:

state = GetAsyncKeyState('k'); 
    state1 = GetAsyncKeyState('K'); 
    if ((0x80000000 & state) || 
     (0x80000000 & state1)) 
    {  
     printf("Kill Program"); 
     gRunning = FALSE; 
    } 
+0

Так что я просто поместил такой код в начало моего кода? Также я немного смущен тем, как правильно использовать синтаксис/какие параметры функции? –

+0

Google «GetAsyncKeyState MSDN» или нажмите ссылку, которую я оставил выше в разделе комментариев вашего вопроса. – ryyker

+0

_So я просто помещаю код наподобие этого в верхней части моего кода? _ Да. Вы определяете функцию, содержащую похожий синтаксис, к тому, что я предоставил для _example_, *** Но для ваших собственных целей *** и *** вызывают это *** из цикла внутри, запущенного, возможно, из вашего 'main() 'функция. – ryyker

0

Терминал используется в STDIO, вероятно, будут линия буферной (вареный) , Если это так, проверка ключа эвакуации через scanf будет не работает.

СМОТРИТЕ ЭТИ URLS:

Capture characters from standard input without waiting for enter to be pressed

scanf not reading input

проклятий или Ncurses обнаружит ключ побег (ASCII символ 27), в зависимости от типа терминала.

Этот код может использоваться в WINDOWS для проверки ключа ESCAPE .

#include <conio.h> 
    #include <ctype.h> 

    int ch; 

    _cputs("Type 'Y' when finished typing keys: "); 
    do 
    { 
     ch = _getch(); 
     ch = toupper(ch); 

      if (ch != 27) { 
      _cputs("CHARACTER: "); 
      _putch(ch); 
      _putch('\r'); // Carriage return 
      _putch('\n'); // Line feed 
     } 

    } while(ch != 27);