Q ディスクの空き容量を知りた いのですが , どうすればよいでし A ディスクの総容量や空き容量 は getdfree 関数を使うことにより 調べることがてきます。 List 1 にデ イスクの空き容量を調べる関数例 を示しますのて、参考にしてくださ 0 0 158 C MAGAZINE 1 2 4 たとえば , クライアントウインド バーの範囲を指定してください SetScroIIRange< スクロール A スクロールバーが表示されません。 たのですが , 実際に動作させると ールバーを表示させるよう指定し CROLL や WS HSCROLL でスクロ インドウのスタイルとして WS VS しています。 M 引のクライアントウ Windows のプログラムを開発 Q 値を指定することがて、きます。 び出し側に戻るときのレジスタの などとすることてハンドラから呼 bx 0x 1234 , ています。したがって , タを退避した領域そのものを指し Fig. 1 に示された引数は , レジス の内容が関数に渡されます。 ては Fig. 1 のような形式て、レジスタ interrupt 修飾子を使った関数 0 A ますか。 タの値を変更して戻ることはでき 復帰を行ってくれますが , レジス 数は , 自動的にレジスタの退避 , interrupt 修飾子が使われた関 Q ホーランド lnformation from C0mpiler Makers 10 : { 16 : } 19 : ( 1 : 〃 3 : 〃 6 : ″ 11 : ″ 12 : / / 14 : 〃 15 : 〃 16 : / / 17 : / / 18 : / / 19 : 〃 20 : 〃 21 : 〃 38 : / / BorIand C 十十 Turbo C 十十 ウの WM CREATE メッセージの 処理ルーチンに Fig. 2 のような文を 追加してください Q TurbO AssembIer が LEA 命令 を MOV 命令に置き換えてしまうた め , 予想したコードサイズと違っ てしまいます。これを置き換えな いようにはできませんか。 0 と , シンポル情報がみつからない ログラムをデバッグしようとする TurbO Debugger で . COM プ Q 0 してください NK 4.0 を使ってリンクするように orland C 十十に付属している TLI rbo C Ver. 2.0 のプログラムを B が表示されます。この場合は , Tu ようとするとこうしたメッセージ Debugger Ver. 2.5 て、デバッグし and C 十十に付属している Turbo デルて、作成したプログラムを Borl Turbo CVer. 2.0 のラージモ A ーになってしまいます。 がシンポル情報がないというエラ 「 . 2.5 でデバッグしようとしました ログラムを , Turbo Debugger Ve TurbO C Ver. 2.0 で作ったプ Q 0 ってください るときは , SMART 疑似命令を使 ください。再度最適化を有効にす は NOSMART 疑似命令を使って こうした最適化を禁止するために 高速な MOV 命令に置き換えます。 えが可能な場合は LEA 命令をより Turbo AssembIer は , 置き換 A List 1 3 : #include く dOS. h 〉 2 : #include く dir. h> 1 : #include く stdiO. h> 4 : 6 : 8 : 11 : 12 : 13 : 14 : 15 : 17 : 20 : 21 : 22 : 18 : void min() * ( 10 ) dinfO. df 一 * (long)dinfo. df—sclus; return (long)dinfo. df—avail getdfree(drv, 記 infO) : struct dfree dinfo; 9 : 10 getdiskfree(int drv) drv: ドライブ番号 ( 1 = A : , 2=B:, * ディスクの空き領域の大きさを取得する ' A' + cu ー 1. getdiskfræ(curdr の ) : printf("Drive : Xld bytes free%n ” int curdrv = getdisk() + 1 : List 2 2 : ″ Turbo Vision ーネストされたメニューの作成 7 : / / -TMenuItem には 2 つのコンストラクタがあります。メニュー項目の内容は、 メニューを作成する例を示します。 4 : 〃ーこのサンプルプログラムでは、 TSubMenu クラスを使ってネストされた 10. 13 : これらの 2 つのコンストラクタを使って制御されます。 TMenuItem(const char *aName, ushort aCormnd, ushort aKeYC«1e, ushort aHel$-•tx = hcNoContext, char *P ニ 0 , TMenuItem *aNext ー TMenuItem(const char *aName, ushort aKeyCcHe, TMenu *aSubMenu, ushort 1 tx = hcN(ßontext, TMenuItem *aNext ニの : で示されたメニューが呼び出されます。 2 番目のコンストラクタが使われると、メニュー項目を選択すると aSubMenu ことで aCommand で示されたイベントが生成されます。 これらのコンストラクタの最初の形式が使われると、メニュー項目を選択する 22 : #define Uses_MsgBox 23 : #define Uses_TApplication 24 : #define Uses TButton 25 : #define Uses_TDeskT 叩 26 : #define Uses_TDialog 27 : #define Uses_TKeys 28 : #define Uses TMenu 29 : #define Uses TMenuBar 30 : #define Uses_TMenuItem 31 : #define Uses TStaticText 32 : #def ine Uses_TStatusIhf 33 : #def ine Uses_TStatus ltem 34 : #define Uses_TStatus い ne 35 : #define Uses_TSubMenu 36 : #include く tv. h> 39 : 〃コマンド定義
onfig. h を入れておく必要がある。また統合 環境の中て、コンパイルするのて、はなく ,TC C を使用する。 tcc -v -K -J -w -ml -c ( デバッガを使用 /char を unsigned cha r にする / 漢字を使用する / 警告あり / ラー ジメモリモード / リンクは行わずコンバ イルのみ行う ) ・ TurbO C 用 config. h #define TURBOC #ifndef MSDOS #define MSDOS #endif #ifndef PROTOTYPE #define PROTOTYP E wtypew. exeC 表示したファイル Fig. 3 くくファイルの表示 > > s c r 0 1 ー T$TO 【書式】 ウィⅢ 81 ude 終ÄincIude く stdiO. h> äinclude く stdlib. h 〉 äinclude く string. h> Ⅲ nclude ” curses. h ” Ⅲ fde 「 PROTOTYPE ウインドウの 1 行スクロール ” conf ig. h ” 終了 ESC 選択 C R 次画面 TAB 前画面 B S Fig. 4 U N Ⅸ上での sc 「 0 Ⅲ exe の実行画面 #endif MS-C MS-C て、コンパイルする場合には , 従来と 同様にコンパイルスイッチを設定するとと もに , MS-C コンパイラのディレクトリ (M (C) 下の INCLUDEi•ィレクトリの中に con fig. h を入れておく必要がある。 CL /AL /Od /W2 /Zi /J /c 関数 . c ( ラージメモリモード /CodeView を使用 / 警告レベルは 2/char を unsigned char に する / リンクは行わずコンバイルのみ行 鰍 x 3 れ ・唸氿ー町田ま 亂 0 リ t t を虹 . C 0 第 . 8 懇 ー V 駅謝 師嘯 tP. C 計 P. 1 TE 訂 1 . 8 E E. H し A 間 . C 町一層 . C 3. 0 trans 制 2 は 0 州 07. C 0 Ⅲ S. C CT 山 C 03. C ー E . C [ 0 」 TF 〔 . C [ 雅田 E C 町一順 . C ー「 a03 制 . 0 tr 3 制 2 第圏 . C ー SPCKEY C 価 F ( . C ー y. れ TESTI. C 第 E 用 2. C 000Y2 ⅱ nd ー 0 リ 00 を門 . C 層ー 00k をれ C Fig. 5 U NIX 上での wtypew. exe の実行画面 ・ MS-C 用 config. h #define MSC #ifndef MSDOS #define MSDOS #endif #ifndef PROTOTYPE #define PROTOTYPE ー日 5 第代 00Y ・を一 5 第 0 北 を y. S 盟尺されました ー町フィンドウの表示ー ) T A B VIDIN ー〉 CRO SPCTO 終 TESTO 1 供 P [ 0 介 F EF 貶 C 町 E 灯順 . C tr 3 制 2 #endif 道具箱に追加された関数を UN Ⅸ上て、コン パイルし , 特定のライプラリ ( たとえば libc b 。 x. a ) に追加するには , 以下のような操作 を行えばよい。なお , 当然のことながら , 132 C MAGAZINE 1992 4 ー爲 CA に . C 町ー物 . C ー 0 ー 0 ーを . 0 3. 0 t 「 an ー制 2.0 Cu 「 . 0 「 00Y2 れ nd t0000 を門 . 0 30 「 y. 0
「何を知っていれば , イベントを知っている TYPE という型を作り , それをメンバに入 クチクタク時を刻むタイマイベント用に「現 れよう。マウスのイベントはボタンの押下 在時刻」というメンバを用意してもいいけれ 「イベントを同定するにはどんなデータが必 やらカーソルの移動などさらに多種類にな こて、は何回目のチクタクかを示す力 要か」 るから , それは MOUSE EVENT という別 ウンタとして TICK 型をメンバに含めてみよ 「イベントとは何か ? 」 こまて、はよし。 う。そして , もちろんキーイベントて、は , のメンノヾにしておこう。 などとなるてしよう。 マウスイベントが起こったときに , マウス どんな文字が入力されたかを知る必要があ どんな種類のイベントが起こったの る。私が考えたいイベントに必要な情報は カーソルがどこにあったのかを知ることは かを知る必要はあるな , それなら EVENT 重要だ。それは 2 次元の x と y て、いい。チクタ これくらいて、いいな 私はこのように考えて構造体 EVENT を作 イベント型の定義 成しました。これが私の設計した「イベント の定義」て、す。あなたは , あなたのイベント の定義をしてかまいません・・・・・・それがあな たの目的に合っているならば。 イントを得る関数を作ろう 文字型は C 言語に初めから備えられてお り , 文字を得る関数 getch ( ) はライプラリ関 数として処理系に用意されています。これ と同様に , イベント型という新しい型を作 ったからには , イベントを得る関数 get ne xt event ( ) を作る必要があります。 イベントを得る関数 get next event() の 役割りは関数 getch ( ) の役割りと同じことて、 す。 getch ( ) は入力した文字を順番にひとつ ずつ返します。 get next event() は発生し たイベントを順番にひとつずつ返します。 関数 getch ( ) が文字を返すのに対して , 関数 get next event ( ) はイベントを返します ( T able 1 参照 ) 。 関数がイベントを返すってどういう おやおや。先ほど作ったじゃないて、すか。 「これさえわかっていればイベントを同定て、 きる情報の集まり」 , すなわち EVENT 型の 構造体を返せばいいのて、す。 イベントループ といえるか」 List 1 : typedef enum { EVENT MOUSE = 0X001f , 2 : EVENT KEYBOARD = 0X0100 , EVENT TIMER = 0X10 圓 , 4 : 5 : } EVENT_TYPE; 6 : 7 : typedef short MOUSE—EVENT; 0X0001 / * カーソルが移動したイベント * / 8 : #define MOUSE_EVENT_MOVE 0X0002 / * 左ボタンが押されたイベント * / 9 : #define MOUSE_EVENT_PRESS_LEFT 10 : #define MOUSE—EVENT RELEASE—LEFT 0X0004 / * 左ボタンが離されたイベント * / 11 : #define MOUSE—EVENT PRESS-RIGKT 0X0008 / * 右ボタンが押されたイベント * / 12 : #define MOUSE-EVENT_RELEASE_RIGHT 0X0010 / * 右ボタンが離されたイベント * / 0X001f / * すべての OR * / 13 : #define MOUSE EVENT—ALL 14 : 15 : typedef struct { / * イベントの種類 * / EVENT_TYPE event_type ; MOUSE_EVENT mouse_event ; / * マウスイベントの種類 * / int / * マウスの位置 * / TICK / * 何回目のクロックイベントか * / tick; 20 : char / * キーコード * / key; 21 : ) EVENT; / * マウス関連のイベント / * キーポードイベント / * 定期的に呼び出されるイベント * / イベントグループ List event—loop(void) EVENT event ; event = get—next—event() : / * 次のイベントを取得 * / if (event. event—tYIE = EVENT—MOUSE) { exec_mouse (&event) : / * マウスイベント * / else if (event. event_type = = EVENT TIMER) { exec_timer(&event) ; / * タイマーイベント * / else if (event. event_type = EVENT_KEYBOARD) { exec—keyboard(&event) : / * キーイベント * / else { printf("Unknown event. %n") ; 0 1 り也 3 4 戸 0 6 7 8 9 0 1 りな 00 -4 ′ 0 6 叮ー 8 9 0 1 さて , イベント型と関数 get next event ( ) がて、きてしまえば , あとはもう楽て、す。 イベント駆動などと難しいことをいわなく 72 C MAGAZINE 1 2 4
ロックを割り当てるときには , リストの先 割り当てられたものてあることを確認する トの頭を使った循環リストによって表現し 頭から , 必要なバイト数より大きい空きプ のに使います。 magic には必ず MEM MAG ます。ヒープ領域は Fig. 4 のように管理され ロックが見つかるまて、スキャンします。そ IC という値がセットされているはずなの こて、は , ヒープ領域 ることになります。 して , 空き領域から必要な分だけ取り除い て、 , もしこの値が MEM MAGIC て、なけれ は三つのプロックに分割されています。左 て , 残りは再びリストに返します。 ば , そのプロックは allocate block が割り当 端のプロックは , 400 バイトの大きさて空き てたものてはないか , あるいはヘッダ情報 たとえば , Fig. 4 の状態て、 50 バイトの要求 プロックてす。中央のプロックは , 400 バイ を受け取ったら , 左端の 400 バイトの空きプ トの大きさて使用中てす。右端のプロック が壊れてしまっていることを意味します。 このアルゴリズムて、は , すべてのプロック ロックのうち , 先頭の 50 バイトを割り当て は 200 バイトの大きさて空いています。これ て残りの 350 バイトは再びリストに返しま がヒープの中にとられていることを前提と ら三つのプロックは , 双方向リストて、連結 す。しかし , あまりに小さいプロックしか しています。て、すから , ヒープ領域内にな されています。また , 図の上のほうにリス 残らない場合には , 残りの分もいっしょに こて、は , すべてのプ いプロックを渡されたり , ヘッダが壊れて トの頭があります。 割り当てたほうが , プロックの数も減り好 いたりすると致命的なのて、 , マジックナン ロックがアドレスの昇順にリストて連結さ 都合て、す。そこて、 , 要求されたプロックの ーを使ってチェックします。 れています。 大きさとみつかった空きプロックの大きさ メンバ occupied は , そのプロックが使用 このように双方向リストて、連結されてい の差が DELTA 以下だったら , プロックを分 中てあるか否かを示すものてす。 0 てなけれ ると空き領域の併合が簡単にて、きます。 Fi 割せずに少々のムダを承知て、丸ごと割り当 ばそのプロックは使用中 , 0 ならば空いてい g. 4 の状態て , 中央のプロックが解放された ててしまいます。実際問題として , List 1 を としましよう。このとき , 前後のプロック ることを表します。メンバ next と prev は , MS ー DOS マシンて、コンパイルするとヘッダ それぞれ前と後ろのプロックへのポインタ がともに空き状態て、あることが簡単にわか て、す。最後にメンバ body は , プロックの本 の大きさ HEADER SIZE は 10 になりますか ります。なぜなら , 双方向リストて、前後の ら , 10 バイト以下の空き領域は無意味にな 体を表しています。関数 allocate block は , 関係が , メモリ上ての物理的な位置関係を そのまま反映しているからてす。またプロ メンバ body を指すポインタを返します。 ります。 ックの併合もごく簡単にて、きます。 26 行目のマクロ WORD ALIGN は , パラ 11 行目のマクロ HEADER SIZE は , メン メータをワードサイズに切り上げるための バ body を除いたヘッダの大きさを表すマク リ管理のプログラム ものて、す。 29 行目の変数 block chain は , プ ロて、す。 15 行目のマクロ DELTA は , プロッ クの最小の大きさを定義するものて、す。プ ロックリストの頭てす。 32 ~ 33 行目て、定義 List 1 のプログラムをもとに説明していき メモリ管理 List 1 ましよう。このプログラムは三つの関数か ら成っています。関数 initialize memory typedef struct memblock { / * プロックのバイト単位の大きさ ( ヘッダを含む ) * / int size; は , 初期化を行うものて、す。ほかの関数を / * マジックナンバー * / unsigned char magic; unsigned char occupied; / * 1 ならこのプロックは使用中。 0 なら空いている。 * / 使う前に , 必ず 1 回だけ呼び出しておかなけ struct memblock *next; / * 次のプロックへのポインタ * / struct memblock *prev; / * 前のプロックへのポインタ * / ればなりません。関数 allocate block は指定 / * メモリプロックの本体 ( ダミー ) * / char bodyC1] ; した大きさのメモリプロックを割り当てま / * メモリプロックのヘッダの大きさ ( メンバ b y を除く ) 。 * / す。ライプラリ関数の malloc と同じ働きを ー sizeof(charC1])) (sizeof(struct memblock) #define HEADER_SIZE します。関数 free block は , allocate bloc / * 割り当てる大きさと見つかったプロックの大きさの差が DELTA 以下 k て、割り当てたメモリを解放するためもの だったら、プロックを分割せずに丸ごと割り当てる。 * / #define DELTA 10 て、 , ライプラリ関数の free に当たるものて、 / * マジックナンバー。 magic フィールドには常にこの値をセットしておく。 す。 プロックを解放するときに , プロックが allocate ー block で割り当てられたもの であることを確認するのに使う。 * / 1 ~ 8 行目は , プロックのヘッダを表す str #define MEM_MAGIC 0xa5 uct memblock 型の定義てす。メンバ size は / * ワードの大きさ ( バイト数 ) 。 * / ( ヘッダを含む ) プロックの大きさて、す。メ #define WORDSIZE 2 ンバ magic は , プロックを解放するときに渡 / * 大きさ n がワードの大きさ WORDSIZE の倍数になるように切り上げる。 されたプロックが , allocate block によって 1 りれ 0 4 0 6 7 8 9 0 1 人っ 00 4 戸 0 ^ 0 ー 8 0 ) 0 1- り 0 00 4 - -0 1 ↓ 1 亠 1 人 1 よ・ -1 1 人、ー一 11 1 人 14 つつなつ 00 りり 80 C MAGAZINE 1 2 4
Fig. 1 PC ー 9801 上での sc 「 0 Ⅲ exe の実行画面 0 H E しし 0 WO R し D サンプルプログラム (wtypew. tst) List 5 1 : #include ” config. h ” 3 : #define MYEXTERN 5 : #include く stdio. h 〉 6 : #include く string. h 〉 7 : #include く curses. h> 9 : #ifndef C5 ー 1 10 : #include く locale. h 〉 11 : #endif 13 : #include ” pldwn. h ” 15 : #ifdef PROTOTYPE 16 : #include ” cboxprot. 17 : #endif 18 : struct Gmnstr2{ char m0ji[15]; int x; int y; 23 : #define ENTER ' *n' 25 : void main ( ) 48 : 46 : 44 : 43 : 42 : 41 : 40 : 39 : 38 : 36 : 35 : 34 : 30 : 27 : 24 : 22 : 21 : 20 : 12 : 8 : 4 : 2 : h ” int opt, flpos , flmax, linemax,key 28 : char fIbuf[FILENUHMAX] [ 15 ] ・ 29 : char fInameC30] ; int count, i 31 : struct Gmnstr2 mn[FILENUMMAX] : scrollok(stdscr, TRUE) : keypad(stdscr, TRUE) ; mywin2 = newwin(17, 76 , 5 , 3 ) mywinl = newwin(10, 40 , initscr(); linemax = flmax / 4 ・ flmax = 64 ・ 33 : WINDOW * ⅵ n2 : 32 : WINDOW * ⅵ nl : FILENUMMAX は pldwn. h で定義 5 , 19 ) : noecho() ; raw(); 45 : #ifndef MSC5_1 s et 1 oca 1 e (LC—ALL, 47 : #endif 応用 C 言語 C の道具箱 いえ , まがりなりにも端末側て、マルチウィ ンドウが実現するわけて、ある。 道具箱に追加された関数 ーーウインドウの 1 行スクロール scroll ( ) 関数 ( CM920401 , List 1 ) #include #include [ 書式 ] curses. h #include く string. h > #include く stdlib. h > #include く stdiO. h > 'config. h" [ 機能 ] 正常終了の場合 0 を返す。 [ 戻り値 ] 格納する構造体のポインタ * pw ←ウインドウ関連のパラメータを [ 引数 ] scroll(WlNDOW * pw) #endif #include ' cboxprot. h" #ifdef PROTOTYPE 応用 C 言語 129 #include ” curses. h' #include く string. h > #include く stdlib. h > #include く stdiO. h > #include "config. h' [ 書式 ] ーースクロールのロック / 解除 sc 「訓0k ( ) 関数 ( CM920402 , List 2 ) ウインドウ pw を 1 行上にスクロールさせる。
1 : 3 : 10 : 11 : 12 : 13 : 14 : 15 : 17 : 18 : 19 : 20 : 21 : 22 : 23 : 26 : 28 : 2 : / * * マウス制御用の拡張ファンクションコールを集めた関数集 ( MOUSE. c ) List 2 16 : ) ; 149 : 150 : short m_color(short n) 151 152 : 153 : 154 : 155 : 156 : 157 : 158 : } 159 : union REGS regs ; regs. x. ax ニ 0X12 ; regs. X. bX = n; int86 ( 0X33 , ®s, ®s) ; return(OK) ; / * n = 0 : 青 ( 3 : 灰未使用 ) / * マウス表示画面の設定 MOUSE. H List 3 ワンポイント プログラミング 講座 しまっている。 なお , マウスに関するファンクションコ 用している。 グラムて、はこれをフラグとしても利 ソルの色を変えているのて、このプロ サプメニュー表示中は , マウスカー C010r マウスカーソルの色を示す。また , ールの詳細は TabIe 2,TabIe 3 をご覧くだ TabIe 3 使用したマウスファンクションの設定方法 4 : #define ON 5 : #define OFF 6 : #def i ne OK 7 : #def i ne NG 8 : #define YES 9 : #define NO S truc t Mouse { int rb, 1 b, 1 0 1 0 1 0 rpush, 1 push, rrel, lrel, ro 響 , C01 : short m_cursor (char *cursor data) : short m_creck ( struct Mouse (m) ; short m_read (S truct Mouse (m) : short m_locate(short x, short y) ; short mouse_disp(short (w) ; short init_mouse(void); / * ” true ” / * ” false ” / * 右ボタン , 左ボタンの状態 / * 右ボタン , 左ボタンの押下回数 / * 右ボタン , 左ボタンの解放回数 / * y , x 座標 / * 行列 / * マウスカーソルの形状設定 / * ボタンの押下情報の取得 / * カーソル位置の取得 / * カーソル位置の設定 / * マウスカーソルの表示 / 消去 / * マウスの使用可能チェック 24 : void m-micky(short hori, short vert); / * ミッキー / ドット比の設定 25 : void m_area(short xl, short yl, short x2, short (2) ; 27 : short m_color(short n) ; / * マウスの移動範囲の設定 / * 左上 ( xl , yl ) ~ 右下 ( x2 , y2 ) / * マウス表示画面の設定 TabIe 2 マウスドライバのファンクション一覧 機能 設定 戻り値 機能 設定 戻り値 ノ 機能 設定 戻り値 ァン 機能 設定 戻り値 機能コード 00H0 01H ◎ 02H ◎ 03H ◎ 04H ◎ 05H * 06H * 07H * 08H * 09H ◎ OBH OCH OFH * 1 OH * 1 1 H * 1 2 H ◎ 13H 05H : 左ハタンの押情報の取得 ソ 左ボタンの押下情報を取得します AX=Ox05 AX : 左ホタンの状態 0 : 離されている ー 1 : 押されている BX : 左ボタンが押された回数 CX : マウスカーソルの位置の水平座標 DX : マウスカーソルの位置の垂直座標 ノ 06H : 左ボタンの解放情報の取 左ボタンの解放情報を取得します AX = 0X06 AX : 左ボタンの状態 0 ・離されている ー 1 : 押されている BX : 左ボタンが離された回数 CX : マウスカーソルの位置の水平座標 DX : マウスカーソルの位置の垂直座標 7H . ボタノの下情取 ショ、 右ホタンの押下情報を取得します AX=Ox07 AX : 右ボタンの状態 0 : 離されている ー 1 : 押されている BX : 右ボタンが押された回数 CX : マウスカーソルの位置の水平座標 DX : マウスカーソルの位置の垂直座標 ショノ 08H . 右ボタンの解放情報取 右ホタンの解放情報を取得します AX = 0X08 AX : 右ボタンの状態 0 : 離されている ー 1 : 押されている BX : 右ボタンが離された回数 CX : マウスカーソルの位置の水平座標 DX : マウスカーソルの位置の垂直座標 窰 ファンクション名 環境のチェック カーソル表示 カーソル消去 カーソル位置の取得 カーソル位置の設定 左ホタンの押下情報の取得 左ボタンの解放情報の取得 右ボタンの押下情報の取得 右ボタンの解放情報の取得 カーソルの形の設定 マウスの移動距離の取得 ユーザ定義サプルーチンのコール条件の設定 ミッキー / ドット比の設定 水平方向のカーソル移動範囲の設定 垂直方向のカーソル移動範囲の設定 カーソルの表示画面の設定 グラフィック用 VRAM の 4 面目の設定 アノクション OFH : ニッキー・ツ比の設定 ◎印は今回使用したファンクションです * 印は今回追加した関数 , および使用したファンクションです 機能 設定 戻り値 アン 機能 設定 戻り値 フン 機能 設定 戻り値 マウスの移動距離とカーソルの移動距離の比を設定します AX = 0X0 F CX : 水平方向のミッキー / ドット比 DX : 垂直方向のミッキー / ドット比 なし ロの一ソ移動囲の設 ション 1 OH 、一 水平方向のカーソル移動範囲を設定します AX=Ox10 CX : 水平方向の移動範囲の最小値 DX : 水平方向の移動範囲の最大値 なし ション tH . 直方向のカーノル移動範囲の設定 垂直方向のカーソル移動範囲の設定 AX=Ox1 1 CX : 垂直方向の移動範囲の最小値 DX : 垂直方向の移動範囲の最大値 なし
List 6 応用 C 言語 C の道具箱 tabtospc( ) 関数 ( タブコードのスペースへの置き換え , CM920403 ) ” config. h ” 1 : #include 3 : #define MYEXTERN extern 5 : #include く stdio. h> 6 : #include く string. 8 : # i fde f PROTOTYP E 9 : #include ” cboxprot. h ” 10 : #endif 12 : tabtospc(ds, ss, tablen) 13 : char *ds 14 : Char *SS int tablen; 17 : i nt i , k, j, n ・ n=strlen(ss) fo で (i=0 ・ i く n ・ if (ssCi] ト dsCk)=ssCi); else{ for(j=0 ;j く tablen dsCk)= con t i nue dsCk]='*0' return( の : 34 : 33 : 32 : 31 : 30 : 28 : 22 : 20 : 15 : 11 : 4 : 2 : ログラムにバグがあり , ディレクトリ内の 前回紹介したディレクトリ制御関係のプ バグについてのお詫び #define SYSV #define UNIX ・ UNIX 用 config. h ox. a の指定てある。 , こてヾー lcbox クとは , ライプラリ libcb -lcurses -ltermcap ー 0 sample /usr/5bin/cc sample. c -g -lcbox オプションを指定する必要がある。 コンパイル ( あるいはリンク ) の際にリンク curses ライプラリとリンクする場合には , ar rv libcbox. a func. 0 /usr/5bin/cc func. c -c -g が必要て、ある。 類に応じてこれを EUC などに変換すること 漢字コードはシフト JIS なのて、 , マシンの種 付録ディスクに収録されているファイルの ファイル数が非常に多い場合や UNIX 上て起 動した場合に , 適切に動かないことがわか りました。今月号の付録ディスクにその修 正版を収録しましたのて、 , 前回のものと差 し換えてください [ 参考文献 ] [ 6 ] [ 2 ] [ 1 ] ログラム集」技術評論社 MELON. A. I. G 著「ファイル処理プ ング入門 [ 下 ] 』技術評論社 [ 5 ] 河西朝雄著「 Micr 。 s 。 ft 初級プログラミ サイエンス出版 浩訳「 UNIX システムプログラミング」 [ 4 ] K. ハヴィランド , B. サラマ共著 / 玉井 菊池彰訳「 CURSESJ 啓学出版 [ 3 ] ジョン・ストラング著 / 矢吹道郎監修 / xplainedl , Prentice Hall, 1991 Berny Goodheart, TIJNIX Curses E tice Hall, 1990 CURSES, LEX and YACC 』 , Pren Axel T. Schreiner, TUSING C with ・新刊案内 ( 定価は税込 ) Windows プログラマー 短期養成講座 オプジェクト指向 W i n d 0 w s プロクラミンク 中山茂著 / A5 ・ 480 頁・定価 3 , 605 円 Windows プログラミングは , メッセージ 誘導やイベント誘導の考え方を理解し , さらに 600 近くの Windnws 関数を覚えな けれはならぬなど , 簡単には乗リ越えら れない壁かある。本書は , 操作性のよい BorlandC + + を用い , 簡潔なプログラム を例題として , オつ・ジェクト指向・手続 き指向の差異も把握てきるよう工夫しな から , 短期間て容易にプログラミングが 習得てきるようまとめたテキスト。 裔日本語 Windows3 中山茂著 / A5 ・ 342 頁・定価 2 , 369 円 解説に対応した画面例 700 余を併載。操 作によリ実際の画面表示かどの様に変わ るか , 次にどのような操作をすればよい か , 実行手順か一目てわかるよう編集さ れた入門テキスト。付属の 13 種のアプリ ケーション・ソフト総てについても解説。 C ユーザー待望の解説書 ( ソースプログラム F D 別売 ) TurbO C + + オプジェクト指向 プロクラミンク入門 ー ANSI C, AT&T C + + Ver2.0 版ー 中山茂著 / A5 ・ 268 頁・定価 2 , 369 円 グレードアップされた C++ の基礎知識・ 基本操作 , 統合開発環境メニューはもと よリ , C + + の特徴てあるオプジェクト指 向プログラ三ングを自在に駆使てきるよ う , その基本的考え方から実技まてを平 易に解説 ( PC9801 シリース対応 ) 。 TurbO C, Turbo C + + クラフィックス プロクラミンク入門 —TurboC 2.0c, TurboC + + 1 0 版ー 中山茂著 / A5 ・ 278 頁・定価 2 , 369 円 プログラミングの基礎から , 基本操作 , 効果的グラフィックスを用いたシステム 構築 , 関数を学ぶための CAI の作成まご を習得てきる入門テキスト ( PC9801 シリ ーズ・ FMR シリース対応 ) 。 Borland C + + 技報堂出版 〒 107 東京都港区赤坂 1 ー 11 ー 41 容 03 ( 3585 ) 0166 FAX03 ( 3505 ) 5838 く資料請求番号 133 〉 応用 C 言語 133
応用 C 言語 C の道具箱 このスクロールの機能は , 場合によって はないほうがよいことがある。 UNIX 版 cur ses て、は , こういう場合に備えて , この機能 を一時的にロックする scrollok という関数が 用意されている。そこて、 MS-DOS 版 curses にも scrollok() 関数 (List 2 ) を追加した。 L ist 3 は , これらの関数を使用したサンプル プログラムてある。 サンプルプログラム ( List 3 ) を実行する と , まず Fig. 1 のように画面中央に、 \HEL LOWORLD ′′が表示される。そして何らか のキーを押すとその文字が上にスクロール する。しかし , 途中て scr 。 11 。 k ( ) 関数によ りスクロールがロックされ , スクロールが 停止する。 このふたつの関数を応用するとサプウィ ンドウ内にファイルを表示する関数を比較 的容易に作成することカイきる。 List 4 がそ のプログラムてある。 このプログラムて、は , 指定されたファイ ルからデータを 1 行ずつ読み取り , サプウィ ンドウにそれを表示し , この表示が最下行 にきた時点て scr 。 11 ( ) 関数を実行し , 全体を 1 行分スクロールさせている。 またこのままだと , 瞬く間に表示が終了 してしまうのて、 , 1 画面の表示が終わった段 階て、 getch ( ) 関数により , スクロールを停止 させている。 なお , プログラム中の tabtospc ( ) 関数 は , タブコードをスペースに置き換える関 数てある。 ファイル表示プログラム scroll( ) 関数 ,wtypew( ) 関数などを使用 して , ファイルを画面上て選択し , そのフ ァイルの内容を表示するサンプルプログラ ムを作成した ( List 5 ) 。 MS-DOS wtypew. exe を起動すると , ファイルの一 覧が表示される (Fig. 2 ) 。 カーソルキーを使用して , 特定のファイ ルをリバース表示にさせ , キーを押すと 応用 C 言語 127 List 1 linel ) ; atmemseg, atmemoff + linel*i movedata(spcseg, spcoff, cdmemseg, cdmemoff + 1 inel*(ylen return( の ; ー 8 9 0 1 宀 -4 -4 4 0 ′ 0 linel ) : scrollok( ) 関数 ( スクロールのロック / 解除 , CM920402 ) List 2 1 : #include ” config. h ” 2 : 3 : #define MYEXTERN extern 4 : 5 : #include く stdio. h> 6 : #include く stdlib. h 〉 7 : #include く string. h 〉 9 : #include ” curses. h ” 11 : #ifdef PROTOTYPE 12 : #include ” cboxprot. h ” 13 : #endif 14 : / * スクロールのロック / 解除 16 : scr0110k(WINDOW *pw, int flag) 17 : { if(flag = FALSE){ 18 : 19 : pw->scroll 20 : if(flag ー = TRUE & & pw- 〉 scroll = 21 : 22 : ー〉 scrol 1 23 : return( の : 24 : = の { サンプルプログラム (scroll.tst) 1 : #include ” config. h ” 2 : 3 : #define MYEXTERN 4 : 5 : #include く curses. h> 6 : 7 : #ifdef PROTOTYPE 8 : #include ” cboxprot. h ” 9 : #endif 10 : 11 : main() 12 : { WINDOW *mywin; initscr(); 14 : mywin = newwin(10, 40 , 5 , 1 の 15 : scrollok(mywin, TRUE) : 17 : mvwaddstr(mywin, 10 / 2 , 4 , ” wrefresh(mywin) : getch() ; 20 : scroll(mywin) : 22 : wrefresh(mywin) : 23 : getch() : 24 : scroll(mywin) ; 26 : wrefresh(mywin) : getch() : 28 : 29 : scroll(mywin) ; 30 : wrefresh(mywin) : 32 : getch() : 33 : 34 : 35 : List 3 W 0 R L D ” ) : H E L L 0
えるべきてはないてしようか。 あらためて 「定義」とは ? コンパイラにメモリ確保をさせる , う定義 (definition) の定義は , K & R 第二版や ANSI C の文面て、も同じて、す。 とい はずてす。 の , 大きさが S の , メモリ確保が行なわれる ト ) の定義があって初めて , 変数 var のため どこかに , 上のような変数 ( ~ オプジェク / * C 十十のシンタクス * / S var , / * C のシンタクス * / struct S var 教えている情報にすぎませんから。 この構造体の名前と形 ( ~ 大きさ ) を 確保は行なわれないはずてすよ。コンパイ グの宣言」といって , なんら物理的なメモリ ての常識ては , こういうものは「構造体のタ 造体 (struct) もクラスの一種 ) 。私のこれま (df4) は , クラスの宣言て、す ( C 十十ては構 (df4) (df5) の二つはどうてしようか ? M て「これは定義だ」とされていた Fig. 1 の せる文が定義て、ある , とすると , ては , AR 具体的・物理的に , メモリ確保を起こさ は , 定義である。 CANSI C 3.5 ] メモリの確保を起こさせるような宣言 タオプジェクト〕または関数のために て名付けられるオプジェクト〔 = デー と属性を指定する。その識別子によっ 宣言は , 一群の (a set (f) 識別子の解釈 ence ManuaI A8] を , 定義と呼ぶ。 [K&R 2nd ed. Refer しない。メモリを確保する宣言のこと 別子に結びつくメモリを必ずしも確保 れる解釈を指定する。宣言は , その識 宣言は , 各識別子〔 = 名前〕に与えら ります。 OOP が , 現実世界のモデリング機能を豪 語するのなら , こらのセマンティクス ( ひ いては合法と見なされるシンタクス ) は , 変 C 言語フォーラム 137 ARM が言うように , クラスの宣言 = 定義 ( = メモリ確保 ) てあるなら , コンパイラと いつものに関する私の従来の常識の一部を , 大きく変更しなければなりません。しかし , なんてタグ情報をメモリ上に持つ必要があ るのか ? そんな話 , これまて聞いたこと も読んだことも , ありまへんが・・・ 私の勉強不足か ? 誰か , 教えてくれえー 次の ( df5 ) は , 列挙型の宣言てす。 ARM 7.2 には , 列挙型は , 名前付き定数を実体とする , 独自の整数型である。 と書かれていまして , 定数てすから , その ためにメモリ確保が行われて , わざわざメ モリ参照をするなんてことは , どんな馬鹿 なコンパイラてもやんないてすよ。ぜった い。列挙型に関する私の従来の常識は , プ ログラムが , それが int てあることにとくに 依存していないならば , #define up 0 #define down 1 的には定数てあるのなら , 機械命令の定数 る値のフェッチをしていても , それが実質 いちいち , 式の評価や , メモリ参照によ するのは , 次の機会にします。 れまた面倒な話題なのて , const について云々 考察しなければならなくなりそうてす。 んど必然的に , const キーワードについても こんな話を始めると , C 十十の場合はほと からくつがえされます。 てあるのなら , これまた私の C 常識は , 根底 が宣言てあると同時に定義 ( = メモリ確保 ) enum {up, down} ; ARM が言うように 上に存在するようになるはずてす。 りうる , いわゆる列挙型変数としてメモリ p と down だけをその離散的な値域としてと と変数が定義されると , この変数 var は , u enum T var , のようにタグ名が付いて , enum T{up, down} , と , 機能的にはまったく同じはずてすよ。 オペランドに変更する , というのが , 最適 化技法のイロハのイだったはずてす。 それに , ARM の言うように , クラスの宣 言 = 定義てあるのなら , てはなぜ , その中 に書かれている static メンバだけが , 別途に 定義を要するのか , あまりにも ? ? な話じ ゃあーりませんか。 というより , そもそも , クラスの宣言 = 定義てあるとは , 物理的に , そして論理的 , どういう意味なのか ( 先の , 列挙型の宣 言 = 定義 (df5) もそう ) 。 推察するに , TurboC 十十を書いた時点 て、の処理系作家は , ARM の , クラスの宣言 = 定義説を鵜呑みにして , 、、別途定義が書かれ ていなくても "static メンバをメモリ上に実 装したのてしよう。そして BorIand C 十十て は , その、、間違い〃を修正したのてしよう。 とも , コンパイラのアセン フいったこ プラ出力を眺めてみれば , 具体的な事情は ある程度分かると思いますが , 今回はその 時間的余裕がありません。読者の方々から いろいろ教えていただければ , またこの欄 て、ご報告しようと思います。 00P ( オプジェクト指向プログラミング ) は , 面白いと私は思いますよ。コンピュー タブログラムが , 現実の世界 ~ 宇宙と感深い 仲クにならなければならなくなった , プログ ラミング言語 ~ ソースプログラムが , 現実 を記述しなければならなくなった , という 意味て , OOP は何か , 大きな「パンドラの箱」 を開けたと思いますね。現に , もうすてに ヾ継承クという機構の ( 現実表現能力の ) 限界 も指摘されています。 ANSI C 十十もまだ先のことのようてす し , われわれは , プログラミングが ーコロロ 人間の第二の言語 ( いわゆる自然言語よりは コミュニケーション能力がマシてあると期 待したい言語 ) として , 徐々に精錬されてい く様子を見守り , また可能なかぎりの発言 ・関与もしていきたいものてす。
アレゴ丿ズム・テータ構造入門 されている配列 memory heap がヒープ領域 て、す。 37 ~ 51 行目の関数 initialize memory は , ヒープ領域を初期化します。具体的には , 配列 memory heap をひとつの大きな空きプ ロックとしてプロックリストに登録してい ます。 関数 allocate block はパラメータ size て、与 えられる大きさを持っメモリプロックをヒ ープ領域から割り当てます。割り当てたプ ロックへのポインタを返しますが , 割り当 てに失敗すると NULL を返します。最初に 63 行目て、 , 実際に必要なバイト数を変数 nb ytes に求めます。これには , パラメータ siz e の値に , ヘッダの大きさ HEADER SIZE を 加えて , ワード単位に切り上げます。 67 行目の for ループて、プロックリストの先 頭から順に調べて , nbytes より大きい空き プロックを探します。もしそのような空き プロックが見つからなければ , 割り当ては 失敗なのて、 NULL を返します ( 102 行目 ) 。 空きプロックが見つかったら , その空き プロックの大きさから nbytes を引いた残り が , DELTA よりも大きいかどうかをチェッ クします ( 72 行目 ) 。もし大きければ , その プロックをふたつに分けます ( 77 ~ 90 行目 ) 。 そして , 後半を空きプロックとして残し , 前半の nbytes バイト分を割り当てたプロッ クとして返します ( 97 行目 ) 。このとき , プ ロックの先頭へのポインタを返すのてはな く , メンバ body へのポインタを返すことに 注意しましよう。また , 残りが DELTA 以下 だったら , そのプロックを丸ごと割り当て ます ( 94 行目 ) 。 関数 free block は , パラメータ block て、与 えられたプロックを解放します。渡される ポインタは , プロックの先頭を指している のてはなく , メンバ body を指しているはず てす。てすから , まず最初にプロックの先 頭を指すポインタを得る必要があります。 ヘッダの大きさは HEADER SIZE'* イトて すから , ポインタ block を char へのポインタ List 1 (((n) + WORDSIZE ー 1 ) & -WORDSIZE) #define WORD_ALIGN(n) / * プロックリスト。 struct memblock block_chain; / * ヒープ領域 * / #define HEAP_SIZE 10000 char memory—heapLHEAP_SIZE] ; / * プロックリストを初期化する。 ヒープ領域 memory ー heap を一つの空きプロックとして登録する。 void initialize memory() struct memblock *h; h = (struct memblock *)memory_heap; s izeof(block—chain) ; block chain. size block_chain. magic ニ MEM MAGIC ; block—chain. occupied = 1 ; block chain. next = block—chain. prev ニ h ; h- 〉 size ニ HEAP_SIZE; h- 〉 magic = MEM—MAGIC; h- 〉 occupied = 0 ; h->next ニ h->prev ニ &block—chain; / * 大きさ s ize のメモリプロックを割り当てる。 割り当てたメモリプロックへのポインタを返す。 もし , メモリが足らなくて割り当てに失敗したら NULL を返す。 * / void *allocate block(int size) struct memblock * 店 *s ; int nbytes ; / * ヘッダを含めて必要なバイト数を求める。 ワードの倍数になるようにする。 * / nbytes = WORD ALIGN(size + HEADER SIZE) ; / * プロックリストを調べて、 nbytes 以上の大きさをもつ 空きプロックを探す。 * / for (p = block—chain. next; p ! = &block—chain; P = p->next) { / * 見つかった。 * / if (!p- 〉 occupied & & p->size 〉 = nbytes) { / * このプロックから nbytes を切り出した残りは DELTA より大きいか ? * / if (p->size ー nbytes > DELTA) ( / * もし残りが DELTA より大きいなら、プロックの前半を割り り当てて、後半はプロックリストに残しておく。 * / / * 後半を独立したプロック s にする。 * / (struct memblock *)((char *)p + nbytes); S s->size = p- 〉 size ー nbytes; s->magic ニ MEM-MAGIC; s->occupied = 0 ; / * s を双方向リストに追加する。 * / p->next->prev s->next = p- 〉 next ; p->next s->prev ニ p; / * 前半の長さを調整して , 使用中のマークをつける。 * / p->size ニ nbytes; p->occupied ニ 1 : } else / * もし残りが DELTA よりも小さいなら、すべてを割り当てて しまう。 * / p->occupied ニ 1 ; CD っー 8 0 ・ 1 っ 0 っ 0 -4 ・ - -0 ^ 0 っーー 6 0 リ 0 11 りムっ 0 ・ 4- - -0 c.D 叮ー 8 0 1 よっ 00 4- 【 0 ^ 0 「ー 8 9 0 1 宀りっ 0 4 ′ 0 ー 8 0 リ 0 1 亠ワっ 0 4 ・ - -0 れ 0 「ー 8 0 1 ・つ 4 ・戸 0 ^ 0 っー 8 0 リ 0 1 よりム 00 -4 ・【 0 りムりっりなっ 0 00 っ 0 っ 0 00 《 0 っーっ 0 -4- 4 ・ 4 ・ 4 -4 414 ・ -4- 4 ・ 4 ・ - -0 【 0 戸 0 戸 0 戸 0 - -0 戸 0 - -0 -0 6 6 6 6 6 6 6 6 ^ 0 叮ー 7 ーっーワー叮ーワー 7 ーーっーっー 8 8 8 8 8 8 8 8 8 8 0 ) 0 ひ 0 リ アルゴリズムとデータ構造入門 81