2009-09-19 2 views
63

Я пытаюсь написать программу на C++, в которой пользователь вводит любой символ с клавиатуры и должен перейти к следующей строке кода.Как имитировать «Нажмите любую клавишу, чтобы продолжить?»

Вот мой код:

char c; 

cin>>c; 

cout<<"Something"<<endl; 

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

ИЛИ

Если я использую этот

cin.get() or cin.get(c) 

это перейти к следующей строке инструкции при нажатии Enter.

Но я хотел, чтобы он переместился на следующую строку на любой клавише, нажатой на клавиатуре, как это можно сделать?

+1

Какой ОС вы используете? – Lucas

+0

Насколько я знаю, проблема в том, что ваша оболочка ждет вас, чтобы нажать ENTER или EOF, а затем позволит вашей программе заботиться о том, что находится в буфере, или что-то вроде этого. Может быть, кто-нибудь, обладающий некоторыми знаниями, может дать реальное объяснение. Но я думаю, что это не так просто, как кажется на первый взгляд. – Lucas

+5

Самым простым способом справиться с этим и единственным переносным способом является изменение приглашения от «Нажмите любую клавишу, чтобы продолжить» до «Нажмите клавишу« Ввод », чтобы продолжить». –

ответ

6

Для достижения этой функциональности вы можете использовать библиотеку ncurses, которая была реализована как в Windows, так и в Linux (и MacOS, насколько я знаю).

+0

Ну, это своего рода назначение, в котором я не могу использовать какие-либо внешние библиотеки и т. Д., Поэтому просто оставайтесь в «контексте главы» lox. – itsaboutcode

+2

Тогда единственный вариант - реализовать необходимые функции для каждой ОС, которую вы планируете поддерживать. –

+1

ncurses - это более или менее клиент VT200. Немного переборщик для простого чтения из TTY. – greyfade

49

Если вы работаете в Windows, вы можете использовать kbhit(), который является частью библиотеки времени выполнения Microsoft. Если вы на Linux, вы можете реализовать kbhit таким образом (source):

#include <stdio.h> 
#include <termios.h> 
#include <unistd.h> 
#include <fcntl.h> 

int kbhit(void) 
{ 
    struct termios oldt, newt; 
    int ch; 
    int oldf; 

    tcgetattr(STDIN_FILENO, &oldt); 
    newt = oldt; 
    newt.c_lflag &= ~(ICANON | ECHO); 
    tcsetattr(STDIN_FILENO, TCSANOW, &newt); 
    oldf = fcntl(STDIN_FILENO, F_GETFL, 0); 
    fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); 

    ch = getchar(); 

    tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 
    fcntl(STDIN_FILENO, F_SETFL, oldf); 

    if(ch != EOF) 
    { 
    ungetc(ch, stdin); 
    return 1; 
    } 

    return 0; 
} 

Update: выше функция работает на OS X (по крайней мере, на OS X 10.5.8 - Leopard, так что я бы ожидайте, что он будет работать над более поздними версиями OS X). Это gist может быть сохранен как kbhit.c и скомпилирован как на Linux и OS X с

gcc -o kbhit kbhit.c 

При запуске с

./kbhit 

Это побуждает вас нажатие клавиши, и выходит, когда вы нажмете клавишу (не ограничено для ввода или печати).

@Johnsyweb - пожалуйста, уточните, что вы подразумеваете под «подробным каноническим ответом» и «всеми проблемами». Кроме того, перекрестная платформа: с этой реализацией kbhit() вы можете иметь одинаковую функциональность в программе на C++ в Linux/Unix/OS X/Windows - на каких других платформах вы можете ссылаться?

Дальнейшее обновление для @Johnsyweb: Приложения на C++ не живут в герметично закрытой среде C++. Большой причиной успеха C++ является совместимость с C. Все основные платформы реализованы с помощью C-интерфейсов (даже если внутренняя реализация использует C++), поэтому ваши разговоры о «наследии» кажутся неуместными. Кроме того, поскольку мы говорим об одной функции, зачем вам C++ для этого («C с классами»)? Как я уже сказал, вы можете написать на C++ и легко получить доступ к этой функции, и пользователям вашего приложения вряд ли понравится , как вы его внедрили.

+0

Жаль, что нет стандартного способа управления консолью, вам всегда нужно использовать некоторую магию ОС – Vargas

+0

True. Консоли были де-подчеркнуты с момента появления графических интерфейсов. –

+0

«Этот вопрос широко применим для большой аудитории. Для решения всех проблем необходим подробный канонический ответ». это формулировка StackOverflow. Я хотел подчеркнуть ** C++ ** и не полагаться на устаревшие заголовки C и вызовы функций, так как вопрос помечен C++. – Johnsyweb

