break - みる会図書館


検索対象: 月刊 C MAGAZINE 1990年3月号
10件見つかりました。

1. 月刊 C MAGAZINE 1990年3月号

学 五ロ としてパラメータを取り出します。 % d て、は 符号を出力する必要がありますから , まず i が負かどうかを調べます。負のときには符 号を出力し , i を正にします。そして print digit を呼び出して , i を 10 進に変換します。 %u, %x, % 0 て、はどれも unsigned int と してパラメータを取り出し , それぞれ 10 進 , 16 進 , 8 進数に変換します。 % s 変換は文字列 ( c れ ar * ) がパラメータ て、す。取り出したポインタが表す文字列を while ループを使って出力します。 % c は文字 ( c れ ar ) の出力て、す。ここて、注意 が必要なのは , パラメータを int 型として取 り出していることて、す。 char 型のデータも パラメータとして渡されるときには , int 型 に拡張されます。そのため , va arg()p , char); とすると , char と int のバイト数だけポイン タがずれてきます。そうすると , それ以降 のパラメータを正しくアクセスて、きなくな ってしまいます。 % % のときには ' % ' を出力します。 format が % て、おわっていたときにも , 正 しく動作するようにしなければなりません。 case ' \ 0 ' に制御が移るのはこういう場合て、 す。このときには ' \ O ' を読んて、いない して , メインループの while 文に戻ります。 それ以外の文字が書かれていたときには , default の処理て、その文字を出力します。 最後に w れ ile ループを終了すると ,va end て、後始末をしておわりて、す。 おわりに C て、は , パラメータは値呼びて、しか渡され ません。そのため , 複数の値を返したいとき にはポインタを使用する必要があります。 ポインタを使ってもとの変数を書き換える ことはて、きますが , ポインタそのものは値 呼びて、渡されている点に注意してください List 4 0 printdigit(u, 1 6 ) ; break, case 0 va-arg(ap, unsigned int) : u printdigit(u, 8 ) : break; case S va-arg (ap, char * ) : wh i I e ( (c putchar(c) ; break; case 'C' va-arg(ap, int) : C putchar(c) : break; case ' % ' putchar('%') ; break; case ' \ 0 ' format- break; default: putchar('%') : putchar (c) : break; 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 戸 0 6 7 8 9 0 1 2 3 4 5 6 7 4 -4 4 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 7 } else putchar (c) : va-end(ap) ; うになっています。 処理に入ります。 % d 変換て、は , 対応するパラメータは int 型 mini printf て、は , まず ap を初期化するた のはずて、すから , めに va start を実行しています oformat を va arg()p , int); 先頭から調べていき , ' % ' を見つけると変換 [ 表 1 ] サポートする変換 パラメータを符号つき 10 進数として表示する パラメータを符号なし悧進数として表示する パラメータを符号なし 16 進数として表示する パラメータを符号なし 8 進数として表示する ノヾラメータを cha 「 * として取り出し , 文字列を表示する パラメータを文字として表示する %d %u %x % 0 %s %c C 言語雑学講座 131

2. 月刊 C MAGAZINE 1990年3月号

