include - みる会図書館


検索対象: 月刊 C MAGAZINE 1992年7月号
43件見つかりました。

1. 月刊 C MAGAZINE 1992年7月号

に , overlay_print_start 関数によって行う。 この関数は以下のような書式となっており , 呼び出したいバッフアのページ番号を引数 として与える。 overlay print start (page) List 1 2 : 4 : 8 : 13 : 15 : 16 : 17 : 18 : 19 : 21 : 28 : 35 : 37 : { 39 : 40 : 41 : 42 : 43 : 44 : 45 : 46 : 48 : 49 : 51 : 52 : 53 : 55 : 58 : 60 : 61 : 62 : 63 : 64 : 65 : 66 : 68 : 69 : 71 : 73 : 74 : 75 : 76 : 77 : 80 : 82 : オーバレイ機能を活用したサンプルプログラム char * page は 1 ) ページ番号 ( 0 また ” config. h ” 1 : #include 3 : #define MYEXTERN 5 : #include く stdio. h> 6 : #include く fcntl. h 〉 7 : #include く string. h> 9 : #include ” pld Ⅷ . h ” 10 : #include ” Iips2. h ” 11 : #include ” 1 ipsvar2. h ” 12 : #include く curses. h 〉 14 : #ifdef PROTOTYPE #include ” 1 ipspr02. h ” #include ” cbox rot. h ” このオーバレイベージの印字は , overlay _print_end 関数が呼び出されるまて、行われ る。前述のように LIPS て、はオーバレイ用の ノヾッフアがふたっ用意されている。このふ たつのオーバレイベージは同時に指定する こともて、きるのて、 , 通常の印字と合わせれ ば三重の印字がて、きることになる。 Fig. 2 , Fig. 3 は , サンプルプログラムに よって出力されたものて、ある。この 2 枚の印 字出力については , 罫線データの転送はオ ーバレイ機能によって 1 回て、済んて、いること に注意していただきたい 明細書印刷プログラム このオーバレイ機能を応用して前回紹介 した診療報酬明細書用紙を印字するプログ ラムをさらに発展させてみた。このプログ ラム (List 2 , List 3 参照。なお , プログラ ムの詳細は , 付録ディスク収録のソースプ ログラムをご覧いただきたい ) は , 年月 , 医 療機関名 , 枚数などのをキーポード入力し , それぞれ独自の明細書を印刷することを可 能にしたものて、ある。 入力自体は , あまり勝手のいいものて、は ないが , UNIX および MS ー DOS の双方て、稼 働することを優先させたのて、ご容赦いただ ■■プログラムの実行 MS-DOS および UNIX の端末ないし tty ウ インドウを前提とした curses ライプラリを 活用したプログラムを実行すると Fig. 4 (P C ー 9801 の例 ) のような形になる。メニューか らデータ入力を選択すると Fig. 5(UNIX の 例 ) のような画面が現われる。それぞれの入 134 C MAGAZINE 1992 7 VOid main(void mojisets(void) ; wakprint(void) ; 20 : #endif 22 : #ifdef UNIX 23 : #define ASSIGN_TABLE 24 : #endif 25 : #ifdef MSDOS 26 : #define ASSIGN_TABLE 27 : #endif 29 : #define MINCH032 30 : #define MINCH024 31 : #define GOTHIC 32 : #define MINCH032_TATE 33 : #define MINCH024_TATE 34 : #define GOTHIC_TATE ” 5 ” , ASSIGN_TABLE, ” 2 ” ” 2 ” ” 3 ” / * UNIX と S ー DOS では / * アサインテーブルが異なる。 * / / * ここが最も重要なポイント * / ” 0 ” , ASSIGN_TABLE, " 2 ” ” 1 ” , ASSIGN TABLE, ” 2 ” ” 2 ” , ASSIGN_TABLE, " 2 " ” 3 " , ASSIGN_TABLE, ” 2 ” " 4 " , ASSIGN_TABLE, " 2 " 36 : void main() 38 : #ifdef UNIX int handle ・ exit(l) ; exit(l); if((handle = 0健n( ” /dev/ttyb", O_WRONLY ) ) = printf("can' t open printer }n") : if((stdprn ニ fdopen(handle, "w") ) = = NULL){ printf("can' t fopen printer }n") ; system( ” /usr/5bin/stty raw く /dev/ttyb") ; 50 : #endif Gdpi = 240 ; 54 : #ifdef MSDOS job—start( ” 21 ” , ” 240 ” , ” 4 ” ) ; 56 : #endif 57 : #ifdef UNIX job—start( ” 21", " 240 ” , ” 2 " ) : 59 : #endif initlaza(); size—mde(); ⅳ ot ー凹 it ( " ? 6 " ) ; mojiretsu kakudai mode() ; ←プリンタ用のデバイスを raw モードにしている auto-kyocho() ; print—maisu( ” 1 ” ) ; mojisets(); overlay—touroku start( zenkaku() : wakprint() ; overlay-touroku—end() : overlay—print—start( ” 0, get—m0jiset(GOTHIC) ; fourbai ( ) ; mkprint 80 , 25 , ”納品 kaipage ) : mkprint(80, 25 , ”請求 kaipage() ; overlay rint_end( ” 0 ” ) ; job—end exit( の : 83 : wakprint() 書 書” 罫線部分のデータはすでに登録されている ので , これだけで 1 頁分の出力ができる

2. 月刊 C MAGAZINE 1992年7月号

List 1 変わり目を検出するため , 余分な時間がか かるという欠点がありますが , タイマ割り 込みのオーバヘッドがないため , 実際の経 過時間を計測て、きるという利点があります。 timer. c は筆者のユーティリテイからタイ マ割り込みを使用する機種依存部のモード を取り去ったものて、すが , 興味があればタ イマ割り込みて、の計測モードも追加してく ださい。タイマを開始 / 停止する関数 void ( * timer start) (void) ・ unsigned long ( * timer stop) ( void ) ; を差し換えるだけて、て、きます。詳細はソー スプログラムを参照してください 実行時間測定ユーティリティの使用法く 【使用法】 timer [ ーぐ > く回数 > ] く起動コマンドライン > < 起動コマンドライン > を起動して実行 時間を表示します。起動コマンドが COM フ ァイルまたは EXE ファイルて、あれば spawn 関数て、直接起動し , それ以外 ( バッチファイ ルまたは DOS の内部コマンド ) て、あれば sys tem 関数を使用して COMMAND ℃ OM 経由 て、起動します。 起動コマンドに COM, EXE 以外の拡張子 を指定しないて、ください。拡張子を指定す ると無条件に spawn 関数て、直接起動するた め , バッチファイルて、あれば暴走します。 また , 拡張子を指定しない場合は COM → E XE の順に検索します。 オプションスイッチは必ず < 起動コマン ドライン > の前に指定してください 続ける場合は一 0 のように指定してくださ stime_st. second, stime st. hsecond ) ; printf( " 終了時刻 % 2u : % 02u : % 02u. % 02u \ n " stime end. hour, stime end. minute, stime end. second, stime end. hsecond ) ; return( ret ) ; ^ 0 ー 8 0 り臨ワ】り 0 つなっ 0 00 List べンチマークテスト ( その 2 ) 1 : #include く stdiO. h> 2 : #include く process. h> 3 : #include く time. h 〉 5 : int main( int argc, char *argvC] ) time t stime St, stime end; 8 : int ret; 9 : 10 : 十十 argv; time( &stime st ) : / * 開始時刻 11 : spawnvp( P_WAIT, *argv, argv ) : 12 : ret time( &stime_end ) ; / * 終了時刻 13 : printf( ”経過時間 Xlu 秒 \ n ” , stime-end 14 : return( ret ) : 15 : / * 開始 / 終了時刻 stime_st ) : Li st —dos—gettime/gettime と time とのオーノヾヘッド 1 : #include く stdi0. h 〉 2 : #include く time. h> 3 : #include く process. h 〉 4 : #include く dos. h> 5 : 6 : # i fdef TURBO C 7 : #define _dos_gettime 8 : #define dostime—t 9 : #define hour 10 : #define minute 11 : #define second 12 : #define hsecond 13 : #endif 14 : 15 : void func dos( void ) , func time( void ) ; 16 : 17 : int main( void ) 18 : { func_dos() ; 19 : func_time() ; 20 : return( 0 ) ; 21 : 22 : } 23 : 24 : void func—dos( void ) struct dostime_t stime st, stime end; 26 : register unsigned int count 27 : 28 : _dos_gettime( &stime end ) ; 29 : do { 30 : _dos_gettime( &stime st ) ; 31 : } while ( stime_st. second 32 : do { 33 : —dos—gettime( &stime end ) ; 34 : 35 : 十十 count : = stime_end. second ) ; / * 秒の変わり目検出 * / } while ( stime_st. second 36 : 37 : #ifdef _TURBO C Xu 回 #n", count ) ; printf( "gettime 38 : 39 : #else printf( " dos_gettime %u 回 }n", count ) ; 40 : 41 : #endif 42 : } 43 : 44 : void func_time( void ) 45 : { time t stime st, stime end; 46 : register unsigned int count 48 : gett ime time ti hour ti min ti_sec t i _hund / * 開始 / 終了時刻 = stime_end. second ) ; / * 秒の変わり目検出 * / IBM-PC 互換機や FM-TOWNS のように DOS タイマが 1 / 100 秒単位の場合に指定可能 て、す。 PC ー 9801 シリーズて、指定すると 1 秒以 下の時間を計測て、きなくなります。 List 1 と同じような手順て、経過時間を計 測することになります。 ・回数 ( 1 ~ 65535 ) / * 開始 / 終了時刻 126 C MAGAZINE 1992 7

