2016-04-12 6 views
5

getchを本質的に標準のC関数としてインクルードできないようにするには?getchは移植できないのはなぜですか?

コンソールインターフェイスにはとても直感的でエレガントです。それがなければ、ユーザーが複数のキーを入力することが許可されているため、1文字を要求することは常に誤解を招きます。

さらに悪いことに、標準入力としても提供されていないコンソール入力を読み込んだ後、標準入力をクリアする必要があることがよくあります。私は自分自身を使用する必要があります!

可能性があり、単純なプログラム:

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

int main(int argc, char **argv) 
{ 
    while (1) { 
     char yes_or_no;   

     printf("is this statement correct? 1 + 1 = 2(Y/N) $ "); 
     yes_or_no = tolower(getch()); 

     switch (yes_or_no) { 
      case 'y': 
       puts("Right!");  
       goto done; 

      case 'n': 
       puts("\nhint> Please just say yes for the sake of this demo..."); 
       break; 

      case 'q': 
       puts("\nExitting."); 
       goto done; 

      case EOF: 
       puts("\nEOF."); 
       goto done; 

      default: 
       printf("\nunknown response '%c'.\n", yes_or_no); 
       break; 
     } 
    } 


done: 
    return 0; 
} 

は次のようになります。

#include <stdio.h> 
#include <stdlib.h> 
#include <ctype.h> 

static inline void flush_stdin() 
{ 
    char ch; 

    do { 
     ch = getchar(); 
    } while ((ch != '\n') && (ch != EOF)); 
} 

int main(int argc, char **argv) 
{ 
    while (1) { 
     char yes_or_no;   

     printf("is this statement correct? 1 + 1 = 2(Y/N) $ "); 
     yes_or_no = tolower(getchar()); 


     switch (yes_or_no) { 
      case 'y': 
       puts("Right!");  
       goto done; 

      case 'n': 
       puts("hint> Please just say yes for the sake of this demo..."); 
       break; 

      case EOF: 
       puts("EOF."); 
       goto done; 

      default: 
       printf("unknown response '%c'.\n", yes_or_no); 
       break; 
     } 
     flush_stdin(); /* remove this to see the difference */   
    } 


done: 
    return 0; 
} 

私はシンプルなポータブルコンソールプログラムを作りたいたびに、私はそのような機能の束を作るに強制的に感じます、そしてまだ私が望むすべてのものを持っていない、getchのように。

もちろん、cursesを使用することもできますが、cursesはコンソール全体を引き継ぎ、通常のユーザーが期待しているものとは異なる動作をします(プログラムをスクロールするだけで、コンソールバッファ)。

私は「なぜ」が悪い質問であるかを知っていますが(常に好むべきことは何ですか)、質問する必要があります。 getchに本質的に移植不可能なものがありますか?デスクトップシステムでサポートできませんか?もし存在しなければ、私は自分自身を書いて、私がサポートしたいすべてのプラットフォームに移植することができ、私は良いです。

デスクトップシステムでサポートされていないgetchがある場合は、それは何ですか?ですから、私は、なぜ「ncurses/conioは標準ではありません」よりも、conioが避けられる理由を理解する良い理由があります。

+1

Btwの場合、 'ch'は' int'型でなければなりません。 – pzaenger

+0

フォーマットされたI/O( 'scanf' /' printf')とフォーマットされていないI/O( 'getchar' /' putchar')を混ぜることを避けようとすれば、それは必要ありません。 – edmz

+0

@pzaenger私は知っていますが、EOFとの比較を避けるためにcharを作成しました。無効にしたのは、1バイトではなく4バイト全体を比較し、追加のキャストを追加するためです。それはよくある間違いです。 -black:その詳細は明白ではなく、ユーザーフレンドリーなライブラリ設計の考慮事項を避けて回避できる微妙なバグがあります。 – Dmitry

答えて

5

C標準には端末またはWindowsという概念はありません。これらのことに関係するものは実装固有のものであり、Cプログラミング言語の一部ではありません。

しかし、端末プログラミングの業界標準があります。 1つはtermiosターミナル・ドライバ・インタフェース、1つはX/Open cursesであり、上位レベルで端末を操作するC関数のライブラリを指定し、3番目はISO 6429であるPOSIX(IEEE 1003.1)の一部であり、ANSIターミナルエスケープシーケンス。

なお、X/Open cursesはgetch()の機能を提供します。 Microsoft Windowsもこれらの標準をサポートしますが、有用な方法ではありません。 conio.hが簡単に起因するコンソールはDOSの対にどのように動作するかの異なるモデルに他のプラットフォーム上で実装することができないDOS特定のヘッダであるとして、あなたは(すなわちconio.h経由)Windows上でgetch()を使用することになり

方法は、しかし、ポータブルではありません他のプラットフォームの端末。

+0

私はターミナルについて完全に忘れました。私はそれを調べる必要があります。私に思い出させてくれてありがとう。 – Dmitry

+0

しかし、実際には、1文字のeacoをオフにして1文字を読み、それを返すためにterminal/windowの概念が必要ですか?標準ioは高いレベルでなければならないので、キー押下を検出する方法がなく、完全な文字列入力のみを操作する必要がありますか?これは物事を移植可能にする唯一の方法ですか? – Dmitry

+0

@Dmitryあなたはそれについて新しい質問を開くことができます(少し言いたいことがあります)。しかし、要するに答えは「はい」です。標準はそれについて気にしません。 §1.2N1570 _ "この国際規格では、入力データがCプログラムで使用するために変換されるメカニズムを指定していません;" _ – edmz