214

めったに出てこないので、どうやってこれをしたのか思い出せません。しかし、C または C++ で、改行を待たずに標準入力から文字を読み取る最良の方法は何ですか (Enter キーを押します)。

また、理想的には、入力文字を画面にエコーしません。コンソール画面に影響を与えずにキーストロークをキャプチャしたいだけです。

4

21 に答える 21

119

これは純粋な C++ では移植可能な方法では不可能です。これは、接続されている可能性のある使用端末に大きく依存するためですstdin(通常はライン バッファリングされています)。ただし、そのためにライブラリを使用できます。

  1. conio は Windows コンパイラで利用できます。_getch()Enterキーを待たずに文字を与える機能を使用してください。私は頻繁に Windows を開発するわけではありませんが、クラスメートがそれを組み込んで使用しているのを見たことが<conio.h>あります。conio.hウィキペディアで参照してください。getch()Visual C++ で非推奨と宣言されている がリストされています。

  2. Linux で利用可能な curses。互換性のある curses の実装は、Windows でも利用できます。機能もありgetch()ます。(man getchそのマンページを表示してみてください)。ウィキペディアの呪いを参照してください。

クロス プラットフォームの互換性を目指す場合は、curses を使用することをお勧めします。そうは言っても、ラインバッファリングをオフにするために使用できる機能があると確信しています(「クックモード」ではなく「生モード」と呼ばれていると思います-調べてくださいman stty)。私が間違っていなければ、Curses はそれをポータブルな方法で処理します。

于 2009-01-07T20:08:54.710 に答える
26

同じ問題を解決しようとしているときに、別のフォーラムでこれを見つけました。私が見つけたものから少し修正しました。それはうまくいきます。私は OS X を実行しているので、Microsoft を実行している場合は、正しい system() コマンドを見つけて raw モードとクック モードに切り替える必要があります。

#include <iostream> 
#include <stdio.h>  
using namespace std;  

int main() { 
  // Output prompt 
  cout << "Press any key to continue..." << endl; 

  // Set terminal to raw mode 
  system("stty raw"); 

  // Wait for single character 
  char input = getchar(); 

  // Echo input:
  cout << "--" << input << "--";

  // Reset terminal to normal "cooked" mode 
  system("stty cooked"); 

  // And we're out of here 
  return 0; 
}
于 2009-05-26T19:07:25.320 に答える
13

CONIO.H

必要な機能は次のとおりです。

int getch();
Prototype
    int _getch(void); 
Description
    _getch obtains a character  from stdin. Input is unbuffered, and this
    routine  will  return as  soon as  a character is  available  without 
    waiting for a carriage return. The character is not echoed to stdout.
    _getch bypasses the normal buffering done by getchar and getc. ungetc 
    cannot be used with _getch. 
Synonym
    Function: getch 


int kbhit();
Description
    Checks if a keyboard key has been pressed but not yet read. 
Return Value
    Returns a non-zero value if a key was pressed. Otherwise, returns 0.

libconio http://sourceforge.net/projects/libconio

また

conio.h の Linux C++ 実装 http://sourceforge.net/projects/linux-conioh

于 2009-01-07T21:37:10.243 に答える
12

Windows を使用している場合は、PeekConsoleInputを使用して、入力があるかどうかを検出できます。

HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
DWORD events;
INPUT_RECORD buffer;
PeekConsoleInput( handle, &buffer, 1, &events );

次に、ReadConsoleInput を使用して入力文字を「消費」します。

PeekConsoleInput(handle, &buffer, 1, &events);
if(events > 0)
{
    ReadConsoleInput(handle, &buffer, 1, &events);  
    return buffer.Event.KeyEvent.wVirtualKeyCode;
}
else return 0

正直なところ、これは私が持っている古いコードからのものなので、少しいじる必要があります。

クールなことは、何もプロンプトを表示せずに入力を読み取るため、文字がまったく表示されないことです。

于 2009-01-08T01:10:29.580 に答える
9
#include <conio.h>

if (kbhit() != 0) {
    cout << getch() << endl;
}

これはkbhit()、キーボードが押されているかどうかを確認し、押されてgetch()いる文字を取得するために使用します。

于 2012-07-07T23:44:17.643 に答える
4

ポータブルに最も近いのは、ncursesライブラリを使用して端末を「cbreak モード」にすることです。API は巨大です。あなたが最も望むルーチンは

  • initscrendwin
  • cbreaknocbreak
  • getch

幸運を!

于 2009-01-08T00:44:35.857 に答える
4

Windows を想定して、 ReadConsoleInput関数を見てみましょう。

于 2009-01-07T20:13:06.543 に答える
3

リターンキーを押さずに入力を読み取るループが常に必要でした。これは私のために働いた。

#include<stdio.h>
 main()
 {
   char ch;
    system("stty raw");//seting the terminal in raw mode
    while(1)
     {
     ch=getchar();
      if(ch=='~'){          //terminate or come out of raw mode on "~" pressed
      system("stty cooked");
     //while(1);//you may still run the code 
     exit(0); //or terminate
     }
       printf("you pressed %c\n ",ch);  //write rest code here
      }

    }
于 2015-02-19T19:10:25.750 に答える
2

以下はExpert C Programming: Deep Secretsから抽出されたソリューションで、SVr4 で動作するはずです。sttyioctlを使用します。

#include <sys/filio.h>
int kbhit()
{
 int i;
 ioctl(0, FIONREAD, &i);
 return i; /* return a count of chars available to read */
}
main()
{
 int i = 0;
 intc='';
 system("stty raw -echo");
 printf("enter 'q' to quit \n");
 for (;c!='q';i++) {
    if (kbhit()) {
        c=getchar();
       printf("\n got %c, on iteration %d",c, i);
    }
}
 system("stty cooked echo");
}
于 2009-01-08T09:04:38.123 に答える
1

SDL (Simple DirectMedia Library) を使用して移植可能にできますが、その動作が気に入らないかもしれません。試してみたところ、SDL に新しいビデオ ウィンドウを作成させ (私のプログラムには必要ありませんでしたが)、このウィンドウにほとんどすべてのキーボードとマウスの入力を "グラブ" させる必要がありました (これは私の使用法では問題ありませんでしたが、他の状況では煩わしい、または機能しない)。完全な移植性が必須でない限り、やり過ぎで価値がないと思います。それ以外の場合は、他の提案された解決策のいずれかを試してください。

ちなみに、これに興味がある場合は、キーを押すイベントとリリースするイベントが別々に提供されます。

于 2012-08-28T22:38:51.747 に答える
0

WINDOWSで私はそうします:

#include <Windows.h>
int main()
{
    system("PAUSE>NUL");
    if (GetKeyState(0x41/*(the 'A' key, choosen e.g.)*/) & (0xff80/*That stands for "Default state / Key Down"*/)) {
        //whatever I want to do after 'A' is pressed
    }
}

それぞれに独自の 16 進値を持つキーのリストを次に示します: https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes

于 2022-01-13T16:57:54.537 に答える