3. 月刊 C MAGAZINE 1992年7月号

短期連載 GCC 阨 p. 2 の移植 と G 十十 第 2 回 X68k 活用講座 X68000 版 G 十十 Ver. l. 耻 3 吉野智興 先月に引き続き , いつもの連載を休んで , 今月号と来月号 の 2 回に分けて付録ティスクに収録する X68000 版 G 十十 (G NIJG 十十 ) Ve 「 . 1 .40.3 の使い方を概説します。ティス ク容量のつごう上 , 2 回に分けて収録されるので今回の説明 に使用するライプラリなどが今月号だけでは用意できない ことをあらかじめお断わりしておきます。 動作環境とインストール X68000 版 G 十十 1.40.3 は , もともとが D OS-EXTENDER 上て、動く DJGPP と同じソ ースから作られたものなのて、 , コマンドオ プションなどはほとんど同じになっていま す。実際に X68000 上て、動かす場合について の留意事項を中心に説明をしていきます。 どこかに格納します。 この G 十十は , かなり厳しいハードウェア メモリ増設 1 M バイト ( 全 2M バイト ) の場合 ・ヘッダを適当なドライプのルートディレ 環境を要求します。基本的には XGCC が動作 残念て、すが , ほとんど実用にはなりませ クトリ上て、解凍します。その後 , ディレ する環境とまったく同じてす。 X68000 の G 十十もライプラリを XC に依存しているの クトリ SYS に格納されているヘッダを自 ん。が , 簡単なサンプルプログラム程度な て、 , XC がないと動かすことはて、きません。 分の環境に合わせて変更します。 List 1 を らコンパイル可能て、す。 ・最低 1.5M バイト程度のフリーエリア ( me 以下に環境に応じたインストールの例を紹 参照してください ドライプまて、指定し mfree て、確認て、きます ) を確保したシステ てある # include の部分は修正が必要て、す。 介します。なお , G 十十は非常に大きな処理 ムて、立ち上げを行います。この時 , RAM このヘッダを収録したディレクトリのパ 系て、す。真面目にメーカーのマニュアルな DISK にグラフィック RAM は指定て、きま スを , 環境変数 cplusplus include に設定 みに詳しく書くと , C マガ 1 冊になってしま せん。グラフィック RAM はコンパイラの してください います ( 爆笑 ) 。大いにおおざっぱな点はご ・ライプラリ環境変数 LIB の示すディレクト 作業メモリとして使用します。 容赦願います。 ・テンボラリファイルを作成する場所を指 リに格納します。解凍されたライプラリ 共通事項 定する環境変数 TEMP に , FDD を指定す の拡張子が . a のものは X C V e r. 1.01 るか , HDD を持っている方は適当な HD 用 , . 1 のものは XC Ver. 2.0 ( 2.1 ) 用て、 ・ gpp. x などの実行形式ファイルは , そのま D 上のディレクリを指定してください す。混在はて、きません。 ま環境変数 PATH が示すディレクトリの ヘッダを自分の環境に合わせる List 1 : #ifndef sys—fcntl_h 2 : #pragma once 3 : 4 : #include く a:%include*fcntl. h> ←ロ 5 : 6 : #include く std. h> 7 : 8 : #endif の部分を各人の環境に合わせる

