単一の文字のみを読み取るためにgetchar()でEnterキーを押さないようにするにはどうすればよいですか?


80

次のコードでは:

Enter入力したすべての文字を印刷するにはを押すgetchar必要がありますが、これはやりたくありません。文字を押して、を押さずに、紹介した文字をすぐに繰り返し表示しEnterます。たとえば、文字「a」を押すと、その横に別の「a」が表示されます。

しかし、「a」を押しても何も起こらず、他の文字を書くことができ、コピーは私が押したときにのみ表示されますEnter

これどうやってするの?

cc -o example example.cコンパイルにはUbuntuでコマンドを使用しています。


5
これは、OSと端末が入力を処理する方法に大きく依存します。動作環境を指定すると、おそらくより良い答えが得られます。
goldPseudo 2009年

cplusplus.com/forum/articles/19975で提供される回答は、WinAPIを使用するWindowsで機能します。

回答:


72

Linuxシステムでは、sttyコマンドを使用して端末の動作を変更できます。デフォルトでは、端末はEnterが押されるまですべての情報をバッファリングしてから、Cプログラムに送信します。

プログラム自体の中から動作を変更するための、すばやく、汚く、特に移植性のない例:

これは実際には最適ではないことに注意してください。これはstty cooked、元の端末設定が何であったかを確認するのではなく、プログラムの終了時に必要な動作であると想定しているためです。また、rawモードではすべての特別な処理がスキップされるため、多くのキーシーケンス(CTRL-CCTRL-Dなど))は、プログラムで明示的に処理しないと、実際には期待どおりに機能しません。

man stty達成したい内容に正確に応じて、端末の動作をより細かく制御できます。


使用するのsystemは悪い考えです。
Sapphire_Brick

生が多すぎる.... ENTERを待たずに済む解決策を探していました。このソリューションは、すべての入力端子機能にブレーキをかけます。
ABC

93

これはOSによって異なります。UNIXライクな環境では、ICANONフラグがデフォルトで有効になっているため、入力は次の'\n'またはまでバッファリングされますEOF。カノニカルモードを無効にすると、すぐにキャラクターを取得できます。これは他のプラットフォームでも可能ですが、単純なクロスプラットフォームソリューションはありません。

編集:Ubuntuを使用するように指定されたようです。昨日似たようなものを投稿しましたが、これにより端末の多くのデフォルトの動作が無効になることに注意してください。

すべての文字が2回表示されることに気付くでしょう。これは、入力がすぐに端末にエコーバックされ、プログラムがそれを元に戻すputchar()ためです。入力と出力の関連付けを解除する場合は、ECHOフラグもオフにする必要があります。これを行うには、適切な行を次のように変更するだけです。


9
+1 tbhですが、これはおそらく元のポスターが快適なコードのレベルではありません;)
Andomar 2009年

2
すごい!それが私が探していたものです!
–DenilsonSáMaia 2010

詳細なコメントと一緒に助けてくれてありがとう、それは私の問題を解決しました。
kaminsknator 2016

非常に基本的なものを実現するのが非常に難しく、移植性がないことは信じられないことです。
Pedro 7720

12

getchar()は標準関数であり、多くのプラットフォームでは、Enterキーを押して入力を取得する必要があります。これは、プラットフォームがそのキーが押されるまで入力をバッファリングするためです。多くのコンパイラ/プラットフォームは、ENTERを気にしない非標準のgetch()をサポートしています(プラットフォームのバッファリングをバイパスし、ENTERを別のキーのように扱います)。


1
+1正解、getchar()
Enter

32
getchar()ENTERは気にせず、stdinを介して来るものはすべて処理するだけです。ラインバッファリングは、OS /端末で定義された動作になる傾向があります。
goldPseudo 2009年

1
@goldPseudo:本当ですが、ほとんどすべてのプラットフォームが入力をバッファリングするため、これはほとんどの実際的なケースで見られる動作です。getch()は、サポートされている場合、バッファリングを管理または無視します。一部の古いDOS実装は、ハードウェアと直接対話するためにOSバッファリングをバイパスしたことを知っています。他の実装では、同じ動作を得るためにstdinをフラッシュする場合があります。
Eric J.

10
それでも、getchar()「Enterキーを押す必要がある」ということではなく、環境です。
ベンジXVI

1
非常に簡潔で理解しやすい。他のトップクラスの回答は、圧倒的な不要な技術の詳細について投げかけるだけです。
mzoz 2017年

6

I / Oはオペレーティングシステムの機能です。多くの場合、オペレーティングシステムは、Enterキーが押されるまで、入力された文字をプログラムに渡しません。これにより、ユーザーは入力をプログラムに送信する前に変更(バックスペースや再入力など)することができます。ほとんどの目的で、これはうまく機能し、ユーザーに一貫したインターフェイスを提供し、プログラムがこれに対処する必要をなくします。場合によっては、キーが押されたときにプログラムがキーから文字を取得することが望ましいことがあります。

Cライブラリ自体はファイルを処理し、データが入力ファイルにどのように入るかには関係ありません。したがって、キーが押されたときにキーを取得する方法は言語自体にはありません。代わりに、これはプラットフォーム固有です。OSまたはコンパイラを指定していないため、検索できません。

