WindowsというかDOSの時代から、マイクロソフトのOSには非標準の機能をC言語の中に入れ込んでいました。つまりC言語にはリアルタイムキー処理関数は無いのです。
とはいうものの、そんな時代の遺物というか、C言語の本の多くに、getch() や kbhit() なる関数が出てきます。これらの機能は古きDOS時代には、OSの割り込み機能としてINT21というアセンブラレベルのシステムコールにより実現していた機能です。
よって、言語側には、本来そのようなハードとOSに依存するような機能の関数はないのです。
キー入力は、本来、getchar(),gets() であるべきなのですが、・・・
リアルタイムにおされているキーの処理ができないとつくれないものが出てくることになりました。
それはゲームです。
C言語標準のキーボードからの入力は、本来OSと一体化するので標準入力のみをファイルとして扱っています。よってバッファリングに溜め込まれ、エンターキーなどでFlashされるという流れになるのですが、これではゲームが成り立ちませんよね。^^;
そこで、リアルタイムにキーを処理する機能が当時のDOSに盛り込まれたのです。
int21 あるいはNECのPC9801時代なら、int18 などの割り込み機能です。
つまり、マイクロソフトのDOS〜Windowsの流れには存在していますが、LinuxやUnixには必要ありませんでした。
なぜなら、サーバーにターミナル(TTY)をネットワークで接続するタイプのものだったからです。
しかし、実際にはローグや、ハングマンといったゲームにもリアルにキー入力を扱わなければゲーム性が無くなるので、ひっそりとリアルタイムキー入力処理は実現可能ではありました。
現在は、カノニカルモード(バッファー処理有りのモード)と、RAWモードの門ブロッキング処理に分けています。
つまり、非標準な機能として、端末(TTY)を一時的にノンブロッキングモードでどうささせ、キーバッファーしょりをせずリアルにキーボード処理をおこなう機能も盛り込まれています。
つまり、getch() も使えるようにはなっています。
もっとも簡単な方法は、ライブラリのncursysです。ncurses は、端末に依存しない形式でテキストユーザインタフェース (TUI) を作成するためのAPIを提供するライブラリです。
ただ実際には、kbhit()のようなキーが押されているかというテスト関数が必要なので別途用意します。
以下のソースは、MacのBSD上で動作を確認しましたので、そのまま使えます。
ーーーktest.c
#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;
}
int main(void)
{
puts("何かキーを押したら終了");
while (1) {
if (kbhit()) {
printf("'%c'を押しました。¥n", getchar());
break;
}
}
return 0;
}
ーーー
<>は全角文字なので半角に修正して下さいね
スポンサードリンク