4. 月刊 C MAGAZINE 1992年7月号

にぐ - 書 りば対 0 5 い屮 : 野を冐ー F 「、 ) 「だ 1 日支 . Of ⅲ ね「 t 発ま先名ッ : - マイクロア -- ( 株 ) ー、・保存機能 ート製品概念 ート試作用 ーし製発 し市販目的 ト画面作成 ト機能ボタン ト択一ボタン パラメータ X 68 k 活用講座 ト制御 List static メンバ int 変数を明示初期化 プロトタイビストは試作品を作ります。 1 : / * クラス定義を include する * / 2 : #include "sample. h ” 3 : 4 : / * static メンバを明示初期化する * / 5 : int サンプル : ・変数 = 10 : プロトタイピストは画面入出力の設計 / 制作を行う ツールです。実際に動作するマルチウインドウ画面 が対話型で即座に作成てきます。新製品開発時の試 作用にこ利用ください。プログラム ( C 言語 ) を組 込めば完成品の作成もてきます。 対応機種 . PC9801,lBM-PC, J3100 ( TIJ 日 BO - C 十十用 ) プロトタイビスト \ 49 , 000 なり前に G 十十て、 GNUroff を移植した際に 場合はたいへんな手間になります。これを 問題になって , フリーウェアとして hlk. x ( ハ 避ける手段は現在の X68000 版 G 十十には用 イスヒ。ードリンカ ) を制作された「そると」氏 意されていません。 にお願いして , . bss セクションと . data セク 次回は ションにシンボ、ルが重複した場合て、 , かっ . bss セクション以外に重複していない場合 は , . data セクションのシンボ、ルをそのデー 次回は , libg 十十について X68000 版の タ定義として扱うようにしていただきまし G 十十に実装されているヘッダのプリコンパ イル機能 ( これは , 常用するヘッダ類をあら 、 0 この結果 , hlk. x を使う場合は問題なくリ かじめコンパイラの内部情報としてコンパ ンクが行えますが , SHARP 純正のリンカて、 イルしておき , それをへッダをコンパイル は , このような明示的な static メンバの初期 する代わりに直接その内部情報を再度ロー 化がある場合はリンクを行う前に各コンパ ドしてヘッダをコンパイルする時間を節約 イル単位て、アセンプラソースを作成して . b する方法 ) について , X68000 版 G 十十て、のソ ss セクションに出力されている static メンノヾ ースコードデバッグについて説明を行う予 を削除してからアセンプルを行ってリンク 定て、す。 しなければなりません。 注ーフリーウェアの「とえんていわん」を ソース作成者が自分自身なら static メンバ 常駐させている場合は , これでもうまく 初期化は関数内部て、行うなりして逃げるこ 動きません。 floatfnc 」→ floatfnclib 」とリ ともて、きますが , 他人が作成したソースの ネームしてください。 C ドキュメント作成プログラム ト・、メ / トをア 0 ′ム をリ , -4 名を - す ニューパージョン ()3 , 0 ) プログラムの変化に対応できる文書化システム マイクロドックは、 C 言語ソースを解析して詳細仕 様書 ( 内部仕様書 ) を自動作成します。 表紙、目次、モジュール構成図、モジュール一覧表、 インクルードファイル使用一覧、グローノヾル変数使 用一覧表、関数仕様書等ぞ 1 冊の仕様書として罫線 でレイアウトして出力します。また、用紙のサイズ 合わせ、出力項目の選択等ができます。 ソース上に決められた型でコメントを記述すれば仕 様書の説明郎に取り込む事ができます。これによっ てドキュメントの完全自動作成も可能です。てきあ がりの文書をワープロ等て編集てきます。 V3.0 は次の機能強化および追加かされます。 ・英語スタイルのドキュメント出力 ・ AN 日規格の引数に対応 ・ nc 旧 de ファイルの解析および使用一覧出力 ・グロー八ル変数使用一覧出力 ・実行部のソースのコメントより構造化フローを出 力。これに依ってソースと対応のとれたプロック フロー付きのドキュメントが作成てきます 対応機種 . PC9801 シリーズ・ MS-DOS マシン 解析対象 . AN 仕様に準拠した C ソース マイクロドック V3.0 ( c ソース付 ) \ 48 , 000 上記製品はいすれもデモ・ディスク ( 無料 PC98 -5 インチ FD ) があります資料及びデモのご請求 は FAX でも受付ています。 マイクロアート株式会社 〒 2 幻横浜市神奈川区鶴屋町 2 ー 9 ー 22 ー引 4 電話 045 ー引 6-6508 FAX 045 ー引 6 ー 6509 受付時問 AMI 0 : 00 ー解 5 : 00 ( 月 ~ 金祭日除く ) く資料請求番号 143 ) い 2 7 TabIe 1 環境変数の一覧 環境変数名 内容 例 set GCC OP 引 ON = LFAMWGTO GCC OP 引 ON XGCC と同じ機能です。ー f ・・・・・・で指定する最適化の一部などがデフォルトで設定 されます プロプロセッサが処理するシステムヘッダが存在しているバスを示す環境変数 cplusplus include てす。 cplusplus include, include の順で検索されます。 stdio. h のように双方 include に存在するヘッダの場合には cp ⅳ sp ⅳ s include の stdio. h が優先されるわけです ライプラリが存在するノヾスを示す環境変数です リンカとして起動するプログラム名を指定する環境変数です ライプラリのサフィックス ( 拡張子 ) を指定する環境変数です アセンプラとして起動するプログラム名を指定する環境変数です G CC 凵 N K GCC L 旧 GCC AS 真里子 MARIKO 満里奈 MARINA これらの環境変数は参照はしていますが , 何も機能はありません 144 (