また、標準出力は通常、効率のためにバッファリングされます。これはCライブラリによって行われるためfflush(stdout);、各文字が書き込まれた後に行うCソリューションがあります。その後、文字がすぐに表示されるかどうかはオペレーティングシステム次第ですが、私が精通しているすべてのOSが出力をすぐに表示するので、通常は問題ありません。


6

ルーカスの答えが好きですが、少し詳しく説明したいと思います。termios.h名前付きには組み込み関数がcfmakeraw()あり、manは次のように説明しています。

これは基本的にLucasが提案したものと同じであり、さらに、manページで設定された正確なフラグを確認できます:termios(3)

使用事例


これcfmakeraw()POSIXのtermios.h移植性がなく、標準ではない拡張機能であり、必ずしも利用できるとは限らないことに注意してください。
アンドリューヘンレ

4

Unix派生物(Ubuntu)で作業しているので、これを行う1つの方法があります-推奨されませんが、(コマンドを正確に入力できる限り)機能します:

あなたがそれに飽きたら、割り込みを使ってプログラムを止めてください。

  • 'echo'行は、現在の端末設定を、それらを復元するシェルスクリプトとして保存します。
  • 'stty'行は、ほとんどの特別な処理をオフにします( Control-Dたとえば、効果はありません)、文字が使用可能になるとすぐにプログラムに送信します。これ以上入力を編集できないことを意味します。
  • 'sh'行は、元の端末設定を復元します。

'sttysane'が目的に十分正確に設定を復元するかどうかを節約できます。'-g'の形式は 'stty'のバージョン間で移植できません(したがって、Solaris 10で生成されたものはLinuxで機能しません、またはその逆です)が、この概念はどこでも機能します。'stty sane'オプションは、普遍的に利用できるわけではありません、AFAIK(ただし、Linux上にあります)。


2

'ncurses'ライブラリを含めて、のgetch()代わりに使用することができますgetchar()


1

はい、Windowsでもこれを行うことができます。conio.hライブラリを使用して、以下のコードを示します。


6
質問がでタグ付けされているC、いないC ++
Spikatrix

@CoolGuyだから何?誰かがまったく同じ質問を開いたが、タグをcからc ++に変更した場合、なぜそれが誰かを助けるのでしょうか?
Andreas Haferburg 2018年

@AndreasHaferburgここではC ++の回答がないため、特に記述が不十分な回答はないので、ウィンクウィンク
Sapphire_Brick

1

この問題/質問は、現在取り組んでいる課題で出てきました。また、取得する入力によっても異なります。使ってます

プログラムの実行中に入力を取得するため、コマンドに関連付けられたファイルストリームである必要があります。

私がテスト/ターゲットする必要があるubuntuマシンでは、それは単なる

または

次のように、-fileフラグとコマンドへのパスを追加する必要がありました。

今ではすべてが共食いです。


2
このソリューションはOSに依存することに注意してください。
Ottavio Campana 2012年

0

このコードは私のために働いた。注意:ほとんどのコンパイラー(私はGCCを使用しています)がサポートしている場合でも、これは標準ライブラリーの一部ではありません。

このコードは、最初のキー押下を検出します。


0

「で押すのを避ける方法Entergetchar()

まず第一に、端子入力は通常、ラインまたは完全にバッファリングされています。これは、オペレーティングシステムが端末からの実際の入力をバッファに保存することを意味します。通常、このバッファは、fe\nがで通知/提供されたときにプログラムにフラッシュされstdinます。これはプレスによって作られたfeEnterです。

getchar()チェーンの終わりにあります。実際にバッファリングプロセスに影響を与えることはできません。


どうすればこれができますか?

getchar()最初の場所で、他の回答で説明したように明示的に端末の動作を変更するために、特定のシステムコールを使用したい場合はドント。

残念ながら、標準のライブラリ関数はなく、1文字の入力でバッファをフラッシュするポータブルな方法はありません。ただし、実装ベースの非ポータブルソリューションがあります。


Windows / MS-DOSには、getch()とがありますgetche()機能があります。conio.hヘッダーファイルに、必要なことを正確に実行します。改行がバッファをフラッシュするのを待たずに、1文字を読み取ります。

主な違いgetch()とはgetche()つまりgetch()ながら、コンソールではないすぐに出力実際の入力文字を行いgetche()ません。追加の"e"スタンドはエコーを表します

例:


Linuxでは、直接文字処理および出力を得るための方法は、使用することですcbreak()し、echo()オプションとgetch()し、refresh()は、ncurses-libraryルーチンです。

と呼ばれる標準画面をで初期化し、initscr()で閉じる必要があることに注意してください。endwin()ルーチン。

例:


注:-lncursesリンカーがncurses-libraryを検索して見つけることができるように、オプションを指定してコンパイラーを呼び出す必要があります。


-1

デフォルトでは、Cライブラリはリターンが表示されるまで出力をバッファリングします。結果をすぐに印刷するには、次を使用しますfflush


2
ただし、出力は問題の一部です。質問者は、キーが押されたときにプログラムにキーを読み取らせ、画面にすぐに印刷させたいと考えています。これは、入力と出力の両方の問題です。
David Thornley

つまり、fflushは出力のみをフラッシュしますが、キーが押された後もgetcharは返されません(キーはバッファリングされます)。
NickSoft 2012
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.