1

Вы можете использовать рутину getchar.

Из приведенной выше ссылке:

/* getchar example : typewriter */ 
#include <stdio.h> 

int main() 
{ 
    char c; 
    puts ("Enter text. Include a dot ('.') in a sentence to exit:"); 
    do { 
    c=getchar(); 
    putchar (c); 
    } while (c != '.'); 
    return 0; 
} 
+3

Я не думаю, что это то, о чем просил OP, если я его правильно понимаю. Вам еще нужно нажать ENTER, чтобы заполнить буфер, прежде чем getchar() сможет его прочитать. – Lucas

4

Я смотрел на то, что вы пытаетесь достичь, потому что я помню, что я хотел сделать то же самое. Вдохновленный Vinay Я написал что-то, что работает для меня, и я понимаю. Но я не эксперт, поэтому, пожалуйста, будьте осторожны.

Я не знаю, как Винай знает, что вы используете Mac OS X. Но он должен работать как это с большинством UNIX-подобных ОС. Полезно в качестве ресурса opengroup.org

Перед использованием функции обязательно очистите буфер.

#include <stdio.h> 
#include <termios.h>  //termios, TCSANOW, ECHO, ICANON 
#include <unistd.h>  //STDIN_FILENO 


void pressKey() 
{ 
    //the struct termios stores all kinds of flags which can manipulate the I/O Interface 
    //I have an old one to save the old settings and a new 
    static struct termios oldt, newt; 
    printf("Press key to continue....\n"); 

    //tcgetattr gets the parameters of the current terminal 
    //STDIN_FILENO will tell tcgetattr that it should write the settings 
    // of stdin to oldt 
    tcgetattr(STDIN_FILENO, &oldt); 
    //now the settings will be copied 
    newt = oldt; 

    //two of the c_lflag will be turned off 
    //ECHO which is responsible for displaying the input of the user in the terminal 
    //ICANON is the essential one! Normally this takes care that one line at a time will be processed 
    //that means it will return if it sees a "\n" or an EOF or an EOL 
    newt.c_lflag &= ~(ICANON | ECHO);  

    //Those new settings will be set to STDIN 
    //TCSANOW tells tcsetattr to change attributes immediately. 
    tcsetattr(STDIN_FILENO, TCSANOW, &newt); 

    //now the char wil be requested 
    getchar(); 

    //the old settings will be written back to STDIN 
    tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 

} 


int main(void) 
{ 
    pressKey(); 
    printf("END\n"); 
    return 0; 
} 

O_NONBLOCK, кажется, также является важным флаг, но это ничего не изменило для меня.

Я ценю, если люди с более глубокими знаниями прокомментируют это и дадут совет.

+0

O_NONBLOCK должен быть установлен, потому что без него getchar() (который вызывает read()) блокирует ожидание ввода. Решение kbhit() сообщает, если вы нажали клавишу, не дожидаясь; вы можете использовать его в цикле ожидания или для любых других целей, поэтому это более общее решение. Решение без O_NONBLOCK будет ждать нажатия клавиши - ОК для этого вопроса, но в меньшей степени полезен. –

47

В Windows:

system("pause"); 

и на Mac и Linux:

system("read"); 

Выведет "Нажмите любую клавишу для продолжения ..." и, очевидно, ждать какой-либо ключ, который будет нажата. Надеюсь, что вы имели в виду

+0

Я думаю, проблема в том, что он не использует окна. – Lucas

+2

'system' вызывает внешнюю программу. Вам не нужно вызывать внешнюю программу для ожидания любой клавиши! Это похоже на призыв другого человека включить компьютер, когда вы сидите перед ним - это медленное решение. – GingerPlusPlus

+7

Правда, но это только одна линия! Иногда просто не стоит прилагать усилий, чтобы сэкономить компьютер на некоторых циклах ... –

0

Также вы можете использовать getch() из conio.h. Так же, как это:

...includes, defines etc 
void main() 
{ 
//operator 
getch(); //now this function is waiting for any key press. When you have pressed its  just  //finish and next line of code will be called 
} 

Таким образом, потому что UNIX не имеет conio.h, мы можем моделировать Геч() с помощью этого кода (но этот код уже написанный Vinary, мой провал):

#include <stdio.h> 
#include <termios.h> 
#include <unistd.h> 

int mygetch() { 
    struct termios oldt, 
      newt; 
    int   ch; 
    tcgetattr(STDIN_FILENO, &oldt); 
    newt = oldt; 
    newt.c_lflag &= ~(ICANON | ECHO); 
    tcsetattr(STDIN_FILENO, TCSANOW, &newt); 
    ch = getchar(); 
    tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 
    return ch; 
} 
4