5. 月刊 C MAGAZINE 1992年7月号

実践アルゴリズム戦路解法のテクニック 1 : 3 : 4 : 7 : 9 : 10 : 11 : 12 : 14 : 16 : 20 : 22 : 24 : 25 : 26 : 28 : 29 : 30 : 32 : 34 : 35 : 36 : 38 : 39 : 40 : 41 : 42 : 43 : 44 : 45 : 46 : 48 : 49 : 50 : 52 : 53 : 54 : 55 : 56 : 58 : 59 : 60 : 61 : 62 : 63 : 64 : 65 : 68 : 69 : 71 : List 4 #include く stdiO. h 〉 2 : #include く stdlib. h> 17 : e{ 19 : } 23 : { 33 : { fgrep 主要部 #include く string. h> #include く jctype. h> 5 : #include く io. h 〉 6 : #include く fcntl. h> 8 : #define BUFSIZE 32000 char *position(char * , char * , int); void setup—table(char pattern[), int len) ; int my_nthctype(const char *S, int n) ; 13 : char POOICBUFSIZE + 1 ] ; 15 : / * パッフアの末尾に「番兵」セットする * / char *set_sentinel (char *buff, char *pattern, int pat—len) return memmove(buff + BUFSIZE ー pat-len, pattern, 21 : / * 文字列 s の中から , 文字 c を逆向きに探す * / char *strchr r(char *s, int c) int search_fiIe(FILE *infile, return s; while ()s ! = c) char *line tail; char * 1 ine head; char *next head : char *head; *sentinel; char *buf f ; rema1mng_Slze; len; int pat—len) char *pat tern, Char *fi le name, char *p; char int int buff ニ 801 + 1 ; pat—len) ; / * バッファ末尾の半端の行の長さ * / / * 読み込んだ文字列のサイズ * / / * パターン長 * / / * 検索パターン * / / * ファイル名 ( 現状では未使用 ) / * 入力ファイルストリーム * / / * バッフアの先頭の番兵 * / / * 表示行の末尾 * / / * 表示行の先頭 * / / * サーチボインタ * / / * バッファ末尾の半端な行の先頭 * / / * バッフアの空き領域の先頭 * / / 、パッフアの実質的な先頭 * / には , テキスト ( 行 ) の長さを求めなければ なりませんが , fgets ( ) は行の長さを返さな いため , strlen ( ) て、長さを求めることになり ます ostrlen( ) の処理内容は ' \ 0 ' を 1 文字ず っチェックすることて、すから , 下手をする と BM 法のサーチよりも時間がかかります。 つまり , 行単位の処理中て、 BM 法を使い , B M 法の高速性を殺さないようにするのは , かなり難しそうて、す。 このように BM 法はたいへん高速なアルゴ リズムて、はありますが , 使いこなすのにや や難しい点があります。 BM 法を使う人はこ の点に十分注意する必要があるて、しよう。 プログラムの説明 要素技術の検討が済んだのて、 , いよいよ プログラムを作ることがて、きます。プログ ラムの主要部のみを List 4 に示しました。 m y nthctype() という関数は , 前回説明し た , 高速版の文字種判定関数て、す。そのほ か細かい内容については , コメントを詳し く書いておきましたのて、 , そちらを参照し ていただくこ こてはバッファ / * バッファ末尾の番兵のセット * / = set_sentinel(buff, pattern, pat—len) : sentinel head = buff; while ((len ー fread(head, sizeof(char), sentinel ー head' / * 「半端な行」を探す * / next_head = strchr r(head + len ー 1 , / * 読み込んだプロック内でパターン検索する * / p = buff; infile)) 〉の { whi le ()p = position(), patterm pat—len)) く next-head) { p+;; / * p が漢字の 2 バイト目を指している * / if ( nthctype(buff, P ー buff) = CT-KJ2) line_tai 1 1 ine—head + 1 , stdout) : / * 行の印刷 * / fwrite(l ine-head, sizeof(char), / * 行の末尾をサーチ * / line_tail = strchr(), ' %n' ) ; line_head = strchr-r(), ' *n' ) + 1 ; / * 行の先頭をサーチ * / else { / * ボタンの掛け違いなので , ポインタを一つ進める * / / * 次の fread ( ) に備えて , 空き領域の先頭 ( h d ) を求めておく * / / * それをバッフアの先頭に移動 ( me 。 ve ) し , り / * 半端な行の長さ (remaining-siz) を計算し , */ p = line tail + 1 ; / * 次の行の先頭から検索を再開する * / の構造について補足説明します。 バッフアの概略については , 前に説明し たとおりて、すが , BM 法との関係て、バッファ 末尾に番兵をおいています。このバッファ にテキストを読み込んだ状態を Fig. 5 ー①に 図示します。 バッフアの末尾には , 「半端な行」が存在 することになり , そのためにプログラムが 少し複雑になっています。プロック内の処 をつけます。このようすを Fig. 5 ー②に示し ータを読み込むことて、 , 「半端な行」の始末 先頭に移動し , その直後の部分に残りのデ この「半端な行」をバッファ み込む直前に 理が終了し , 次回のプロックを fread ( ) て読 ー実践アルゴリズム戦略解法のテクニック 101

6. 月刊 C MAGAZINE 1992年7月号

