<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
	<title><![CDATA[ No.491 - 電装工芸日記 - 舞台照明機器の製作とか - ]]></title>
	<link>https://www.densokogei.jp/tegalog/tegalog.cgi</link>
	<description><![CDATA[ 今年は開発案件を進めたい ]]></description>
	<language>ja</language>
	<copyright>Copyright 2026</copyright>
	<lastBuildDate>Mon, 20 Apr 2026 06:10:27 +0900</lastBuildDate>
	<generator><![CDATA[ <!-- てがろぐ Version: -->Powered by <a href="https://www.nishishi.com/cgi/tegalog/" target="_top">てがろぐ</a> Ver 3.4.0 ]]></generator>
	<!-- BEGIN ENTRIES -->
	<!-- One Entry Data for RSS Feed -->
<item>
	<title><![CDATA[ 　キー入力の処理を書き直してみました。 ]]></title>
	<description><![CDATA[ 　キー入力の処理を書き直してみました。<br />　ファンクションキーやカーソルキーなどの複数バイトでキーコードを出すキーも扱えます。shiftやAltなどの装飾キーは拾えませんケド。<br />　入力の待ち時間はありません。get_inkey()はすぐ戻ってきます。戻り値はキーコードの長さを表しますが、０なら入力が無かったと判別出来ます。<br />　得られるのは標準入力からのASCIIコードです。read()はキャッシュを読むだけでタイミング次第では取得値に複数のキーコードが混じることがありますが、これをキー単体のコードとして仕分けています。キャッシュの一番前のキーコードだけを取り出す単純な仕分けで、想定外のキーコードは読み飛ばしていますが十分でした。<br />　キーコードで何かをするにはswitch文やif文でそのコードを仕分ける必要があります。<br />　正常に動かすなら、100msec(1/10秒)毎以下でget_inkey()を読みに行く必要があります。<br />　定数設定とプロトタイプ宣言をヘッダーファイルに書けばincludeしてライブラリとして使えます。mainはコメント化して使った方がいいですけど。<br /><br /><small class="decorationT"><span class="decorationF deco-code">Raspberry Pi 4B / Rasbian11_32bit(blueseye) / OS標準gcc<br />/*　---------------------------------<br />　　リアルタイムにキー入力をチェックする<br />　　--------------------------------- */<br />/*　getcharはキー入力のキャッシュが空だと入力があるまで待つ。<br />　　キャッシュが無いなら無いでそのまま抜けたいが、タイムアウトを設定しても<br />　　抜けない。環境に寄るのかもしれないが、ioctl.hを用いることで<br />　　タイムアウトが実現できた。<br />　　get_inkeyの呼び出しは100msec(1/10秒)毎以下で繰り返し行うこと。短い方がいい。<br />*/<br /><br />/*　ライブラリ読み込み */<br />＃include &lt;stdio.h&gt;<br />＃include &lt;sys/ioctl.h&gt;<br />＃include &lt;termios.h&gt;<br />＃include &lt;unistd.h&gt;<br />＃include &lt;time.h&gt;<br /><br />/*　定数設定 */<br />＃define SET 1　　　　　　　 // ioctl.readのモードをRawにするフラグ<br />＃define RESET 0　　　　　　 // ipctl.readのモードをCanonicalに戻すフラグ<br />＃define LENGTH_STACK 32　　 // キー入力のスタック長 状況によるが、長めにしないと取り出しが半端になる<br />＃define ESC 0x1B　　　　　　// ASCIIコード ESC <br />＃define BRACKET 0x5B　　　　// ASCIIコード ［<br /><br />/* プロトタイプ宣言 */<br />int get_inkey( char *get_char ) ;　　　 // キー入力を取得する関数<br />　　// 戻り値　　　　　　　　　　　　　 // -1=エラー、0&gt;=取得したキーコードの長さ<br />　　// char *get_char　　　　　　　　　 // 取得したキーコードを返すポインタ<br />int set_inkey( int mode_flag ) ;　　　　// キー入力のモードを設定する関数<br />　　// int mode_flag　　　　　　　　　　// モードの設定フラグ 1(SET)=Rawモードにする / 0(CLR)=モードを戻す<br /><br />/*　テスト用main */<br />int main(void) {<br />　　int i ;　　　　　　　　　　　　　　 // for文用カウンタ<br />　　char get_char［ LENGTH_STACK ］ ;　　 // 入力されたキーコードを保存する変数<br />　　int ret_inkey　;　　　　　　　　　　// get_inkeyからの戻り値を保存する変数<br />　　/* コンソールの設定を初期化 */<br />　　set_inkey( SET ) ;<br />　　/* 無限ループで入力したキーを表示する */<br />　　for(;;) {<br />　　　　usleep( 1e5 ) ;<br />　　　　ret_inkey = get_inkey( get_char ) ;　　　　 // get_inkeyから文字取得<br />　　　　/* get_inkeyの戻り値を処理 */<br />　　　　if( ret_inkey == -1 ) break ;　　　　　　　 // 戻り値が-1ならエラーなのでループから抜けて終了<br />　　　　if( get_char［0］ == 0x0A ) break ;　　　　　 // エンターキーが押されたならループを抜けて終了<br />　　　　/* 入力された文字を出力する */<br />　　　　if( ret_inkey &gt; 0) {<br />　　　　　　for( i = 0; i &lt; ret_inkey; i++ ) {<br />　　　　　　　　if( get_char［i］ &gt;= 0x20 && get_char［i］ &lt;= 0x7E ) {　　　　　// 入力された文字を出力する・・・表示可能な文字<br />　　　　　　　　　　printf( &quot; %c&lt;%02X&gt;&quot;, get_char［i］, get_char［i］ ) ;<br />　　　　　　　　} else if( get_char［i］ &gt;= 0x00 && get_char［i］ &lt;= 0xFF ) {　 // 入力された文字を出力する・・・表示不可能な文字<br />　　　　　　　　　　printf( &quot;　&lt;%02X&gt;&quot;, get_char［i］ ) ;<br />　　　　　　　　}<br />　　　　　　}<br />　　　　　　printf( &quot;\n&quot; ) ;<br />　　　　}<br />　　　　fflush( stdout ) ;　// 画面表示のスタックを吐き出す　　　<br />　　}<br />　　/* 正常終了 */<br />　　printf( &quot;\n&quot; ) ;　　　　// 念のための改行<br />　　set_inkey( RESET ) ;　　// コンソールの設定を元に戻す<br />　　return 0 ;<br />}<br /><br />/* キー入力を取得する */<br />int get_inkey( char *get_char) {<br />　　// char *get_char　　　　　　　　　　　　　　　　　 // キーコードを返すためのchar配列のポインタ<br />　　int i ;　　　　　　　　　　　　　　　　　　　　　　 // for用変数<br />　　char in_char［ LENGTH_STACK ］ = { 0x00 };　　　　　　// 入力されたキーを取得<br />　　int read_length ;　　　　　　　　　　　　　　　　　 // read()戻り値 キーコードのバイト数<br />　　int put_length = 0 ;　　　　　　　　　　　　　　　　// 戻り値 キーコードのバイト数<br /><br />　　/* get_charの初期化 */<br />　　for( i = 0; i &lt; LENGTH_STACK; i++ ) {　　　　　　　 // すべての値を0x00にする<br />　　　　get_char［ i ］ = 0x00 ;<br />　　}<br />　　/* キー入力を読み取る */<br />　　read_length = read( 0, &in_char, LENGTH_STACK ) ;　 // read_lengthに取得バイト数、in_charにキーコードを得る<br /><br />　　/* 取得値の仕分け */<br />　　if( read_length &lt; 0 ) {　　　　　　　　　　　　　　 // 取得エラーなのでエラーを返して終了<br />　　　　return -1 ;<br />　　} else if( read_length == 0 ) {　　　　　　　　　　 // キーコードを得られなかったのでゼロを返す<br />　　　　return 0 ;<br />　　} else if( read_length == 1　　　　　　　　　　　　 // 取得が１バイトか先頭バイトがESC(0x1B)以外なら先頭バイトを返す<br />　　　　　　　|| in_char［ 0 ］ != ESC ) {<br />　　　　get_char［ 0 ］ = in_char［ 0 ］ ;　　　　　　　　　// 値コピー<br />　　　　return 1 ;<br />　　} else if( read_length &gt; 2　　　　　　　　　　　　　// 3バイト以上で先頭２バイトが0x1B(ESC)、0x5B(［)なら<br />　　　　　　　&& in_char［ 0 ］ == ESC　　　　　　　　　　// ファンクションキーまたはカーソルキー<br />　　　　　　　&& in_char［ 1 ］ == BRACKET ) {<br />　　　　get_char［ 0 ］ = ESC ;　　　　　　　　　　　　　 // 0バイト目<br />　　　　get_char［ 1 ］ = BRACKET ;　　　　　　　　　　　 // 1バイト目<br />　　　　put_length = 2;　　　　　　　　　　　　　　　　 // 戻り値設定<br />　　　　for( i = 2; i &lt; read_length; i++ ) {　　　　　　// 2バイト目以降をコピー<br />　　　　　　if( in_char［ i ］ == ESC ) break ;　　　　　 // 末尾にESCがあれば終了<br />　　　　　　　　get_char［ i ］ = in_char［ i ］ ;　　　　　// 値コピー<br />　　　　　　　　put_length++ ;　　　　　　　　　　　　　// 戻り値インクリメント<br />　　　　}<br />　　　　return put_length ;　　　　　　　　　　　　　　 // 戻り値送って終了<br />　　}<br />　　return 0 ;<br />}<br /><br />/* キー入力のモードを設定する */<br />int set_inkey( int mode_flag ) {<br />　　static struct termio tty_backup ;　　　　　　　 // 変更前の設定を保持<br />　　static struct termio tty_change ;　　　　　　　 // 変更後の設定を保持<br />　　/* モードを設定する */<br />　　if( mode_flag == SET ) {<br />　　　　ioctl( 0, TCGETA, &tty_backup ) ;　　　　　 // 現在の設定を読み出し<br />　　　　tty_change = tty_backup ;　　　　　　　　　 // 現在設定のスタック<br />　　　　tty_change.c_lflag &= ~( ECHO | ICANON ) ;　// エコーを止め、RAW モードへ変更<br />　　　　tty_change.c_cc［ VMIN ］= 0 ;　　　　　　　　// 0文字入力された時点で入力を受け取る<br />　　　　tty_change.c_cc［ VTIME ］ = 0.01 ;　　　　　 // 何も入力がない場合、1msec待つ (1 = 1/10sec)<br />　　　　ioctl( 0, TCSETAF, &tty_change ) ;　　　　　// ここで設定を反映<br />　　/* モードを戻す */<br />　　} else if( mode_flag == 0 ) {<br />　　　　ioctl( 0, TCSETAF, &tty_backup ) ;　　　　　// スタックしていた設定に戻す<br />　　}<br />　　return 0;<br />}</span></small><br /><small class="decorationS">　※ このブログシステムでは＃や［が機能文字扱いなので、上記ではこれらを全角文字で書いています。</small><br /><br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%ef%bc%a3%e8%a8%80%e8%aa%9e" class="taglink" title="Ｃ言語">#Ｃ言語</a> -- Posted by 電装工芸 〔4874文字〕 ]]></description>
	<link>https://www.densokogei.jp/tegalog/tegalog.cgi?postid=491</link>
	<guid>https://www.densokogei.jp/tegalog/tegalog.cgi?postid=491</guid>
	<category>tegalog</category>
	<pubDate>Tue, 31 Jan 2023 14:20:06 +0900</pubDate>
</item>

	<!-- END ENTRIES -->
</channel>
</rss>