Вы можете использовать Microsoft специфическую функцию _getch:

#include <iostream> 
#include <conio.h> 
// ... 
// ... 
// ... 
cout << "Press any key to continue..." << endl; 
_getch(); 
cout << "Something" << endl; 
3

Это работает на платформе Windows: Он использует микропроцессорные регистры непосредственно и может быть использована для проверки нажатия клавиши или MouseButton

#include<stdio.h> 
    #include<conio.h> 
    #include<dos.h> 
    void main() 
    { 
    clrscr(); 
    union REGS in,out; 
    in.h.ah=0x00; 
    printf("Press any key : "); 

    int86(0x16,&in,&out); 
    printf("Ascii : %d\n",out.h.al); 
    char ch = out.h.al; 
    printf("Charcter Pressed : %c",&ch); 
    printf("Scan code : %d",out.h.ah); 
    getch(); 
    } 
7

Там не полностью портативное решения.

Вопрос 19.1 из comp.lang.c FAQ охватывает это в некоторой степени, с решениями для Windows, Unix-подобных систем и даже MS-DOS и VMS.

Быстрая и неполное резюме:

  • Вы можете использовать curses библиотеку; звоните cbreak(), а затем getch() (не путать с функцией getch(), специфичной для Windows). Обратите внимание, что curses обычно берет на себя управление терминалом, поэтому это, вероятно, будет излишним.
  • Возможно, вы используете ioctl() для управления настройками терминала.
  • В POSIX-совместимых системах tcgetattr() и tcsetattr() могут быть лучшим решением.
  • В Unix вы можете использовать system() для вызова команды stty.
  • На MS-DOS вы можете использовать getch() или getche().
  • На VMS (теперь называемом OpenVMS) подпрограммы управления экранами (SMG$) могут сделать трюк.

Все эти решения C должны работать одинаково хорошо в C++; Я не знаю ни одного специального решения на C++.

+0

Все эти многоплатформенные решения могут делать с кем-то, кто пишет функцию который реализован для правильной работы в зависимости от вашей платформы с большим количеством предварительных процессоров, чтобы определить, что такое платформа. – CashCow

-4

Просто используйте команду system("pause");.

Все остальные ответы более сложны.

+0

Все остальные ответы также используют _good programming practice_ –

4

Это очень просто. Я сделал программу, и она отлично работает .. Вот программа.

#include<iostream.h> 
#include<conio.h> 

void check() 
{ 
    char chk; int j; 
    cout<<"\n\nPress any key to continue..."; 
    chk=getch(); 
    j=chk; 
    for(int i=1;i<=256;i++) 
     if(i==j) break; 
    clrscr(); 
} 

void main() 
{ 
    clrscr(); 
    check(); 
    cout<<"\n\nSee, Its Working....Have a Good day"; 
    getch(); 
} 
+0

Эта очень простая программа. Его очень легко понять. – BoldX

+0

Пожалуйста, объясните, как 'getch()' отличается от 'cin.get' или' cin >> ', может быть, некоторая ссылка на документацию – user2622016

2

Если вы используете Visual Studio 2012 или старше, используйте "Геч()" функции, если вы используете Visual Studio 2013 или более новую версию, используйте "_getch()". Вам нужно будет использовать «#include < conio.h>». Пример:

#include "stdafx" 
#include <iostream> 
#include <conio.h> 

int main() 
{ 
    std::cout << "Press any key to continue. . .\n" 
    _getch() //Or "getch()" 
} 
-2

Если вы сейчас посмотрите функцию kbhit() на MSDN, она говорит, что функция устарела. Вместо этого используйте _kbhit().

#include <conio.h> 
int main() 
{ 
    _kbhit(); 
    return 0; 
} 
-1

Вы можете использовать переменную Scanner и использовать метод HasNext(). Затем сломайте его и выйдите с помощью функции exit();

import java.util.Scanner; 

    public class exit_onClick { 
     public static int exit() 
     { 
      return 0; 
     } 
     public static void main(String[] args) { 
      Scanner scan = new Scanner(System.in); 
      System.out.println("Press Any Key to EXIT...."); 
      int c=0; 
      while(scan.hasNext()) 
      { 
       c++; 
       if(c==1) 
        break; 
      } 
      exit(); 
     } 

    } 
0
#include <iostream> 
using namespace std; 

int main() { 
    bool boolean; 
    boolean = true; 

    if (boolean == true) { 

     cout << "press any key to continue"; 
     cin >> boolean; 

    } 
    return 0; 
} 
Смежные вопросы