-PC あるいはコンパチ機にインストールして ファイル転送した後 , 大規模な移植作業を 必要とする。筆者の友人が PC ー 9801 への移植 を試み , そこそこ動くものを作ってくれた。 彼の話によると ,DOS テキスト版は ROMB IOS や VRAM アクセスを多用しているのて、 かなりの部分に手を加えなければならない DOS グラフィック版はテキスト版ほどて、 はないにせよ , グラフィックモードて、の文 字のピクセルサイズが異なるため , 結構修 正が必要だ。 MS-Windows 版は DOS に比べ るとずっと楽て、 , ほとんど修正しなくても 済みそうて、ある。ちなみにソースコードは DOS 版て、約 23 , 000 行ある。 HellO wO 目団 おなじみ、、 Helloworld 〃を ZIL を使って書 いてみよう。 List 17 をご覧いただきたい。プログラム は大きく五つの部分 , すなわちディスプレ イの生成 , イベントマネージャの生成とデ バイスの登録 , ウインドウマネージャの生 成 , ウインドウの構築 , そしてイベントル ープから構成されている。 ディスプレイは , ま $BGI を使った DOS グラフィック版をインストールし , 失敗し たら DOS テキスト版に切り換えている。 M S-Windows 版てあればこの部分は , DISPLAY* display new MSWINDOWS DISPLAY ; if ( !display->installed ) { delete display return 最小自乗法による直線近似 1 : #include く iostream. h> 2 : #include く dvec. h> 3 : #include く lsqfit. h 〉 4 : #include く randunif. h> 5 : 6 : void main() { DoubleVec x ( 10 , 0.0 , 1. の 7 : DoubIeVec y ( 10 , 1.0 , 2. の 8 : 9 : 10 : RandUniform r ・ 11 : 12 : 13 : ”くく x くく endl cout くく” x 14 : ”くく y くく endl ・ cout くく” y LeastSqFit lsf(x,y) 17 : / / 最小自乗法によって求められた傾きと切片を表示する ' くく lsf. slope() くく” X + ”くく lsf. intercept() くく endl cout くく” Y = 20 : //x= 0.0 , 1.0 ... に対する Y の予測値を表示する 21 : for (double xx = 0.0 ; xx く 10.0 xx + = 1.0 ) 22 : " くく lsf. yPosition(xx) くく endl cout くく” x= ”くく xx くく” 23 : 24 : } y + = r. randValue(1 の : 〃 y[] に揺らぎをかける . 19.0 } h創0. cpp 1 : #include く ui—win. hpp> 2 : 3 : void main() ( / / ディスプレイの生成 4 : UI_DISPLAY *display = new UI—DOS-BGI DISPLAY; 5 : if (!display->installed) ( 6 : delete display; 7 : display = new UI-DOS TEXT—DISPLAY; 8 : 9 : 10 : / / イベントマネージャの生成とデバイスの登録 11 : UI_EVENT_MANAGER *eventMgr ニ new UI—EVENT MANAGER(IOO, display); 12 : 13 : *eventMgr + new U I_BI OS_KEYBOARD 14 : + new UI_MS_MOUSE 15 : + new UI_CURSOR; 16 : 17 : / / ウインドウマネージャの生成 18 : UI_WINDOW_MANAGER *windowMgr = new UI—WINDOW—MANAGER(display, eventMgr) ; 19 : 20 : / / ウインドウの構築 21 : UIW_WINDOW *window = new UIW—WINDOW(), 5 , 40 , 6 ) ; 22 : *window 23 : / / 外枠 + new UIW_BORDER 24 : / / 最大化ボタン ー + new UIW_MAXIMIZE_BUTTON 25 : 〃最小化ボタン + new UIW_MINIMIZE_BUTTON 26 : / / システムボタン + new UIW SYSTEM_BUTTON + new UIW-TITLE( ” He110 World Window") / / タイトル 28 : + new UIW TEXT(), 0 , 0 , 0 , " 日 e110 , World ! ”を 256 , TXF-NO-FLAGS, 29 : WOF_NONZFIELD_REGION) : 30 : 31 / / ウインドウマネージャにウインドウを登録 32 *windowMgr 十 window; 33 34 : 〃イベントループ 35 : int ccode; 36 : do { UI_EVENT event : 38 : eventMgr->Get(event, Q_NORMAL) ; 39 : ccode = windowMgr->Event(event) ; 40 : } while (ccode ! = L-EXIT & & ccode ! = S-NO OBJECT) ; 41 : 42 : / / 後始末 43 : delete windowMgr : 44 : de 1 ete even tMgr ; 45 : 46 : delete display; / / テキスト となる。 イベントマネージャにはキーポード , マ ウス , カーソルコントローラの三つのデノヾ イスが登録されている。 MS Windows て、 は , EVENT MANAGER* eventMgr new Ⅵ EVENT MANAGER ( 100 , display) ; * eventMgr 十 new MSWINDOWS MESSAGE , となる。 66 C MAGAZINE 1992 7

7. 月刊 C MAGAZINE 1992年7月号

大きくなる。その理由のひとつに仮想関数定する。いい換えれば , 実行するまて、どの おかざるを得ない。したがて , 仮想関 がある。仮想関数は動的束縛 , すなわち対メソッドが選ばれるかわからないのて、 , リ を多用するとそれに比例して = ードサイ 応するメソッド ( メンバ関数 ) を実行時に決ンク時にはすべてのメソッドをリンクして が大きくなる。 T 。 ols.h 十十にかぎらず , ある程度の規穆 diary. cpp のクラスライプラリを使う場合 , 小さなア プリケーシ = ンを組むには。ードサイズの 面て、は不利になる。 T001S. h 十十の MS-Windows 版ライプラ リは DLL をサポートしており , 。ードサイ ズをかなり小さく抑えることがて、きる ( ちな みに , TopSpeed C 十十は smart-method_ linking によて明らかに不必要な仮想関数 をリンクしないようになている。 T001S. h 十十を TopSpeedC 十十て、コン , ヾイルして みたが , 残念ながらコンパイルエラーが続 出してしまった ) 。 t 2 : * 'diary' , a demonstration 0f T001S. h + + ( v4.1.2 ) bY episteme (episteme@MlX GEB01501@NlF pcs51097@ASCII episteme@MlWA) 5 : * compi led with Borland C + + v3. 0 on AX-machine 7 い * write: diary く date 〉く event> ex. diary 4 / 18 / 92 "C-magazine on sale!" ex. d i ary 5 / 25 / 92 8 : * read: diary く date> 10 : 11 : #include く rw/rstream. > / / iostream 12 : #include く strstream. h> / / strstream 13 : #include く rw/rwfile. h 〉 / / RWFile / / RWDate 14 : #include く rw/rwdate. h> 15 : #include く rw/rwstring. h> / / RWString 16 : #include く rw/bintree. h> 〃 RWBinaryTree 18 : class DiaryRecord : public RWC011ectable { 19 : private: RWDate date 、 20 : RWString event 21 : 22 : public: DiaryRecord() 0 23 : DiaryRecord(const RWDate& const char* e) : date(d) 24 : virtual CIassID isA() const { return 256 ・ 25 : virtual int compareTo(const RWCollectable* c) const 26 : { return date. compareT0(&(((const DiaryRecord*)c)->date)) : } 28 : virtual RWCoIlectable* newSpecies() const ・ virtual void restoreGuts (RWFi 1 f) 29 : ; event. restoreFrom(f) { date. restoreFrom(f) 30 : vi れ 1 void saveGuts(RWFiIe& f) const 31 : { date. save0n(f) : event. saveOn(f) 32 : friend 0EErator くく (ostream& 0 , const DiaryRecord& s) 33 : くく s. event : } { return 0 くく s. date くく ' 34 : friend void show(RWC01 lectable* void* の 35 : 36 : ) : 37 : 38 : DEFINE_COLLECTABLE(DiaryRecord) 39 : : 40 : void show(RWC01 lectable* c, void* v) { (D i aryRecord* ) c ・ 41 : D i aryRecord* S if ( s->date. compareTo((RWDate*) の〉 = 0 ) 42 : cout くく *S くく endl 43 : 44 : } 45 : 46 : int main(int argc, char* argv ロ ) ( if ( argc く 2 ) return 1 ・ 47 : 48 : RWBoolean isFirst = !RWPile::Exists("diary. db") 49 : RWFi le f( ” diary. db ” ) ・ 50 : RWBinaryTree* diary ・ 52 : if ( isFirst ) / / 新規作成 53 : diary = new RWBinaryTree 54 : 〃既存ファイルから読み込み else 55 : diary = (RWBinaryTree*)RWCollectable: :restoreFrom(f) 56 : 57 : 〃日付の生成 59 : strstream SS ss くく argv[l] くく ends ・ 60 : RWDate date(ss) 61 : if ( !date. isVaIid() ) return 1 ・ 62 : date. setPrintOption(RWDate: : terse) ; 64 : if ( argc 〉 = 3 ) { / / 登録 65 : diary->insert(new DiaryRecord(date, argvC2]) ) : / / DiaryRecord の追加 66 : f. SeekTOBegin() 67 : diary->save0n(f) : / / ファイルへ書き込み 68 : / / 検索 } else { 69 : diary->apply(show, &date) : 71 : 72 : ・ / / DiaryRecord の消去 diarY->clearAndDestroy() 73 : delete diary ・ 74 : re turn 0 75 : 76 : ) m 則 t 引灼 コレクシ当ンの、 ' と影 Smalltalk には変数の型が存在しない。す べての変数は項点に立っクラス 0bject のポ インタて、あるといってもいいて、あろう。し たがって , どの変数に何を代入してもエラ ーにはならない 一方 , C 十十は PascaI や Modu1a-2 なみに 型チェックの厳しい言語て、ある。型の厳し い C 十十て、 , 型の存在しない Sma11ta1k の流 儀を実現するのだから , そこにはどうして も無理が生じる。 Fig. 11 をご覧いただくとわかるように Smalltalk-like コレクションのほとんどのメ ンバ関数の引数 / 戻り値は smalltalk の項点 クラス Object に対応する RWC011ectab1e の ポインタになっている。したがって , sma lltalk-like コレクションを使ってプログラミ ングする際 , 切れ味が鋭く , それだけ危険 の伴う、キャスト " からは逃れられない。安 全なキャストを実現するのは不可能て、はな いが ( fThe C 十十 programming Langua ge Second Edition 』 13.5 節にそのヒントが 紹介されている ) , ある程度のオーバヘッド は避けられない。 T001S. h 十十は安全性より スビードと高い自由度を選んだ。プログラ マの好みが分かれるところて、あろう。 , event(e) { } cout くく” after ”くく date くく” are.. ”くく endl ・ 62 C MAGAZINE 1992 7

8. 月刊 C MAGAZINE 1992年7月号

前述のように , BM 法て、は着目点のスキッ プ量を決めるために , 補助の表を用いてい ます。この表のサイズは 256 て、すから , おお ざっぱにいって 256 バイト分の処理量が必要 て、す。一方 , 通常のテキストは 1 行あたり 7 2 バイトくらいて、すから , 1 行ごとに表を作 成するのはたいへんムダなことて、す。 BM 法 の高速性が活かされるどころか , 表作成に 処理時間の大部分を取られることになりま す。奧村氏の元プログラムはアルゴリズム の説明用なのて、 , 上記が氏の責任て、ない とは当然て、すが , 書籍に載っているプログ ラムを丸写しして利用する場合は注意が必 要て、す。 今作ろうとしているプログラムはバッフ ァ長が 32000 バイトと長いのて、 , 上記のオー バヘッドはそれほど問題にはなりませんが , ムダを極力避ける意味て、表作成部を分離す ることにしました。プログラムの始めて、一 度だけ setup table( ) を呼び出すことになり ます。 一方 , 2 ) て、示したように関数 position( ) て、 終端チェックを省略したのは , テキストの 終端チェックにも前述の「番兵」を使うこと にしたからて、す。奧村氏は前述の文献中て、 , 終端チェックとして三つの方法をあげてお られます。 ①テキストを、 \ 0 ' ' でターミネートする ②テキストの長さを基準に範囲チェックす 18 : ( 44 : } buff==head len ー 1 skip[(unsigned char) patternCi]] for ( i = 0 ; i く len ー 1 ; i + + ) len; skip[i] = for (i = 0 : i ← UCHAR MAX; i + + ) int i ; / * 表を作成する * / 8 : void setup—table(char pattern ロ , int len) 6 : static int skipCUCHAR MAX + 1 ] ; 4 : #include く limits. h> #include く string. h> 2 : #include く stdlib. h> 1 : #include く stdio. h> BM 法のプログラム List 3 3 : 5 : 7 : 10 : 11 : 12 : 13 : 14 : 16 : 17 : 19 : 20 : 21 : 22 : 23 : 24 : 25 : 26 : 28 : 29 : 30 : 31 : 32 : 33 : 34 : 35 : 36 : 38 : 39 : 40 : 41 : 42 : 43 : char *position(char text[], 1 len ー 1 ; } else { return &text[i] ; for (i = 0 ; text[i] ニ 1 ) { if (len tail = patternClen ー 1 ] : return NULL; if (len char c, tai 1 ; int i, j, k; c = text[i]; J len ー 1 ; ニ tail) { char pattern[], int len) tail; / * 工ラー : 長さ 0 * / / * 最後の文字 * / / * 長さ 1 なら簡単 ! * / i 十十 ) / * 長さ 2 以上なら表を使って・・・ * / / * いよいよ照合 1 while (patternC--j] + = skip[(unsigned char) c]; return &text[k] ; / * 見つかった * / Fig. 5 バッフアの構造 る ③番兵を用いる 場合は注意が必要て、す。① ~ ③を行うため なく , fgets ( ) を使って行単位の処理を行う fread ( ) のようなプロック単位の処理て、は て、す。 文字ずっスキャンするとはかぎらないから ければなりません。 BM 法は , テキストを 1 ' \ 0 ' をパターンの長さ分だけ並べておかな 採用しました。なお , ①を採用する場合は , が , もっとも効率がよいと思われる番兵を 今回は上記のどれを使ってもよいのて、す ① ② ↑ po ↑ po 行 1 ↑ 半端な行 ↑ buff 行 2 ↑ head 行 3 移動 n ext— 半端な行 ↑ head バターン ( 番兵 ) ここにデータを読み込む ↑ sentinel ↑ バターン ( 番兵 ) sentinel 100 C MAGAZINE 1992 7

