C言語入門
第5週
プログラミング言語Ⅰ(実習を含む。),
計算機言語Ⅰ・計算機言語演習Ⅰ,
Scratch
• グラフィカルに表現されたロジック使って、ブ
ロックを組む感覚でプログラムが作成出来る
•
http://scratch.mit.edu/
プログラミン
• 文部科学省による
Scratch に似たプログラミング環境
•
http://www.mext.go.jp/programin/
apt-cyg
• Cygwin用ソフトウェアパッケージ管理ツール
• パッケージが提供されているソフトに関しては
install サブコマンドで自動インストールが
可能(webを探し回る必要がない)。
• 使い方は help サブコマンド
• 例: diff コマンドのインストール
mintty + bashapt-cyg と proxy の設定
• 学内から利用するにはproxyの設定が必要。apt-cyg
実行前に以下を mintty+bash へコピペして実行。
• 2014-05-06以降のversionはproxy自動検出対応済
upgrade-selfサブコマンドで一度apt-cyg自信をバー
ジョンアップしておけば以降proxyの設定は不要。
mintty + bash mintty + bash export ftp_proxy=http://proxy.cc.yamaguchi-u.ac.jp:8080/ export http_proxy=http://proxy.cc.yamaguchi-u.ac.jp:8080/ export https_proxy=http://proxy.cc.yamaguchi-u.ac.jp:8080/apt-cyg upgrade-self
diff のインストール
• mintty+bash から以下のコマンドを実行
mintty + bash
diff
• UNIX系のファイル比較コマンド
mintty + bash
$ diff wavtest.c,20140410_211536.c wavtest.c
56c56
< double dt = 1.0 / 22050.0;
---
> double dt = 1.0 / SampleRate;
58c58
< v = INT16_MAX * sin(M_TWOPI * 1 * f * dt * i) * 0.05;
---
> v = INT16_MAX * sin(M_TWOPI * f * dt * i) * 0.05;
diff
• 並列表示
• --side-by-sideオプションによる比較
fc
• Windows 標準添付のファイル比較コマンド
コマンドプロンプト >fc wavtest.c,20140410_211536.c wavtest.c ファイル wavtest.c,20140410_211536.c と WAVTEST.C を比較しています ***** wavtest.c,20140410_211536.c double f = pow(2.0, (d - 69.0) / 12.0) * 440.0; double dt = 1.0 / 22050.0;for (i = 0; i < NumSamples; i++) {
v = INT16_MAX * sin(M_TWOPI * 1 * f * dt * i) * 0.05; for (j = 0; j < NumChannels; j++) {
***** WAVTEST.C
double f = pow(2.0, (d - 69.0) / 12.0) * 440.0; double dt = 1.0 / SampleRate;
for (i = 0; i < NumSamples; i++) {
v = INT16_MAX * sin(M_TWOPI * f * dt * i) * 0.05; for (j = 0; j < NumChannels; j++) {
WinMerge
• GUIによるテキストファイルの比較ツール
• 相違点の合成も出来る
Rekisa
• GUIによる複数テキストファイルの比較ツール
パイプライン
• 書式: コマンド1 | コマンド2
• コマンド1の出力をコマンド2の入力に繋ぐ
• コマンド2実行時にキーボードを打ってコマンド1
の出力と全く同じ内容を入力したのと同じ効果を
得る。
• 例:
mintty + bashecho 2014 | ./a
コマンドプロンプトecho 2014 | is_leap_year_1_1
入力のリダイレクト
• 書式: コマンド < ファイル
• ファイルの内容をコマンドの入力に繋ぐ
• コマンド実行時にキーボードを打ってファイルの
内容と全く同じ内容を入力したのと同じ効果を得
る。
• 例:
mintty + bash./a < test1_input.txt
コマンドプロンプトis_leap_year_1_1 < test1_input.txt
test1_input.txt2014
出力のリダイレクト
• 書式: コマンド > ファイル
• コマンドの出力をファイルに繋ぐ
• コマンド実行時の出力をファイルに保存出来る。
• 例:
mintty + bash./a > test1_result.txt
コマンドプロンプトis_leap_year_1_1 > test1_result.txt
ファイル比較コマンドを用いた
動作テストの自動化
1. テスト用の入力と期待する出力を用意する
2. テスト用の入力を与えて出力結果得る
mintty + bash
./a < test1_input.txt > test1_result.txt
コマンドプロンプト
is_leap_year_1_1 < test1_input.txt > test1_result.txt
test1_input.txt
2014
test1_expect.txt
テキスト比較ツールを用いた
動作テストの自動化
3. 期待する出力と実際の出力を比較する
mintty + bash
diff test1_expect.txt test1_result.txt
コマンドプロンプト
シェルスクリプト、バッチファイル
• コマンドを入力する代わりに、事前にファイル
に書いておいた一連のコマンドを実行出来る。
test_all.sh
#!/usr/bin/env bash
./a < test1_input.txt > test1_result.txt && diff test1_expect.txt test1_input.txt ./a < test1_input.txt > test2_result.txt && diff test2_expect.txt test2_input.txt ./a < test1_input.txt > test3_result.txt && diff test3_expect.txt test3_input.txt # ...
./a < test1_input.txt > test9_result.txt && diff test9_expect.txt test9_input.txt
test_all.bat
@ECHO OFF
is_leap_year_1_1 < test1_input.txt > test1_result.txt && fc test1_expect.txt test1_result.txt is_leap_year_1_1 < test2_input.txt > test2_result.txt && fc test2_expect.txt test2_result.txt is_leap_year_1_1 < test3_input.txt > test3_result.txt && fc test3_expect.txt test3_result.txt REM ...
テキスト比較ツールを用いた
動作テストの自動化
• シェルスクリプトによる一括テスト
mintty + bashsh test_all.sh
test_all.sh #!/usr/bin/env bash./a < test1_input.txt > test1_result.txt && diff test1_expect.txt test1_input.txt ./a < test1_input.txt > test2_result.txt && diff test2_expect.txt test2_input.txt ./a < test1_input.txt > test3_result.txt && diff test3_expect.txt test3_input.txt # ...
./a < test1_input.txt > test9_result.txt && diff test9_expect.txt test9_input.txt
mintty + bash
chmod +x
./test_all.sh
chmod コマンドで 実行ビットをセット(+x)すると 直接実行もできるテキスト比較ツールを用いた
動作テストの自動化
• バッチファイルによる一括テスト
コマンドプロンプトtest_all.bat
test_all.bat @ECHO OFFis_leap_year_1_1 < test1_input.txt > test1_result.txt && fc test1_expect.txt test1_result.txt is_leap_year_1_1 < test2_input.txt > test2_result.txt && fc test2_expect.txt test2_result.txt is_leap_year_1_1 < test3_input.txt > test3_result.txt && fc test3_expect.txt test3_result.txt REM ...
じゃんけん
日本語
• じゃんけんぽん!
• ぐー
• ちょき
• ぱー
English
• One, two, three, go!
• Stone
• Scissors
• Paper
じゃんけん
• 入力
• キーボードから以下の文字を入力
• "m" : グー
• "v" : チョキ
• "w" : パー
• 出力
• CPU の手を生成して勝敗判定
• 勝ち、負け、引き分けを表示
じゃんけん
• CPUの手の生成とプレイヤーの手の入力と
stone-scissors-paper1.c
#define frand() (rand() / (RAND_MAX + 1.0))
char hand_str[] = {'m', 'v', 'w'};
int cpu;
int you;
printf("'m': stone, 'v': scissors, 'w': paper¥n");
printf("One, two, three, go!¥n");
printf("You : ");
srand(time(NULL));
cpu = frand() * 3.0;
you = getchar();
printf("CPU : %c¥n", hand_str[cpu]);
疑似乱数を用いて 0以上3未満の 整数を生成 実行毎に異なる値を 得るための 疑似乱数の初期化じゃんけん
• プレイヤーの手を数値に変換
stone-scissors-paper1.c
enum hand_enum {stone, scissors, paper};
// ...
switch (you) {
case 'm': you = stone; break;
case 'v': you = scissors; break;
case 'w': you = paper; break;
default:
printf("Your hand is invalid.¥n");
return EXIT_FAILURE;
}
switch 文では
break が重要。
break がない場合
次の条件用の処理も
続けて実行する。
試に break を
削って実行してみると
どうなるか?
列挙定数
stone = 0
scissors = 1
paper = 2
となっている
じゃんけん
• 勝敗の判定
stone-scissors-paper1.c switch (cpu) { case stone: switch (you) {case stone: printf("Draw game.¥n"); break; case scissors: printf("You lose.¥n"); break; case paper: printf("You win.¥n"); break; }
break; // ~中略~ case paper:
switch (you) {
case stone: printf("You lose.¥n"); break; case scissors: printf("You win.¥n"); break; case paper: printf("Draw game.¥n"); break; }
break; default:
printf("CPU hand is invalid.¥n"); return EXIT_FAILURE; }
switch 文では
break が重要。
break がない場合
次の条件用の処理も
続けて実行する。
試に break を
削って実行してみると
どうなるか?
定数
• リテラル
• 数値リテラル
• 文字列リテラル
列挙(enumeration)
列挙子(enumerator)
• 書式:
• enum 列挙名 {列挙定数名 [= 定整数値], ...}
• 値を設定しないと
• 0から開始
• 前の値から+1ずつ増加
• #define の代わりに使える
列挙(enumeration)
列挙子(enumerator)
• 例:
enum boolean {NO, YES};
enum escape {
BELL = '¥a',
BACKSPACE = '¥b',
TAB = '¥t',
NEWLINE = '¥n',
VTAB = '¥v',
RETURN = '¥r'};
enum month {
JAN = 1, FEB, MAR,
APR, MAY, JUN,
JUL, AUG, SEP,
OCT, NOV, DEC};
NO = 0 YES = 1 JAN = 1 FEB = 2 MAR = 3 ... DEC = 12
列挙(enumeration)
列挙子(enumerator)
• #define で書き変えた場合の例:
#define NO 0
#define YES 1
#define BELL '¥a'
#define BACKSPACE '¥b'
#define TAB '¥t'
#define NEWLINE '¥n'
#define VTAB '¥v'
#define RETURN '¥r'
#define JAN 1
#define FEB 2
#define MAR 3
// ...
#define DEC 12
列挙(enumeration)
列挙子(enumerator)
• stone-scissors-paper1.c の例
stone-scissors-paper1.c
enum hand_enum {stone, scissors, paper};
// ...
switch (you) {
case 'm': you = stone; break;
case 'v': you = scissors; break;
case 'w': you = paper; break;
default:
printf("Your hand is invalid.¥n");
return EXIT_FAILURE;
}
stone = 0
scissors = 1
paper = 2
となっている
乱数: ランダムな数値を得る
• rand 関数
:
疑似乱数整数の生成
• srand 関数
:
疑似乱数系列の初期化
• time 関数
:
現在時刻の取得
毎回違う値を得るため
乱数系列初期化に用いる
rand 関数
• int rand(void)
• [0:RAND_MAX]の範囲で整数の疑似乱数を返す
• 戻り値:
• 疑似乱数の整数を返す
• 値の範囲は 0 以上 RAND_MAX 以下
• RAND_MAX は stdlib.h で定義されている
• RAND_MAX は少なくとも 32767 以上である
• RAND_MAX + 1 はオーバーフローするかもしれ
ない
JM / rand(3)srand 関数
• void srand(unsigned int seed)
• 疑似乱数系列の初期化を行う
• 引数:
• seed: 疑似乱数の新しい系列の種
初期値は1
• 同じ種からは毎回同じ疑似乱数系列が生成
される。
JM / rand(3)疑似乱数とは?
• 演算で生成する疑似的な乱数
• POSIX 1003.1-2003 で挙げられている実装例
static unsigned long next = 1;
/* RAND_MAX を 32767 と仮定 */
int myrand(void) {
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % 32768);
}
void mysrand(unsigned int seed) {
next = seed;
}
計算式は決まっているので、 同じseedなら 毎回同じ計算になるため 毎回同じ乱数系列が生成される乱数系列の確認
• seed の値で乱数系列がどうなるか確認
randtest.cint seed, i;
printf("seed = ");
scanf("%d", &seed);
srand(seed);
printf("RAND_MAX: %.0f¥n", (double) RAND_MAX);
for (i = 0; i < 10; i++) {
printf("%.0f¥n", (double) rand());
}
実行毎に異なる乱数系列に初期化
• stone-scissors-paper1.c の例
stone-scissors-paper1.c
#define frand() (rand() / (RAND_MAX + 1.0))
char hand_str[] = {'m', 'v', 'w'};
int cpu;
int you;
printf("'m': stone, 'v': scissors, 'w': paper¥n");
printf("One, two, three, go!¥n");
printf("You : ");
srand(time(NULL));
cpu = frand() * 3.0;
you = getchar();
printf("CPU : %c¥n", hand_str[cpu]);
time関数は 現在時刻を返す関数なので 実行毎に異なる seed を与える事が出来るtime 関数
• time_t time(time_t *t)
• 現在時刻を UNIX time で得る
• 引数:
• t:
通常はNULLで良い
NULLでない場合*tにも戻り値を格納する
• 戻り値:
• 現在時刻を UNIX time で返す。
JM / time(2)UNIX time (UNIX時間、UNIX時刻)
• UNIX epoch (UNIX 紀元)
• 1970-01-01 00:00:00 UTC
• UNIX time
• UNIX epoch からの経過秒数
•
2038年問題
• 2038-01-19 03:14:07 UTC
= UNIX time: 2,147,483,647秒
= UNIC time: 0x7fffffff秒
• time_tが符号付き32bitの環境でオーバーフロー
EppochConverter2038年問題
• 2038-01-19 03:14:07 UTC
= UNIX time: 2,147,483,647秒
= UNIC time: 0x7fffffff秒
• time_t が符号付き 32bit の環境
• time_t がオーバーフロー
• 以降、正しい日時が処理できなくなる!
• 対策
• time_t の 64bit 化等の対応が必要
未対策の環境はあるのか?
• SOURCEFORGE.JP MAGAZINE / 2014-05-02:
2038年問題に対応した「OpenBSD 5.5」リリース
•
http://sourceforge.jp/magazine/14/05/02/160000
• OpenBSD はセキュリティ面で非常に定評のある OS
• そんな OS でもつい最近になってようやく対応してい
る状況もある。
time_t の確認
• 0x7fffffff秒,0x80000000秒,-1秒を確認
time_t_test.c char buf[1024]; time_t t = 0x7fffffff; struct tm *tm; printf("sizeof(time_t): %d¥n", sizeof(time_t));printf("time_t has sign: %s¥n", (~(time_t) 0) < (time_t) 0 ? "YES" : "NO");
tm = gmtime(&t);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S UTC", tm);
printf("%20luUL: %11ldL: %s¥n", (unsigned long) t, (long) t, buf);
t++;
tm = gmtime(&t);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S UTC", tm);
printf("%20luUL: %11ldL: %s¥n", (unsigned long) t, (long) t, buf);
t = -1;
tm = gmtime(&t);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S UTC", tm);
strftime 関数
• size_t strftime(char *s, size_t max,
const char *format,
const struct tm *tm)
• 日付と時刻を文字列に変換する
• 引数:
• s:
変換結果の格納先(通常はchar型配列)
• max: sのサイズ
• format: 変換の書式
• tm:
time_t 型の値をlocaltime関数または
gmtime関数を用いて変換した日付と時刻情報
• 戻り値:
• 終端文字列'¥0'を含めた変換結果のサイズ
• 格納先のサイズが不足していた場合は0
JM / strftime(3) JM / ctime(3)各環境のtime_tの状況
Cygwin64 + GNU C
$ gcc time_t_test.c && ./a sizeof(time_t): 8
time_t has sign: YES
2147483647UL: 2147483647L: 2038-01-19 03:14:07 UTC 2147483648UL: 2147483648L: 2038-01-19 03:14:08 UTC 18446744073709551615UL: -1L: 1969-12-31 23:59:59 UTC
Cygwin32 + GNU C
$ gcc time_t_test.c && ./a sizeof(time_t): 4
time_t has sign: YES
2147483647UL: 2147483647L: 2038-01-19 03:14:07 UTC 2147483648UL: -2147483648L: 1901-12-13 20:45:52 UTC 4294967295UL: -1L: 1969-12-31 23:59:59 UTC
各環境のtime_tの状況
Borland C++ 5.5.1
>bcc32 time_t_test.c && time_t_test
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland time_t_test.c:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland sizeof(time_t): 4
time_t has sign: YES
2147483647UL: 2147483647L: 2038-01-19 03:14:07 UTC 2147483648UL: -2147483648L: 2038-01-19 03:14:08 UTC 4294967295UL: -1L: 2106-02-06 06:28:15 UTC
各環境のtime_tの状況
Visual Studio 2013 Express Desktop Windows 32bit版
>cl time_t_test.c && time_t_test
Microsoft(R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x86 Copyright (C) Microsoft Corporation. All rights reserved.
time_t_test.c
Microsoft (R) Incremental Linker Version 12.00.21005.1
Copyright (C) Microsoft Corporation. All rights reserved.
/out:time_t_test.exe time_t_test.obj
sizeof(time_t): 8 time_t has sign: YES
2147483647UL: 2147483647L: 2038-01-19 03:14:07 UTC 2147483648UL: -2147483648L: 2038-01-19 03:14:08 UTC 4294967295UL: -1L: 1969-12-31 23:59:59 UTC
VC は long が 32bit だったので 64bit 表示出来てない点には注意
各環境のtime_tの状況
Visual Studio 2013 Express Desktop Windows 64bit版
>cl time_t_test.c && time_t_test
Microsoft(R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x64 Copyright (C) Microsoft Corporation. All rights reserved.
time_t_test.c
Microsoft (R) Incremental Linker Version 12.00.21005.1
Copyright (C) Microsoft Corporation. All rights reserved.
/out:time_t_test.exe time_t_test.obj
sizeof(time_t): 8 time_t has sign: YES
2147483647UL: 2147483647L: 2038-01-19 03:14:07 UTC 2147483648UL: -2147483648L: 2038-01-19 03:14:08 UTC 4294967295UL: -1L: 1969-12-31 23:59:59 UTC
VC は long が 32bit だったので 64bit 表示出来てない点には注意
[0:1) の実数の乱数生成法
• rand(): [0:RAND_MAX]の整数の乱数を生成
• [0:1) を得るには?
• 実数にして RAND_MAX + 1 で割れば良い
• RAND_MAX って幾つ?
• RAND_MAX + 1 だとオーバーフローするかも?
• RAND_MAX + 1.0 なら大丈夫
#define frand() (rand() / (RAND_MAX + 1.0))
暗黙の算術変換により全てdoubleに型変換されて 計算される。
暗黙の算術変換 (概略)
• 二項演算子の両辺が異なる型の場合
以下のルールで変換(符号ありの場合)
• 片方がlong double: 他方をlong doubleに変換
• 片方がdouble: 他方を doubleに変換
• 片方がfloat: 他方をfloatに変換
• char, shortをintに変換
[0:N-1]の整数の乱数生成法
• [0:1) の実数の乱数を生成してNを掛けた後
整数に変換する
int x;
x = frand() * N;
なぜ以下の計算方法では駄目か? x = rand() / RAMD_MAX * N; x = rand() / RAMD_MAX * (N – 1); x = frand() * (N – 1); ヒント: • 生成される値の範囲は? • N が出る確率は? [0:N-1] の整数の乱数 = [0:N) の整数の乱数任意の範囲の乱数整数
• stone-scissors-paper1.c の例
stone-scissors-paper1.c
#define frand() (rand() / (RAND_MAX + 1.0))
char hand_str[] = {'m', 'v', 'w'};
int cpu;
int you;
printf("'m': stone, 'v': scissors, 'w': paper¥n");
printf("One, two, three, go!¥n");
printf("You : ");
srand(time(NULL));
cpu = frand() * 3.0;
you = getchar();
printf("CPU : %c¥n", hand_str[cpu]);
[0:2] の乱数整数の生成N面体のサイコロ
• [1:N] の整数が等確率で欲しい
int x;
x = frand() * N + 1;
[1:N] の整数の乱数 = [0:N-1] + 1 の整数の乱数 = [0:N) + 1 の整数の乱数教科書の例
• 実は間違っている
test_p322.c #include <stdio.h> #include <stdlib.h> #include <time.h> #define RANGE_MIN 0 #define RANGE_MAX 10 void main() { int rand10; // 0以上未満 srand( (unsigned)time(NULL) );rand10=(int)(((double) rand() / (double) RAND_MAX) * RANGE_MAX + RANGE_MIN); printf("求まった乱数は %d¥n", rand10); } 0~9 までは (RAND_MAX / 10) / (RAND_MAX + 1) の確率で出現するので 0以上10以下の乱数を意図したとしても 出現確率のバランスが悪い rand() は 0 以上 RAND_MAX 以下 の値を返すので、この実装では 1/(RAND_MAX+1) の確率で 10 が出現してしまう ここのコメントも おかしいが、 0以上10未満でも 0以上10以下でも やってはいけない実装 乱数に関してよく見られる 有名な間違いです。
もっと質の良い疑似乱数
• random 関数 (POSIX.1-2001.)
• 非線形加法フィードバック
• JM /
random
(3)
• drand48 関数 (POSIX.1-2001.)
• 線形合同法+48bit整数
• JM /
drand48
(3)
• メルセンヌツイスタ
• Wikipedia /
メルセンヌツイスタ
getchar 関数
• int getchar(void)
• 入力 stream から1文字読み込む
• stream というのはバッファのようなもの
• 通常はENTERが押されるまで入力streamには値
が入って来ない。入力ストリームに値がない場合
は値が入ってくるまで待機する
• 戻り値:
• 入力された文字の文字コード返す
• ファイル終端やエラーの場合はEOFを返す
JM / fgetc(3)getchar 関数の動作
• ENTERが押されるまで一気に読み込む
getchartest.c#include <stdio.h>
#include <stdlib.h>
int main()
{
int c;
while ((c = getchar()) != EOF) {
printf("%#04x¥n", c);
}
return EXIT_SUCCESS;
}
バッファリングと言います。 読み込み処理を 高速化するための仕組みです。 バッファリングに溜めてある 入力文字を1文字ずつ取り出します。 バッファが空になると ENTERが押されるまで 入力待ちの状態になります。tty_getkey
• ENTER待ちなしのキーボード入力
tty_getkey_example1.c #include "tty_getkey.h" #include "msleep.h" int main() { int c; tty_begin(); // 開始処理 while(tty_iskeyhit() == 0) { // 打鍵待ちループ msleep(1); // CPU に負荷をかけずに 1 msec 待つ// tty_ishitkey() は即座に値を返すので空ループだと CPU に負荷がかかる }
c = tty_getkey(); // 打鍵キーの取得
tty_printf("%#x key was hit.¥n", c); // tty 用の printf tty_printf("Hit ESC key to exit.¥n");
while(KEY_ESC != tty_getkey()) { // 打鍵待ちループ ; // tty_ketkey()はキー入力があるまで待機するため空ループでも CPU に負荷をかけない } tty_end(); // 終了処理 return EXIT_SUCCESS; }
tty_getkey
• ENTER待ちなしのキーボード入力
• Windows 系の環境
• conio.h ライブラリを利用
• embarcadero / RAD Studio /
conio.h
• MSDN /
Console and Port I/O
• UNIX 系の環境
• curses ライブラリを利用
tty_getkey を利用したプログラムの
コンパイル
• サンプルプログラム
• tty_getkey_example1.c : サンプルプログラム本体
• 必要なファイル
• msleep.h
: ミリ秒 sleep 用ヘッダ
• tty_getkey.h
: tty_getkey ヘッダファイル
• tty_getkey.c
: tty_getkey 本体
mintty + bash + GNU C
$ gcc tty_getkey_example1.c tty_getkey.c -lcurses
コマンドプロンプト + Borland C++
tty_getkey 利用前の準備
Cygwin の場合
• ncurses の開発用ライブラリが必要
• 以下のコマンドを入力してインストール
• Borland C++ は、標準添付の conio というライ
ブラリを使っているので前準備は不要
Cygwin64 mintty + bash
apt-cyg install libncursesw-devel
Cygwin32 mintty + bash
Cygwinが何bit版か確認する方法
• uname コマンドに -a オプションを付けて実行
Cygwin64 mintty + bash
$ uname -a
CYGWIN_NT-6.1 EX58EXTREME 1.7.27(0.271/5/3) 2013-12-09 11:54 x86_64 Cygwin
Cygwin32 mintty + bash
$ uname -a
CYGWIN_NT-6.1-WOW64 EX58EXTREME 1.7.27(0.271/5/3) 2013-12-09 11:57 i686 Cygwin
i686 なら 32bit 版 x86_64 なら 64bit 版
tty_getkey 初期化関数
• int tty_begin(void)
• tty_getkey の初期化処理を行います
• int tty_end(void)
tty_getkey キー待ち受け関数
• int tty_iskeyhit(void)
• キー入力の有無を調べます。
• キー入力があれば 1 なければ 0 を返します。
• int tty_getkey(void)
• キー入力を取得します。キー入力がない場合、キー
入力が発生するまで待機します。
• 通常のキーは'a'や'A'等の文字コードを返します。
• 特殊キーの場合はKEY_UPやKEY_DOWN等のマクロで
定義されたキーコードを返します。
tty_getkey() が返すキーコード
• KEY_INSERT
• KEY_DELETE
• KEY_HOME
• KEY_END
• KEY_PAGEUP
• KEY_PAGEDOWN
• KEY_UP
• KEY_DOWN
• KEY_LEFT
• KEY_RIGHT
• KEY_ESC
• KEY_TAB
• KEY_SPACE
• KEY_BS
• KEY_ENTER
• KEY_F1 ~ KEY_F48
通常のキーは 'a', 'A' 等の
文字定数リテラルが対応
tty_getkey 出力関数
• int tty_printf(char *fmt, ....)
• 書式付の出力を行います。
• 画面制御を伴うためtty_begin()~tty_end()
の間では、通常のprintをは使わないでください。
• int tty_setxy(int x, int y)
tty_getkey 画面情報関数
• int tty_getx(void)
• カーソルの x 座標を返します。
• int tty_gety(void)
• カーソルの y 座標を返します。
• int tty_getw(void)
• カーソルが移動可能な画面の幅を返します。
• int tty_geth(void)
• カーソルが移動可能な画面の高さを返します。
tty_getkey_example2
• カーソルキーで移動、ESC キーで終了
• 移動した場所に * を表示する
tty_getkey_example2
tty_getkey_example2.c