語 用 応 buzzer( プサー鳴動 ) 約 1 秒間ブザーを鳴らします。一般に , 工 ラーや警告メッセージとともに使用します (List7) 。 1 0 List y=atOi (work) : 105 : clear(y) : 106 : break : 107 : case 5 : 108 : clear(18); 109 : clear(19); 110 : csr-posit(), 18 ) : 111 : 112 : pr i ntf ( ”カーソルの右側を消しますっ : 113 : getxy (&x, (y) : 114 : printf ( " 消去したい行数 = " ) : 115 : gets (work) : 116 : cnt=ato i (work) : clr-right(x,y,cnt); 1 18 : break; 1 19 : case 6 : cIear(18); 120 : cIear(19); 121 : csr-posit(), 18 ) : 122 : pr i ntf ( " カーソルの左側を消します " ) : 123 : getxy(&x,&y) : 124 : printf ( " 消去したい行数 = " ) : 125 : 126 : gets (work) : cnt=ato i (work) : 127 : clr_left(), y,cnt) : 128 : 129 : break; 130 : case 7 : buzzer() : 131 : 132 : break; 133 : case 8 : cIear(18); 134 : put-str ( 0 , 18 , " 1 桁目なら 0 k 。確認 ! " , 22 ) : 135 : csr-posit(), 19 ) : 136 : csr-fwd() : 137 : 138 : break; 139 : case 9 : cIear(18); 140 : put-str ( 0 , 18. ” 0 桁目なら 0 k 。確認 ! " , 22 ) : 141 : csr-posit(1,19); 142 : csr-back ( ) : 143 : 144 : break : 145 : case 10 : cIear(18); 146 : put - str ( 0 , 18 , " この行なら 0 ko 確認 ! ル , 22 ) : 147 : 148 : csr-posit(), 19 ) : csr-up() : 149 : 150 : break : case 11 : cIear(18); 152 : put - str ( 0.18 げ 1 行飛びなら 0 ko 確認 ! " , 24 ) : 153 : csr-posit(), 19 ) : 154 : csr-down ( ) : 155 : 156 : break : / * 終了 * / 157 : case 99 : 158 : return; 159 : getchar ( ) : 160 : 161 : goto menu : 162 : } 163 : 164. ・ / * getxy 165 : 166 : getxy(int *x. int *Y) VO i d 168 : Char work [ 20 ] : 169 : 170 : clear(2 の : 171 : csr-posit(), 2 の : 172 : pr i ntf ( " X 座標 ( 0 ~ 7 9 ) = 173 : gets (work) : *x=atoi (work) : 174 : pr i ntf ( " Y 座標 ( 0 ~ 2 4 ) = 175 : gets (work) : 176 : *y=atoi (work) : 177 : 178 : return; csr fwd/csr back/csr up/csr down ( カーソル移動右 / 左 / 上 / 下 ) カーソルを 1 桁右へ ( 左へ / 上へ / 下へ ) 移動 します。ラインエデイタやスクリーンエデ イタを作成するときにカーソル制御用とし て使用します (List8)0 c 。 lo 「 ( 表示属性 / 表示色指定 ) 呼び出し後に表示する文字の「属性」と「表 示色」を指定します。指定パラメータは表 3 のとおりて、す。 必ず属性と表示色を指定してください 属性や表示色を変える場合には , また呼び 出してください なお , この ESC シーケンスは , 属性のみ , 表示色のみという指定がて、きます。目的に 応じて , どちらか一方のみの関数も作成し てください (List9) 。 関数の使用例 関数の使用例は , サンプルプログラムの main 関数をご覧ください。それぞれのテス トが使用例になっています (List10)0 宣言文が書かれています。必要な 定義文 , 関数だけを抜き出して使われる場合には , この部分も忘れないようにしてください また , 前回まて、作成してきたデータベー スアクセスプログラムの表示部分ゆ rintf 関 数 ) を上の関数を使って書き換えると , カー ド型データベースふうの表示がて、きます。 次回は , 今回の関数を利用して , 挿入 / 削 除機能つきのキーポード入力関数を作成す る予定てす。 応用 c 言語 103

3. 月刊 C MAGAZINE 1990年3月号

ウインドウがレポートすべきコマンドを もっているとき , またはキーストロークが アクセラレータによって WM COMMAND List 2 188 : 189 : 190 : 191 : 192 : 193 : 194 : 195 : 196 : 197 : 198 : 199 : 200 : 201 : 202 : 203 : 204 : 205 : 206 : 207 : 208 : 209 : 210 : 212 : 213 : 214 : 215 : 216 : 217 : 218 : 219 : 220 : 221 : 222 : 223 : 224 : 225 : 、 226 : 227 : 228 : 229 : 230 : 231 : 232 : 233 : 234 : 235 : 236 : 237 : PWO RK CHAR PSW P SHO RT P : Buffer[2) : pswp; dx, dy; メッセージに変換されたときに このメッ セージが出ます。このプログラムの場合 , メニューをマウスて、クリックすると出ます。 以下の処理を行います。 フレームコントロールウインドウにウィ owText( ) て、子ウインドウのタイトルバー ・実処理開始のサインとして ,WinSetWind り送られてくることになります。 るために WM PAINT メッセージが PM よ り , クライアントウインドウを再描画す インドウを更新領域とします。これによ ・ WinInvalidateRect( ) て、クライアントウ ンドウ番号も表示します。 説明します。ローカルデータ領域のウィ ・メッセージボックスて、オペレーションを ウは回転中 ) , 以降は何もしません。 ・タイマがセットされていれば ( 子ウインド をローカルデータ領域にセットします。 ドウ ( 子フレームウインドウ ) のハンドル ・ WinQueryWindow( ) て取得した親ウイン はすて、に始まっている ) をセットします。 SetWindowUShort( ) て、 TRUE ( 実処理 ・予約メモリ内の実処理開始フラグに Win て、はない ) , 何もせずに抜けます。 ・コマンドが正しくない場合 ( IDD START 処理に入れない ) 。 して , 不成功なら何もせずに抜けます ( 実 ・ローカルデータ領域のポインタを読み出 子ウインドウのクライアント領域て、第一 WM BUTTONI DBLCLK す。 実処理開始 ( IDI ICON2) に差し替えま ・実処理開始のサインとして , ンドウ番号を表示します。 アイコンを こにこのメッセージが出ます。以下の処理 マウスポタンをダブルクリックすると , を行います。 54 CMAGAZINE 19N 3 ・ローカルデータ領域のタイマフラグがオ なら何もせずに抜けます。 実処理開始フラグを読み出して , 不成功 ・ローカルデータ領域のポインタ , および switch (nsg) { case WM_PAINT: if ( ! (WinQueryWindowUShort(hwnd, QW し _USER_USHORT))) { hps = WinBeginPaint (hwnd. NU しし NU しし ) : GpiErase(hps) : WinEndPaint(hps) : break : if ( ! (p = WinQueryWindowPtr(hwnd. QW し _USBR))) break; hps = WinBeginPaint(hwnd, NU しし NU しい : GpiErase(hps) : WinQueryWindowRect(hwnd, &rcl) : WinDrawText( hps, p- 〉 pszText, &rcl, C し R_NEUTRAL, C し R_BACKGROUND. DT_CENTER ー DT_VCENTER ー DT_ERASERECT) : GpiCharStringAt( hps, &p->ptl, ( し ONG) (sizeof ” Timer つ "Tiner つ : GpiCharString( hps. ( し 0NG)sprintf( Buffer, p->timer), Buffer) : WinEndPaint(hps) : break : case WM_COMMAND: = WinQueryWindowPtr(hwnd. QWL_USER))) break,• switch (COMMANDMSG (åmsg) づ c ) { case IDD_START: if (!WinSetWindowUShort(hwnd. QW し _USER_USHORT. TRUE)) break; p->hwndFrame : WinQueryWi ndow(hwnd. QW_PARENT. PA し (E) : if (!p->timer) { WinMessageBox( HWND_DESKTOP. hwndMain. "PIease doubleclick the left mousebutton on the ciient windo 町 then this window begins 「 0 Ⅱ ling. "lf you want tO stop 「 0 Ⅱ ing, you may do this operations onc p- 〉 pszText. 0. MB_OK ー MB_APP し MODA し一 MB_ICONEXC し AMATION) : WinQueryWindowRect(hwnd. &rc l) : WinInvalidateRect(hwnd. &rcl, FALSE) : WinSetWindowText(p->hwndFrame, p->pszText) : WinSendMsg( p->hwndFrame, WM_SETICON, Win し oadPointer( HWND_DESKTOP. hmodDll . ー田」 CON2), NU しし ) : e 第 0 に e again. 238 : 239 : 240 : 24 に 242 : 243 : 244 : 245 : 246 : 247 : 248 : 249 : 250 : 251 : 252 : 253 : 254 : 255 : 256 : 257 : 258 : 259 : 260 : 261 : 262 : 263 : 264 : 265 : 266 : 267 : 268 : 269 : 270 : 271 : 272 : 273 : 274 : 275 : 279 : 278 : 277 : 276 : break; if (p->timer = if ( ! (p = WinQueryWindowPtr(hwnd, QW し _USER))) break: if ( ! (WinQueryWindowUShort(hwnd. QWL_USER_USHORT))) break; case WM-BUTTONIDB し C し K : WinSendMsg( FA し SE), QW_PARENT, hwnd, WinQueryWindow( WinQueryWindowPos( INTERVA い : p->timerID, hwnd, habMain, WinStartTimer ( NU しい : ー田」 CON3 ) . hmodDll, HWND_DESKTOP. Win し oadPointer( WM_SETICON, p->hwndFrame,

4. 月刊 C MAGAZINE 1990年3月号

Tab 5 List 5 35 : public: 34 : c lass i nthashtab : hashtab 36 : 38 : 39 : 40 : 42 : 43 : 44 : 45 : 46 : 49 : 52 : 56 : 58 : 60 : 62 : 64 : 66 : 69 : 90 : 100 : 101 : 102 : 103 : } inthashtab (s i ze_t s i ze) int *lookup(int x) { return (int *)hashtab: : lookup((void *)&x) : VOid insert(int x) { int *ip new i nt; (size, imap. icompare) VOid remove(int x) { hashtab: : insert ((void * ) (p) : / / 記億してあるポインタを得て , オプジェクトを削除する int *ip (int *)hashtab: : lookup((void *)&x) : i f ( i p ! = NU しし ) { hashtab : : remove ( ()o id * ) i p) : delete ip; 54 : #if defined(DEBUG_HÅSHTAB) void dump-tab(void) { hashtab: :dump-tab(idisplay) : #endif inthashtab inttab(4) : 63 : m a i n ( ) { Char command; int *current,• i nt i : while(!cin. eof()) { / / プロンプトとコマンド入力 cout くく” i insert ー lookup d = delete = NU しし ? ” i sn ・ t ” (current くく cout くく i くく current inttab. lookup(i) : C i n 〉 > i : / / 整数を入力 case ' 1 ・ break : inserted. cout くく i くく i nttab. insert (i) : C i n > > i : 〃整数を入力 swi tch (tolower (command) ) { / / コマンドにしたがって動作 cin. get(conmand) : eatwhite(cin); S ShOW table q = qu i t Ⅷ the table" ・ break : case 'd ・ / / 整数を入力 C i n > 〉 i : i nttab. remove (i) : cout くく i くく” deleted" break; case q exit( の : 95 : #if defined(DEBUG-HASHTAB) & & defined(__ZTC__) i nttab. dump-tab ( ) : break: 99 : #endif cout. put( ・・ ) : CMAGAZINE 19N 3 tab 変数を使用することがて、きる。 C 十十は , 汚いインプリメントの細部をう まく隠し , 一般的て、再使用可能なデータ型 を開発することを可能にする。確かに , C 十十 は純粋な意味て、のオプジェクト指向言語て、 はないのて、 , すべてを隠すことはて、きない が , しかし , このことは深刻な問題にはな らない。なぜなら , 私たちの世界において も決して純粋なものはなく , C 十十の混在し た性質は純粋なオプジェクト指向言語に比 べて , この実状に合うからて、ある。 Smalltalk のような純粋なオプジェクト指向言語て、は どうすることもて、きない低水準の作業を行 ことも , たまにはよいて、はないか。 フ プレント法は特定のアプリケーションに とてもよく合う。ツールポックスに汎用 hash クラスをもっているのて、 , LOOKUP に関し て 1 次元的検索を用いる理由はないのて、あ 文献 [ 1 ] Kunuth,Donald,E. ,The art of com puter programming,VoI. 3:Sorting and Serching. Reading,Mass. :Addison- WesIey , 1973. [ 2 ] Stroustrup,Bjarne,The C 十十 pro gramming Language,Reading,Mass. : Addison-Wesley,1986. なお翻訳にあたって以下の文献を参考に 門内淳 , 赤堀一郎℃十十プログラミング』 日本ソフトバンク , 1989 年 Kent WiIIiams 氏はアイオワ州の Omega Microconsulting 社の隠れた功労者。 8 インチ フロッヒ。ー全盛時代からマイコンのプログ ラミングや著述活動を行っている。 28

5. 月刊 C MAGAZINE 1990年3月号

List 2 タイマをセットしたことによりこのメッ 280 : 281 : 282 : 283 : 284 : 285 : 286 : 287 : 288 : 289 : 290 : 291 : 292 : 293 : 294 : 295 : 296 : 297 : 298 : 299 : 300 : 301 : 302 : 303 : 304 : 305 : 306 : 307 : 308 : 309 : 310 : 311 : 312 : 313 : 引 4 : 315 : 316 : 317 : 318 : 319 : 320 : 321 : 322 : 323 : 324 : 325 : 326 : 327 : 328 : } 329 : W inStopTimer(habMain, hwnd, W inSetW indowPos( p- 〉 hwndFrame, P->SWP. hwndlnsertBehind, p—〉 swp. X, p->swp. y, P->swp. cx, p->swp. cy, W inSendMsg( p- 〉 hwndFrane. WM_SETICON. Win し oadPointer( HWND_DESKTOP, hmodD11, ー田」 CON4 ) . NU しい : break : case WM_T IMER: pswp = &swpMain: if ( ! (WinQueryWindowUShort(hwnd, p->tinerID): QW し _USER_USHORT))) break,• 00 最新ー入門 転します ) 。 WM CLOSE ユーザがシステムメニューから「クローズ」 を選択するとこのメッセージが出ます。親 ウインドウ ( フレームウインドウ ) に WinDes troyWindow( ) て、 WM DESTROY を送り return 0 をすることによって , プログラムを 終「せずに子ウインドウだけを終了させま す。 ( 千葉哲也 ) if ( ! (p = W inQueryWindowPtr(hwnd, QW し _USER))) break: if (SHORTlPROMMP(mpl) = p->timerID) { p->Y0ffset = dy * (p->flag / 2 ) : if ( + + p つ f ね g 〉 3 ) p->flag = 0 : p->X0ffset = dx * (p->flag / 2 ) : = pswp->cy / YDIVISION; ニ pswp- 〉 cx / XDIVISION; return 0 : FA し (E)) : QW_PARENT, hwnd, WinQueryWindow( WinDestroyWindow( case WM_C し OSE: break; HWND_TOP, p- 〉 hwndFrame, WinSetW indowPos( SWP_ACTIVATE ー SWP_MOVE ー SWP_SIZE ー SWP_SHOW) : pswp->y 十 dy * p->yposition 十 p- 〉 yoffset, pswp->X 十 dx * p->xposition 十 p->xoffset. return WinDefWindowProc(hwnd. 叩 1 , 叩 2 ) : フの場合は WinStartTimer( ) て、タイマを して , アイコンを静止中 (IDI ICON4) に レームウインドウ ) のサイズと位置を復旧 て、タイマをリセットして , ウインドウ ( フ フラグがオンの場合は WinStopTimer( ) ICON3) に差し替えて終わります。タイマ 位置を保存して , アイコンを回転中 (IDI ンドウ ( フレームウインドウ ) のサイズと セットして , ローカルデータ領域にウィ •WM TIMER 差し替えて終わります。 セージが出ます。ローカルデータ領域のポ インタ , および実処理開始フラグを読み出 して , 不成功なら何もせずに抜けます。タ イマメッセージのパラメータて、あるタイマ ID とローカルデータ領域のタイマ ID とを比 べて , 自分のタイマメッセージて、なければ 以降は何もしません。自分のタイマメッセ ージてあればローカルデータ領域の情報に 基づいてウインドウを回転させます ( ウイン ドウ番号 NO. 1 は左下て , NO. 2 は右上て回 おわりに 以上「開発環境について」 , 「 PM プログ ラムの基本」 , 「開発の実際」と 3 部にわたっ て説明してきました。なにぶん Presentation Manager は新しいシステムのため , まだ十 分に評価したとはいえず , 標準とて、もいう べき形も , いまだっかめてはいません。手 探りの中て、マニュアルを頼りに開発を進め てまいりましたのて、 , 不明瞭な解説や勘違 いやイリーガルな手法などご指摘を受けな ければならない点があるかと思います。 のサンプルプログラムに関しても , あくま て、も可能性のひとっとしてとらえていただ ければ幸いて、す。 参考文献 ( 1 ) 「日本語 MS OS / 2V1.1 マニュアル』株 富士ソフトウェア株教育出版部 ( 3 ) 「 OS / 2 プレゼンテーションマネージャー』 ー 4 』株アスキー ( 2 ) fMicrorsoft Systems JournaI V01. 1 富士通 , 株日本電気 List 3 smp 「 . C IDD_START List 4 1 : NAME 8 : 2 : smp. def SMP WINDOWA 円 く 0S2. h> snp. h" IDM_RESOURCE { HENUITEH "Start", #include 2 : #include 4 : MENU 5 : 3 : 1 : 3 : DESCRIPTION ・ Presentation Manager Sanple p 「 og 「 a Symphony, 1989 ・ 4 : PROTMODE 5 : HEAPSIZE 1024 6 : STACKSIZE 8 192 7 : EXPORTS MainClientWndProc ChildClientWndProc 特集最新 OS / 2 入門 55

6. 月刊 C MAGAZINE 1990年3月号

特集 List 2 95 : 96 : 98 : 99 : 100 : 101 : 102 : 103 : 104 : 105 : 106 : 107 : 108 : 109 : 1 1 L: 112 : 1 13 : 114 : 1 15 : 116 : 1 18 : 】 20 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : ロ 0 : 1 引 : 】 32 : ロ 3 : 134 : 135 : 136 : 137 : 138 : 139 : 140 : 141 : 142 : 143 : 144 : 145 : 146 : 147 : 148 : 149 : 150 : 151 : 152 : 153 : 154 : 155 : 156 : 157 : 158 : 159 : 160 : 161 : 162 : } 163 : 166 : 167 : 168 : 169 : 170 : 171 : 172 : 173 : 174 : 175 : 176 : 177 : 178 : 179 : 180 : 181 : 182 : } 183 : 184 : 186 : NU しし IDM_RESOURCE, &hwndCIientl) : hwndFrame2 : WinCreateStdWindow( i f hwndMain, WS_VISI B い . &flChildFIags, szChildClass, NU しし IDM_RESOURCE. &hwndClient2) : (hwndFrane ! : NU しし & & hwndFramel ! : NU しし & & hwndFrame2 HWND_DESKTOP. Win し oadPointer( WM_SETICON. hwndFrame2, WinSendMsg( NUL い : に ICONI ) . h 田 od 田 l, HWND_DESKTOP, W i n し oad Po i n い r ( WM_SETI CON. hwndFramel. WinSendMsg( return 1 : 朋ー OK ー MB_APP し MODA し 0. NU しし "Cannot find WND8D しし . D しし library. hwndFrame, HWND_DESKTOP, WinMessageBox( if (Dos し oadModuIe ( N 乢し . 0. ー MB_ICONEXC し AMATION) : "SMPD しし "・ &hmodDl l)) { SWP_SIZE ー SWP_MOVE) : 180. 240. 20. 600. NU しし hwndFrame2, WinSetWindowPos( SWP_SIZE ー SWP_MOVE) : 180. 240. 20. 20. NU しし hwndFramel, WinSetWindowPos( NU しい : に ONI) . hmodDl l. ニ NULL) if (!WinSetWindowPtr(hwndClientl, QW し _USER. (PV01D)&wl)) return 1 : if ( ! HinSetWindowUShort (hwndClientl. QW し _USER-USHORT. FA し (E) ) return 1 : if (!WinSetWindowPtr(hwndClient2. QW し _USER. (PVOID)&w2)) return 1 : if (!WinSetWindowUShort (hwndClient2. QWL_USER-USHORT. FA し (E)) return 1 : while (WinGetMsg(habMain, &qnsg. NU しし 0. の ) WinDestroyWindow(hwndFrane) : WinDispatchMsg(habMain. &qmsg) : return 0 : WinTerminate(habMain) : WinDestroyMsgQueue(hmq) : 164 : HRESU し T EXPENTRY MainClientWndProc(H\ND hwnd, break : DosFreeModule(hmodDll) : case WM_DESTROY: break : WinEndPaint(hps) : GpiErase(hps) : hps = WinBeginPaint(hwnd. NU しし NUL い : case WM_PAINT: break : WinQueryNindowPos (hwnd. &swphain) : case WM_SIZE: switch (msg) { HPS hps : USHORT ” g. HPÅRAH 叩 1. MPARAM 叩 2 ) dPaint( ) て、このメッセージの処理が終わる まて、解放します。この処理は , WM PAINT メッセージの処理て、はいちばん基本的なも のて、す。 WM DESTROY ウインドウが破壊されるときにこのメッ セージが出ます。 DosFreeModuIe( ) て、起 動時にロードしたアイコンリソースを解放 します。 上記以外のメッセージは WinDefWindow Proc( ) に渡してシステムに任せます。 く子ウインドウ関数 > こが実際にいろいろな処理を行ってい るところて、す。子ウインドウに対して送ら れたメッセージを処理します。各メッセー ジごとに説明します。 当 WM PAINT すて、にメニューがクリックされたか ( 実処 理が始まったか ) どうかのフラグとして用意 した予約メモリ内の unsigned short (QWL USER USHORT) を WinQuery WindowUShort ( ) て、読み出し , FALSE ( 実処理はまだ始まっていない ) ならばウィ ンドウのクリアをするだけて抜けます。 TRUE ( 実処理はすて、に始まっている ) ならば以下 の処理を行います。 ・ WinQueryWindowPtr( ) て予約メモリよ り口一カルデータ領域のポインタを読み 出します。 ・ウインドウをクリアします。 ・ WinQueryWindowRect( ) て、クライアン トウインドウの大きさを取得します。 ・ WinDrawText( ) て、ローカルデータ領域 の pszText ( ウインドウ番号 ) をクライアン トウインドウの中央に描画します。 ・ GpiCharStringAt( ) , GpiCharStr ing( ) て、ローカルデータ領域の timer の値 ( タイマがセットされているかどうかのフ ラグ 0 : OFF 1 : ON 初期値は 0 ) を , クライアントウインドウの左下に表示し return NinDefWindowProc(hwnd. g. npl. np2) : RECT し HPS hps : MRBSULT EXPENTRY ChildClientWndProc(HWND hwnd. USHORT nsg. hPARÅh 叩 1. HPA RAM 叩 2 ) ます。 ・キャッシュプレセ。ンテーションスペー を解放します。 、 WM COMMAND 特集 最新 OS / 2 入門 ス 53

7. 月刊 C MAGAZINE 1990年3月号

va list ap; VOid va start()a list ap, rightparm); type va arg()a list ap, type); VOid va end()a list ap); va list はパラメータの位置を覚えておく ために使用する変数の型て、す。 va start は va list 型変数を初期化するために使いま 〃の直前に宣言さ す。 rightparm には れているパラメータを与えます。 printf の 場合は format て、す ova arg はパラメータを 取り出すためのマクロて、す。 type には取り 出したいデータの型を書きます。最後の va end は va start と対をなす後処理のためのマ クロて、す。 これらが実際にどのように実現されてい るかを調べてみるのも勉強になるて、しよう。 ただし , TurboC の (ap= .. ) というのは反 則技だと思います。 ANSI 規格て、は、、 にこんな意味をもたせてはいないはずて、す。 mini—printf それて、は , 実際に mini printf のプログラ ム (List4) を見ながら説明していきましょ mini printf がサポートしている変換仕様 を表 1 に示します。この表からもわかるよう に , long や double などの変換はて、きません し , % 3d のような出力幅の指定などもありま せん。 List4 て、はヘッダファイル stdio. h をインク ルードしていますが , これは 1 文字の出力関 数として putchar を使うためて、す。それ以外 のライプラリ関数は使用していません。ま stdarg. h のインクルードによって初め て va ・・・マクロが使えるようになります。 printdigit は数値データを文字列に変換 して出力します。データは符号なしの整数 u て、与えます。 radix は基数のことて、 , 10 進 数に変換するときには 10 を , 16 進数にした ければ 16 を与えます。この関数は自分自身 を再帰的に呼び出すことによって上位の桁 を出力し , それから下位の桁を出力するよ 130 CMAGAZINE 19 3 mprf. c List 4 ・ 1 cd 0 0 1 2 3 4 5 6 7 8 9 1 2 3 -4 5 6 7 8 9 0 一 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 -4 5 6 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 -4 -4 -4 -4 4 -4 -4 mini-printf ー最低機能しかない printf printdigit(unsigned int u, int radix) 1 Cd ・ー 1 0 cd mini-printf(char *format, Char int uns igned int Char va_l ist va-start (ap, format) : while ()c = *format 十 + ) ! = i f (c = switch (c = *format + + ) { case va-arg(ap, int) : 1 if (i くの { putchar(' 1 printdigit(i break; case 'u va-arg(ap, unsigned int) ; u printdigit(), 1 の : break; case X , 1 の : va-arg(ap, unsigned int) :

8. 月刊 C MAGAZINE 1990年3月号

パラメータをセットした後て、 , printf 関 数て、出力しています。「 % 」に続く「 .4 」は精度 指定子て、 4 文字出力の意味て、す。「 s 」は変数 param の文字列出力て、あることを示しま す。 ライプラリが画面上に文字を表示する場 合や文字を入力する場合 , カーソル位置か ら表示 , あるいはカーソル位置て、入力する ようになっています (ListI) 。 put st 「 ( 文字列表示 ) 任意の場所に文字列を表示します。内部 て、 , csr posit 関数を呼び出しています。 printf 関数の「 % 」に続く「 * 」は , 表示する文 字数を引数 (cnt) て、渡すことを示しています 40 : / * 37 : VOid 36 : VOid VOid VOid VOid VOid 31 : VOid VOid 1 0 List 30 : 32 : 33 : 34 : 35 : 38 : 39 : 41 : 42 : 43 : { 44 : 45 : 47 : 50 : 52 : 54 : 56 : 59 : 63 : 70 : 77 : 86 : 92 : 93 : 98 : 100 : 101 : 102 : 103 : 104 : clr_right(int x,int y,int cnt); clr_left(int x,int y, int cnt); -fwd(void) : back ()o (d) : -up(void): down(void) : CSr_ CSr CSr_ CSr color (char *attr, char * c 引 0 に no ) : buzzer(void) : int main() str[60], work [ 20 ] . chr; Char int workno,x, y. cnt; menu: cls(); COIor(REV, SKY) : put - str ( 33 , 2. " 画面関数テスト " , 14 ) : c010r(0RG, WHITE) : csr-posit(), 5 ) : (List2) 。 put chr(l 文字表示 ) 部て、 csr posit 関数を呼び出しています。全 任意の場所に半角 1 文字を表示します。内 clea 「 ( 1 行消去 ) 用します (List4) 。 一般に起動直後 , 画面切り替えなどに使 します。 ソルは , ホームボジション ( 左上端 ) に位置 テキスト画面を全画面消去します。 cls ( 全画面消去 ) 角文字には対応していません (List3) 。 カー データだけを表示する場合 ( あるいは , その す。また , 左側に見出しを残しておいて , 一般に文字列表示を行う前に呼び出しま します。 カーソル位置から右側 ( 左側 ) を n 行分消去 ( カーソル右側 / カーソル左側消去 ) clr right/clr left す (List5) 。 一般に文字列表示を行う前に呼び出しま posit 関数を呼び出しています。 任意の 1 行を消去します。これも内部て、 csr CMAGAZINE 19 3 逆 ) にも使用て、きます (List6)0 102 printf()l : 文字列表示 \ n " ) : printf()2 : 1 文字表示 \ n " ) : printf()3 : 全画面消去 \ n " ) : printf( ” 4 : 1 行消去 \ n " ) : printf()9 : カーソル左移動 \ n " ) : pr i ntf ( " 8 : カーソル右移動 \ n" ) : printf()7 : ブザー鳴動 \ n " ) : printf()6 : カーソル左側消去 \ n " ) : printf()5 : カーソル右側消去 \ n " ) : printf()9 9 : 終了 \ n " ) : printf()1 1 : カーソル下移動 \ n " ) : printf()1 0 : カーソル上移動 \ n " ) : csr-posit(), 19 ) : clear(19); clear(18); case 4 : break : cls(); case 3 : break : put-chr(), Y, str[0]) : cls(); getxy (&x. (Y) : gets(str) : printf ( ”表示したい文字 = つ : csr-posit(), 18 ) : cIear(19): cIear(18); case 2 : break; put-str(x,y,str, cnt) : cls(): getxy (&x, (Y) : cnt=strlen(str) : gets (str) : printf(" 表示したい文字列 = csr-posit(). 18 ) : clear(19); cIear(18); case 1 : switch (workno) workno=atoi (str) : gets (str) : coIor(0RG, WHITE) : printf(" 処理番号 = " ) : csr-posit ( 0 , 19 ) : pr i ntf ( " 処理番号を指定してください。 Yn") : csr-posit(). 18 ) : coIor(0RG, SKY) : gets (work) : pr i ntf ( " 消去したい行番号 ( 0 ~ 2 4 )

9. 月刊 C MAGAZINE 1990年3月号

三田典玄の 実践 C プログラマ VOid 引数 , 戻り値はない #include 〃 keyint. h" 0 ds,ax Reset98StopAndCopyKey( ) ; LiSt 2 112 : } 1 10 : 109 : 108 : 107 : 106 : 105 : 104 : 103 : 102 : 101 : 100 : 98 : 97 : 96 : 94 : 93 : 92 : 89 : 88 : 86 : 85 : 養成講座 第 0 回 C 言語とシステムエンジニアリング = INT_COPY; inpreg. h. al = o-cpy-seg; / * Restore interrupt vector for COPY * / segreg. ds inpreg. X. dx = o-cpy-off; (void) int86x(INT_DOS, &i 叩 reg. &outreg, &segreg) : segread(&segreg) : inpreg. h. ah = SET_INT; inpreg. h. 引 = INT-STOP; = o-stp-seg: / * Restore interrupt vector for STOP * / seg reg. ds inpreg. x. dx = o-stp-off; ()O (d) int86x (INT-DOS, &inpreg, &outreg. &segreg) : Set98StopAndCopyKey( ) 関数て、 無効になったキーと一 キーの本来の機能を復活させ , Set98 StopAndCopyKey( ) が呼ばれる前 の状態に戻す。 引数 , 戻り値はない #include 〃 keyint.h& main() VOid Set98StopAndCopyKey ( ) : if(HIT_STOP) printf("STOPYn") : if(HIT_COPY) printf("COPYYn") : i f (kbh i t ( ) ) break; Reset98StopAndCopyKey ( ) : BOOL H 工 T STOP List 3 Set98StopAndCopyKey( ) 関数を 呼んだ後 , このマクロの値を確かめ ることによって , キーが押 されたかどうかを確かめることがて、 きる。 0 #include 〃 keyint. h" て、きない される。このマクロへの値の代入は HIT_STOP の値は FALSE にクリア このマクロを参照することによって とを示す。 マクロが呼ばれる直前に押された ことを示し , それ以外て、あればこの 値が FALSE て、あれば押されていない 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : 10 : 20 : 23 : 25 : 26 : 27 : 29 : 30 : 32 : 34 : 35 : 36 : 38 : 39 : 40 : 42 : 43 : 44 : 45 : 46 : 47 : 48 : Keyints. asm STOP-Key / COPY-Key / Support Copyr ight (c) 1990 CoreDump CO.. Ltd. Created by N. Mita (CoreDump Co.. し td. ) Please Use MASM 5. 1 or later Åssembler part routines 12 : KEYINTS_TEXT 13 : KEYINTS_TEXT 15 : _DATA 16 : _DATA 18 : CONST 19 : CONST 21 : _BSS 22 : _BSS 24 : DGROUP EXTRN 28 : EXTRN 31 : KEYINTS_TEXT 33 : PUB い C SEGMENT ENDS SEGMENT ENDS SEGMENT ENDS GROUP ASSUM E f_stop:WORD f_copy:WORD TITLE SEGMENT BYTE PUB い C KEYINTS. ASM 'CODE' ENDS WORD PUB い C 'DATA ・ WORD PUB い C ・ CONST' WORD PUB い C 'BSS' CONST, _BSS, DATA CS: KEYINTS_TEXT, DS: DGROUP. PROC FAR -stpintr SEGMENT SS: DGROUP, ES: DGROUP BOOL HIT_COPY -stpintr c ⅱ pushf push push 凱 OV mov IOV mov POP POP ・ ds ax, 1 ds: f_stop. ax ax, DGROUP 92 Set98StopAndCopyKey( ) 関数を 呼んだ後 , このマクロの値を確かめ ることによってキーが押さ れたかどうかを確かめることがて、き 値が FALSE て、あれば押されていない ことを示し , それ以外て、あればこの CMAGAZINE 19 3 Set DS: to DATÅ-SEGMENTS Set Not 0

10. 月刊 C MAGAZINE 1990年3月号

の置換が成立しなければ , 2 番目の要素に 74 : 75 : 88 : 90 : き , 厄介な詳細はすべてプライベート部に List 3 / / 比較する関数と写像する関数のストア this->map map : th iS— >compare = compare : / / 挿入回数の初期化 inserted 80 : / / プレント法によるハッシュテープルへの要素の挿入 81 : void hashtab: : insert(void *element) { size-t mapped-val, hl, h2. depth• i : size-t c2,cur2,depth2; / / テープルの空スロットを探すためのテストの表現 = empty Ⅱ table[(x)] = = deleted) 87 : # define VACANT(x) (table[(x)] / / テープル満杯チェックーいつもテープルに少なくともひとつの空スロットが / / 残されていること ( さもなければ , 満杯のテープルで永遠にキーを 96 : 99 : 100 : 101 : 102 : 103 : 104 : 105 : 106 : 107 : 108 : 109 : 110 : 112 : 113 : 114 : 115 : 116 : 117 : 118 : 119 : 120 : 121 : 122 : 123 : 124 : 125 : 126 : 127 : 128 : 129 : 130 : 131 : 132 : 133 : 134 : 135 : 136 : 137 : 138 : 139 : 140 : / / 永遠に探しつづけなければならない ) if( 十十 inserted = = tablesize) { cerr くく "hash table fuIlYn ” exit(l); / / キーから値への写像と , 1 次ハッシュを行う。 = map (element) : mapped-va ー mapped-val % tables ize; / / 2 次ハッシュ (mapped-val % (tables ize / / 衝突リストの長さ計算 for(cur = hl. depth = 0 : !VACANT(cur); cur = / / テープル内に要素がすでにあれば置換して戻る if(compare(element, table[cur]) table[cur] = element; return; depth + + : / / 衝突リストが長くなければ要素を格納する if(depth く 2 ) { tab 厄 [cur] element; return : (cur + (2) % tablesize) i く depth; i 十十 , cur for ( i = 0. c ur = h 1 : / / 衝突リストの現在の要素の第 2 次のハッシュ値 c2 = (map(table[cur]) % (tablesize ー ( hl + h2 ) % tablesize) { depth2 + + , cur2 (cur2 十 (2) % tablesize) !VACANT (cur2) & & depth2 ← for(depth2 = 0 , cur2 (cur + (2) % tablesize; / / 挿入しようとする対象データよりこのテープルの要素の方が少ない移動なら実行 / / ここに挿入して検索を改良 i f (depth2 く = は要素を格納した空スロットのインデックス tabIe[cur2] = table[cur] : break : / / 終了状態 : cur 注目する。同様に , 2 番目の要素がその対 象データの衝突リストにおいて 2 か所より少 ない移動て、空て、あれば , それと置き換える。 一般に , 対象データの衝突リストのなか の n 番目の要素が , その対象データの衝突リ ストて、 n 回より少ない移動て、空て、あれば , そ れを置換する。これは置換されるもとの対 象データにとってはアクセス時間を増加さ せることになるが , 挿入する対象データに とってはアクセス時間の減少をもたらし , 単純なアルゴリズム D を実質的に改良するこ とがて、きる。このような置換を繰り返して いくと , すべての要素について衝突リスト の長さが等しいものになっていく。 LOOKUP の最悪の場合の性能は , 最大の 衝突リストの長さと直接比例関係にあるか ら , このプレント法により改良されたテー プルは , それぞれの挿入のときに衝突リス トの長さをて、きるかぎり等しくしようとし ているのて、 , 総合的に速い検索がて、きると いえる。アルゴリズム D よりプレント法が優 れていることの証明は , 読者への宿題とし ておこう〔訳注 : 参考文献に Brent,R. P. Reducing the retrieval time Of scatter storage techniques, C. ASM, 16 ( 2 ) ・ pp. 105 ー 109 , 1973. をあげておこう〕。 一般的なハッシュ法に興味をもた れたならば , クヌースの著書の「ハッシュ法」 の章を読むことを勧める。その論は読んて おもしろく , 完璧なものて、あるといえよう。 C 十十とプレント法 C 十十のクラスの仕組みを用いれば , 抽象 データのインプリメントに関する詳細を完 全に隠す (hide) ことがて、きる。つまり , クラ スにはパプリック部 (public part) とプライ べート部 (private part) があり , データ型に ついて , 許される操作をパプリック部にお ァープルのなかのテープル 25