9. 月刊 C MAGAZINE 1992年7月号

・新 MS ー DOS プログラミンク入門 C ログラマのための の変換て、ある程度のオーバヘッドが生じて Table 2 時刻の取得 いることが想像て、きます。たとえば , List 3 DOS ファンクション 2Ch 時刻の取得 ( lsec. c ) のプログラムて、 1 秒間のループ回数 引数 AH : 2Ch INT 2 1 h を比較してみると TabIe 4 のようになりま 返り値 C H : 時 ( 0 ~ 23 ) す。 dos gettime/gettime 関数て、は , どの ( 0 ~ 59 ) CL : 分 コンパイラて、も約 1000 回ループしています ( 0 ~ 59 ) DH : 秒 ニ 1 / 100 秒 ( 0 ~ 99 ) D L が , time 関数て、はコンパイラにより差があ 機能 DOS が管理する時刻を取得する り , 317 ~ 487 回と少なくなっています。 旧 M ー PC 互換機や FM ー TOWNS では 1 / 100 秒まで取得できるが , PC ー 9801 シリーズでは DL レジスタは必ず 00h となる 実行時間測定ユーティリティ TabIe 3 現在の時刻の取得 dos gettime 関数 (MS-C, LSI C) それて、は 1 / 100 秒まて、計測可能なべンチマ #include く dos. h> ークテスト用の実行時間測定ユーティリテ void dOS gettime ( time ) : ィを紹介します (timer. c : 付録ディスク収録 ) / * 現在の時刻 struct dostime t *time , IBM-PC 互換機や FM-TOWNS て、は DO struct dostime t { S ファンクション 2Ch て、 1 / 100 秒単位まて、の / * 時 unsigned hour , 0 ~ 23 * / / * 分 0 ~ 59 * / unsigned char minute , 時間が取得可能て、すが , PC ー 9801 シリーズて、 / * 秒 0 ~ 59 * / unsigned Char second unsigned char hsecond : / * 1 / 100 秒 0 ~ 99 * / は秒単位まて、の時間しか取得て、きません。 したがって , 1 / 100 秒単位まて、測定しようと DOS ファンクション 2Ch を実行して現在の時刻を読み込む すれば工夫が必要て、す。 gettime 関数 0 ー ( れ「 bo C) こて、 , もう一度 TabIe 4 を見てくださ #include く dos. h> dos gettime/gettime 関数を使用すれ VOid gettime( ptime ) : ば 1 秒間に約 1000 回ループしています。とい / * 現在の時刻 * / struct time * ptime , うことは約 1 / 1000 秒まて、計測て、きるという struct time { / * 分 unsigned Char ti min , ことになります 0TabIe 4 は PC ー 9801RA ( 20 / * 時 unsigned char ti hour / * 1 / 100 秒 * / unsigned Char ti hund MHz : 80386 ) て、の結果て、すが , 低速の V30 / * 秒 unsigned Char ti sec , マシンて、も 1 / 100 秒単位程度て、あれば計測て、 DOS ファンクション 2Ch を実行して現在の時刻を読み込む きるて、しよう。 原理は次のようになります。 べンチマークテスト ( その 1 ) ①秒の変わり目を検出する ② 1 秒間のループ回数をカウントし , 開始 時刻を取得する ③指定のプログラムを起動する ④終了時刻を取得して , その時点から秒 の変わり目を検出するまでのループ回 数をカウントする ⑤④と②の比率により , 1 秒以下の時間を 計算し , 終了時刻と開始時刻の差に補 正を加え経過時間を計算する 1 / 100 秒単位の時間を計測しようと思え ば , タイマ割り込みを使用するのが普通て、 すが , 上記の手順を踏むことによりタイマ 割り込みを使用しなくても計測て、きるよう になります。プログラム起動の前後て、秒の Li st 1 : #include く stdio. h 〉 2 : #include く process. h 〉 3 : #include く dos. h 〉 4 : 5 : # i fdef TURBOC 6 : #define _dos_gettime 7 : #define dostime_t 8 : #define hour 9 : #define minute 10 : #define second 11 : #define hsecond 12 : #endif 13 : 14 : int main( int argc, char *argvC] ) struct dostime t stime st, stime end; 16 : int ret; 17 : 19 : 十十 argv : dos_gettime( &stime_st ) ; / * 開始時刻 20 : = spawnvp( P—WAIT, *argv, argv ) : 21 : ret dos—gettime( &stime_end ) ; / * 終了時刻 22 : printf( " 開始時刻 % 2u : % 02u : % 02u. % 02u \ n ” , 23 : 24 : stime st. hour, stime_st. minute, gettime time ti_hour ti min ti sec ti_hund / * 開始 / 終了時刻 新 MS-DOS プログラミング入門 125

10. 月刊 C MAGAZINE 1992年7月号

プログラミング C クイズ研究会 ーーイ直を返す関数 , gets ( ) ~ 先月の C お茶会の後 , 出席者のひとり榛沢 参加ください。 朝倉文夫 もしれん。 美保さんから NIFTY ー Se Ⅳ e を通じてメール 遺言じみて申し訳ないが , 志半ばにてむ このメールは先日プリントしてロバート をいただいた。小さなプログラムがそえて 佐々木氏に伝えておいた。そして , 先ほど , くわれぬ一生を終えるとも , 以後は丹羽さ あったのて、紹介する。く子供 . c > て、ある。 返事をいただいたばかりて、ある。 んがひとりで連載を続け , 小生が全生命を リスト最後のコメントは , 榛沢さんからの なんだか , 最近疲れていかん。 かけて C を学んできたことを後世に伝えてほ メッセージだが , 私もこのプログラムの最 毎月 , C 学習のためにどこかへ出かけている しい。最後に , 最近お気に入りのメールに 後て、 printf された文字列には , 複雑な思いを ことも体力を消耗する一因と思うが , パソ 関するプログラムくメール . C > を贈る。 いだいてしまった。共感する読者の方も多 コン通信でのメールのやりとりに凝ってし ロバート・佐々木 いと思う。さて , 今月はこんなメールが舞 まい , 夜ふかししているのも一因であろう。 おやおや , これは一大事て、ある。手紙か い込んて、きた。 今回も , 招待の声がかかっているようだ らすると , ロバート氏はかなり弱気になっ 有な略 が , 非常にありがたいことである。しかし , ているようだ。しかも , 今回のプログラム C でクイズしちゃおうというノリで発足し 以上のような事情であるから , 出席するつ を起動させてみると , どうにも意味不明て、 た , C クイズ研究会の発起人の朝倉といいま もりだが , 当日の健康状態によっては参加 ある。いったい , 毎晩どんなメールのやり す。最近 , ネタがなくて困っているのです できないかもしれん。その点は了承願いた とりをしているのだろうか。 が , ロバート氏と丹羽さんならば何かネタ い。当日 , 電車の待ち合わせの時刻に遅れ ところて、今回は , 関数が値を返している。 をいただけるのではないかと思い , ご招待 るようなことがあれば , 病気か , 体調不調 とにかく , 細かい事情を別とすれば , だい します。場所は都内の寿司屋です。ぜひ , か , あるいは , 最悪の場合は死んでいるか ぶ上達したようて、もある。しかし , 残念な 子供 . c 円羽信 ー夫の、、 ( その 7 ) イラスト / 山形彰吾 List 2 List puts " 貴君から女性へのメールポックスだ . " ) : 13 : 14 : puts puts " 1 相手の女性にメールを送る。 15 : puts " 2 貴君あてに届いたメールを読む。 " ) ; 16 : puts ” 0 終了する。” ) ; 17 : 18 : scanf("%d", &temp_menu_num) : fflush(stdin); 19 : 20 : 21 : return temp_menu_num,• 22 : 23 : } 24 : 25 : void wait_crkey() 26 : { puts ( " リターンキーを押せ . " ) ; getch(); 28 : 29 : } 30 : 31 : void get il ( ) 32 : { 33 : char *mai 1 buff ; 34 : 35 : puts "#n ” ) ; 36 : puts " メールを入力せよ . " ) ; gets mail_buff) ; 38 : puts 39 : puts ”気持ちが通じるとよいのだが . 40 : 41 : mail sent=l; 42 : / * こちらがメールを出すと相手も返事をよこす * / 43 : 45 : 46 : void disp-mail() 47 : / * 届いているメールを表示する * / 48 : { 49 : puts " 貴君に届いているメールだ . ” ) : 50 : put S puts ' " 陽子 , 昨夜はわるかった。あやまりたいので 6 時にルノアールで . 52 : puts ”明子さん . どうして私の方を向いてくれないんですか . ” ) : 53 : puts 54 : puts " メールは以上だ . 2 通も来てうらやましいだろう . " ) ; 55 : puts 1 : #include く stdio. h> 2 : / * 子供 . c * / 3 : 4 : main() 6 : int oya; 7 : int ko; 8 : puts ( " お子さんは何歳ですか . " ) ; 9 : 10 : scanfC'Xd", &ko) ; puts(' 何歳の時のお子さんですか . 11 : 12 : scanf( ” Xd ” , &oya) ; printf " あなたは今 % d 歳ですね . #n",oya + ko); 13 : printf " あれからもう % d 年になるのですね . #n",ko); 14 : 15 : } 16 : 「あたりまえじゃん . しよーもない ! 」と叫ぶか、 17 : / * 18 : / * 実感 ! するかは、人それぞれ . 19 : / * でも、私なんかは、今、しみじみ・後者です . では、また . List メール . c 1 : #include く stdio. h> 2 : #include く coniO. h 〉 3 : #include く process. h> 4 : 5 : int mail sent=O; 6 : / * メールを出したら 1 出さないとゼロのフラグ * / 7 : 8 : int menu(void) int temp_menu_num; 12 : 164 C MAGAZINE 1992 7