定義 - みる会図書館


検索対象: 月刊 C MAGAZINE 1991年9月号
66件見つかりました。

1. 月刊 C MAGAZINE 1991年9月号

ースタートアップ C + クラス ( 1 ) 実力養成講座 第 。前回まで O 言語に対して拡張された機能について解説 してきた。今回より 2 回にわたり , C 十十の機能の中でも っとも特徴的かつ重要な要素である「クラス」について 解説する。クラスも C 言語を拡張した機能のひとっとし 第て捕えることができる。当然 , 」を拡張された機能の中に一、 は , 新しい概念から生まれたものもある。ここでは , C き語の造体と較からクースの 理論編 とつの単位として扱えるということてある。 『 : ク ? スとは また , 参照てきるメンバと , 参照てきない クラスの定義は , 単に型を決定したにす メンバを区別することもてきる。このよう ぎない。構造体て、は , 構造体の定義を行っ にクラスを構造体の概念の拡張とみなすこ たあとに構造体変数や配列を宣言する。同 クラスは , C 言語の構造体 ( 以下構造体 ) と とにより , クラスの使い方は構造体と同様 同様にユーザが定義する型てあり , 構造体 様に , クラスの定義のあとにクラス変数や 概念を拡張した機能を持つ。構造体は種類 に行える。ただし , 拡張部分の取り扱いが 配列の宣言を行う。クラス変数宣言は , 特徴的なものとなる。 定義済みクラス名変数名 の異なった型のデータをひとつの単位とし て扱うことがてきる。クラスとして拡張さ となる。 クラスの定義 れた概念および機能は , データだけてなく , メンバー そのデータヘアクセスを行う関数まてもひ 構造体がユーザ定義の型てあるように クラスもユーザ定義の型てある。つまり , 構造体の概念を拡張したクラスをメンバ コラム というタームを使ってまとめると クラスを使用するためには , クラスの型の C 十十の構造体 ①関数をメンバとすることができる 定義を行う必要がある。構造体ては , キー C + + にも構造体は存在する。ただし , ②スコープによるメンバの区別 ワード struct により型の定義を行い , 型名に クラス型のひとつの種類として存在す 相当するタグ名をユーザ ( プログラマ ) が決 といえる。 るものである。構造体の定義はキーワ 定した。クラスの定義ては , キーワード class 関数をメンバとする場合は , クラス定義 ード class をキーワード st 「 uct に置き換 の中て関数の定義を行うか , プロトタイプ により型の定義を行い , 型名に相当する「ク えたもので , ラベルが別の保護レベル ラス名 ( タグ名 ) 」をユーザが決定する。ク 宣言を行う必要がある。プロトタイプ宣言 を示すまで自動的にバブリックメンバ ラス定義は , を行ったメンバとなる関数は , クラス定義 となる。つまり , 自動的に設定される class クラス名 { とは別に関数を定義する。 Fig. 1 に示すよう 保護レベルが異なる以外は , クラスと に , クラス定義とは別にメンバとする関数 メン / ヾ 同じものである。 を定義する場合は , 関数の型と関数名の間 龍崎昌平 スタートアップ C 十 + 123

2. 月刊 C MAGAZINE 1991年9月号

Fig. 2 インライン関数として定義 Fig. 1 メンバとする関数の定義 class クラス名 { 〃メンバ関数の定義 関数の型関数名 ( 引数並び ) 関数本体 〃メンバ関数のプロトタイプ宣言 関数の型関数名 ( 引数並び ) : / / プロトタイプ宣言された関数定義 関数の型クラス名 : : 関数名 ( 引数並び ) 関数本体 class クラス名 { 〃メンバ関数のプロトタイプ宣言 関数の型関数名 ( 引数並び ) : / / プロトタイプ宣言された関数のインライン定義 inline 関数の型クラス名 : : 関数名 ( 引数並び ) 関数本体 に「クラス名 : : 」を記述し , どのクラスの イベートメンバとなり , キーワード public を メンバとなる関数かを指示する。クラスの ラベルとして記述したあとのメンバは , パ メンバとなる関数をメンバ関数と呼ぶ。 プリックメンバとなる。 クラス定義内てメンバ関数が定義された class クラス名 { 場合に , そのメンバ関数はインライン関数 / / プライベートメンバ として扱われる。また , クラス定義とは別 メンバ変数 にメンバ関数が定義された場合は , 関数呼 メンバ関数 び出しとなる。ただし , クラス定義とは別 public . に定義されたメンバ関数をインライン関数 メンバ変数 として定義する場合は , メンバ関数定義の メンバ関数 際に , キーワード in ⅱ ne を関数の型の前に記 述する (Fig. 2 ) 。メンバ関数に対し , データ また , クラス定義時にラベル private : を としてのメンバをメンバ変数と呼び , すべ 己述することて , パプリックメンバ以降に てのメンバ変数とメンバ関数をまとめて呼 プライベートメンバを指定することも可能 ぶ場合は , メンバと呼ぶ。 て、ある。ラベル private : や public : は , 複 もうひとつの拡張された概念て、ある , メ 数混在することが許されている。 ンバのスコープについて解説する。構造体 クラス名 { class のメンバは , 構造体変数が外部変数て、ある / / パプリックメンバ public : ときや関数の引数として指定されると , ど メンバ変数 の関数 ( ューザ関数 ) からもメンバを参照 ( ア メンバ関数 クセス ) てきるが , クラスてはユーザ定義関 / / プライベ ートメンバ 数から参照てきるメンバと , そうて、ないメ メンバ変数 ンバをクラス定義時に指定てきる。 メンバ関数 他の関数から参照てきるメンバをバブリッ public : クメンバ ( 変数 , 関数 ) , メンバ関数とフレ ンド関数以外の関数から参照てきないメン バをプライベートメンバ ( 変数 , 関数 ) と呼 ぶ。これらは , クラス定義時に区別され , キーワード class 以降にあるメンバはラベル が別の保護レベルを示すまて自動的にプラ しは , 構造体て、のメンバの参照と同様て、あ る。クラス変数を宣言することにより , そ の実体が記憶領域上に割り当てられ , 実体 に対しては演算子 ! ク ( ピリオド ) を使い クラス変数名 . メンバ変数名 て、値の参照を行う。 メンバ関数の呼び出しは , クラス変数名 . メンバ関数名 ( 引数 ) て、行われる。実体を指すポインタの際には , 演算子、、一 > 〃を用いる。パプリックメンバに 対しプライベートメンバは , ほかの関数か らは参照が行えない。したがって , プライ Fig. 3 メンバの参照 class クラス名 { メンバ変数 p 「 a 関数の型メンバ関数 p 「 af ( ) / / バブリックメンバ 1 三ロ public : メンバ変数 pub , 関数の型メンバ関数 pubf ( ) メンバ変数 p 「 a 十十 : メンバ関数 p 「 af ( ) : private . main( ) クラス名クラス変数 1 : クラス変数 1 . メンバ変数 pub = 値 , クラス変数 1 メンバ関数 pubf ( ) : クラス名 * クラス変数 2 , クラス変数 2 = & クラス変数 1 : クラス変数 2- > メンバ変数 pub = 値 : クラス変数 2 ー > メンバ関数 pubf ( ) : / / バブリックメンバ メンバの参照 ューザ関数からのパプリックメンバとな るメンバ変数の参照やメンバ関数の呼び出 124 C MAGAZINE 1 1 9

3. 月刊 C MAGAZINE 1991年9月号

X 68 k 活用講座 Fig. 1 DEF. BAS のテータ形式 スプライトを使う 実際にスプライトを表示するには , 最初 に一度行う常識的な初期化作業のほかに , 1 PCG ェリアに表示データを定義する 2 スプライトスクロールレジスタに表示 位置などを書き込む のふたつの作業が必要てす。 PCG ェリアは $EB8000—$EBBFFF< すが , BG 画面の表 示枚数によって定義てきるスプライト数が 変化します。 Table 1 の最大定義個数 , 256 個 は BG 面をまったく使用しない場合て , BG 面を 2 面とも使う場合は 128 個に制限されます。 List 1 は XC 付属の DEF. BAS< 作った X- BASIC のソースキャラクタを , PCG ェリア に書き込むプログラムサンプルてす。 DEF. BAS は Fig. 1 のような形式てデータを出力 します。 PCG の構成は Fig. 2 のようになっているの て , ビットフィールドを使ってデータを転 送してスプライトデータを定義します。 Fig. 2 に示してあるように 4 ビットて 1 ドット , 上 位ビットカⅨ座標の若いほうになります。 16X 16 のデータは Fig. 1 のように直感とは少し異 1 ワードで 4DOT になります なった配置になっているのて注意してくだ D15 D14 D13 D12 D07 D06 D05 D04 D11 DIO D09 D08 D03 D02 D01 D00 さい。当然 , 実際のゲームのように頻繁に $EB8000 * * * * PCG を書き換える場合はこのようなムダを 4 BIT 1 DOT しないて , あらかじめ素直にポインタてな ぞって定義てきる形式に直しておくのが望 ましいてしよう。 List 1 が実際のコーディング例てす。スー は , 例によって垂直帰線期間にこの PCG 書 示モードによって最大値が変化しますが , パーバイザ空間をアクセスするのて注意し き換え処理を行えばスプライトが消えるこ コード 0 が PCG ェリア先頭のデータを指すこ てください。 IOCS 経由が一般的てすが , 自 となく効率的に書き換えられます。 とはいつも同じてす。 パレットプロックというのは , スプライ 前てやるように記述してみました。 PCG に表示するスプライトを定義した ら , スプライトスクロールレジスタに表示 21 行と 48 行て整数値をポインタにキャス トの PCGi•—タに対応する表示色を保持す する位置などのデータを書き込めば , めて トしてメモリをいじるという , ほとんど反 るスプライトパレットが 1 固明意されてい 則な記述があります。これは , スプライト るのて , このうちどのパレットプロックを たくキャラクタが表示されます。 制御の LSI と CPU が競合して PCG をアクセ List 2 はスクロールレジスタに書き込みを 使用するのかを指定してやります。攻撃を 受けるとビカピカ白く光る処里があります 行う割り込み処理関数の例てす。冒頭て定 スすることによって , CPU 側にウェイトが が , これを使えば簡単に実現てきます ( 全表 義している構造体はこのスクロールレジス 入るのを防ぐための処理てす。スプライト 示色を白に近い色に定義したパレットを用 は 21 行から 48 行の処理の間は表示されなく タをそのまま C の構造体て定義したものて 意し , そのパレットて表示すルばいいのて なります。スプライトをアニメーション処 す。各フィールドの意味は List 2 に記入して す ) 。垂直反転 , 水平反転は字面のとおりて 理するような目的て PCG を書き換える場合 あるとおりてす。 PCG コードは BG 画面の表 16 ドット ( X ) → 16 ド ツ ト ↓ Fig. 2 PCG 構成 $ EB8000 X68 活用講座 85

4. 月刊 C MAGAZINE 1991年9月号

「 CPW(Compact Programming Windows) 」 ( 株 ) コミュニケーション・プランニング ( 株 ) コミュニケーション・プランニング は MS-Windows (Ver. 3.0 ) 用のアプリケー ションソフト作成支援ツール「 CPW ( C 。 m pact Programming Windows) 」を発売し 同ソフトは Windows 用アプリケーション 開発時のウインドウ制御 ( ウインドウのサイ ズ , 位置 , 入力内容 , 入力条件 ) の設計を効 率よく , 簡単に行うための開発支援ツール て , ウインドウの表示位置 , 大きさ , 文字 , 罫線 , 入力位置 , 内容などを定義するため に専用の「ウインドウ定義体言語」が用意さ れている。 開発は , Windows 上の専用工デイタて、作 成したウインドウ定義体言語のプログラム をコンパイルしてウインドウ定義パラメー タファイルを作成する。ューザプログラム はウインドウ制御関数を介して , この定義 パラメータファイルを読み込みウインドウ の制御を実現することがて、きる。 CPW 基本セットには以下のものが含まれ ・ウインドウ工デイタ Windows 上て、動作するウインドウデザイ ンエデイタ ・ウインドウ定義体コンパイラ 定義体言語の構文チェック , 正規チェッ クなどを行い , 定義パラメータファイル を作成する専用コンパイラ ・ウインドウライプラリ ウインドウ画面 , 入力などを制御する関 数 ( 30 数種類 ) ・ウインドウ表示ルーチン く動作環境 > ・対応機種 PC ー 9801 シリーズ PS/55 シリーズ QuarterL シリーズ 146 C MAGAZINE 1 1 9 C MAGA く価格 > 168 , 000 円 MS-C Ver. 5.1 以上 SDK Ver. 3.0 MS -Windows Ver. 3.0 ・ソフトウェア環境 動作する PC その他 Windows Ver. 3.0 が J ー 3100 シリーズ ・割り込み処理により , 最大 3 回線の同時送 ・拡張 RS ー 232C ポードをサポート ・調歩同期式 , 同期式手順をサポート している。おもな特徴は以下のとおり。 ルとして通信プログラム「 Y ー TERM 」も付属 を行うためのライプラリ。製品にはサンプ 同ソフトは C 言語て RS ー 232C の各種制御 を発売した。 支援するライプラリ集「 RS ー 232C Library 」 吉正電子 ( 株 ) は通信プログラムの開発を 吉正電子 ( 株 ) 「 RS -232C Library 」 TEL 045 ( 316 ) 1168 大西ビル 3F 〒 220 神奈川県横浜市西区楠町 10 ー 1 プランニング横浜システムセンター 問い合わせ先 ( 株 ) コミュニケーション・ く動作環境 > ード / ソフトフロー制御をサポート ・半 / 全二重制御をサポート 受信が可能 TEL 03 ( 5371 ) 3041 「 H D システム」 NTT ソフトウェア ( 株 ) NTT ソフトウェア ( 株 ) は HCP チャート ( プログラムの論理構造を視覚的に表現した チャート ) によるプログラム設計・製造支援 システム「 HD システム」を発古した 製品の特徴は以下のとおり。 ・ HCP チャートとプログラムコードを一元 管理し , 設計書とソースプログラムの内 容を常に一致させておくことが可能 ・処理とデータの流れを関係づけて , わか りやすい HCP チャートを得ることが可能 ・設計した HCP チャートからプログラムコ ードの一部を自動生成することが可能 ・既存のソースプログラムから HCP チャー ノし、 0 ト生成が可能 く動作環境 > ・対応機種 ・対応 OS ・対応プリンタ ・必要メモリ ・適応可能言語 ・外部記憶 く価格 > PC ー 9801 シリーズ MS-DOS Ver. 3.1 以上 PC-PR201H および同等品 640K ノヾイト C, P レ 1 , COBOL, Ada フロッヒ。ーデ、イスク盟Ⅲ刈 ) またはハードディスク ( 20M バイト以上 ) ・対応機種 ・対応 OS ・対応言語 PC ー 9801 シリーズ QuickC Ver. 2.00 以上 MS-C Ver. 5.10 以上 MS-DOS Ver. 2.11 以上 PC ー 9861K ( 拡張 RS ー 232C ポ く価格 > 23 , 000 円 問い合わせ先吉正電子 ( 株 ) 〒 151 東京都渋谷区代々木 1 ー 58 ー 10 第一西脇ビル HD システム基本部 (V5.00N , V5. OON-EX) 98 , 000 円 HD システム言語オプション ( 各言語 ) 各 40 , 000 円 問い合わせ先 NTT ソフトウェア ( 株 ) 〒 231 神奈川県横浜市中区山下町 223 ー 1 TEL 045 ( 212 ) 7516 「地獄の特訓・打てるか ? 」 亀島産業 ( 株 ) コミュニケーション事業部 亀島産業 ( 株 ) はゲーム感覚て、練習てきる キーポードトレーニングソフト「地獄の特訓・ 打てるか ? 」を発売した。

5. 月刊 C MAGAZINE 1991年9月号

ンバ変数とし , スタックを操作する Push , P 叩の操作をパプリックなメンバ関数として クラスを定義する ( Fig. 5 ) 。スタック上のデ ータはプログラムを構成するユーザ関数か らの直接操作は遮断される。したがって , データは保護される。また , プログラムて はデータを Push するときはメンバ関数 Push を , P 叩する場合はメンバ関数 P 叩を呼び出 すだけて , スタックを操作てきるわけてあ る。モジュールからの直接的なデータへの アクセスがなくなり , Push, P 叩以外の操 作はユーザ関数からまったく行えなくなる。 データの保護が実現されスタックという抽 象的な対象をモデル化・部品化しているわ けてある。このように , クラスはデータの 保護とデータの抽象化を実現する手段とな ラスの初期化と消去 クラス変数を宣言したり , メモリ管理演 算子 new を使用することによりクラスの領域 が記憶域上に確保される。 C プログラムの初 心者は , 変数は宣言したものの変数に値を 代入せずに演算したり , 変数がポインタ変 数てあるにもかかわらず , ポインタを代入 しないままポインタ処理を行うなどの初歩 List コンストラクタとディストラクタ class Char int publ ic: len; 的なミスを犯しがちて、ある。 クラスにおいてもクラス変数を宣言した り ,new により領域を確保した後てメンバ変 数に値を代入しないまま何らかの操作を行 う可能性はある。まして , メンバ変数は通 常の変数のような形式ての初期化は行えな い。クラスには , 変数の宣言や new によるク ラスの領域が確保された時点て , 自動的に 初期化を行うためのメンバ関数を設定てき る。このメンバ関数をコンストラクタと呼 ぶ。 メンバ変数がポインタ変数の場合 , コン ストラクタ内て演算子 new により領域を確保 し , そのポインタを持つようなポインタ変 数てあれば , クラス変数のスコープ ( 有効範 囲 ) が終了する際に , 確保された領域を解放 してスコープを終了する必要がある。もし , 解放を行わないとすると new によって確保さ Fig. 7 引数を持つようなコンストラクタ class クラス名 { main( ) Fig. 6 コンストラクタとディストラクタ class クラス名 { メンバ変数 public . / / コンストラクタの定義 クラス名 ( 引数の並び ) 〃コンストラクタのプロトタイプ宣言 クラス名 ( 引数の並び ) : / / ティストラクタの定義 ークラス名 ( 引数の並び ) ″ティストラクタのプロトタイプ宣言 ークラス名 ( 引数の並び ) : / / ほかのメンバ関数 ″コンストラクタの定義 ラス名 : : ークラス名 ( 引数の並び ) ケイ . トラクをの定義 : ークフス名 ( 引数の並び ) クラス名変数名 ( 引数の並び ) : れた領域は , 管理されずプログラムの終了 まて存在することとなりメモリ領域のムダ となる。このようなケースに対し自動的に クラスの後始末 ( 消去 ) を行うメンバ関数を 設定することもてきる。このメンバ関数を ディストラクタと呼ぶ。 コンストラクタやディストラクタを設定 すれば自動的にすべてを管理するわけては ない。それぞれのメンバ関数内て初期化や 後始末の手続きを定義する必要がある。コ ンストラクタ設定時のメンバ関数名は , ク ラス名と同じてあり , ディストラクタのメ ンバ関数名は一クラス名 ' ' ( チルダ ) とす る (Fig. 6 ) 。 コンストラクタやディストラクタは多重 定義 ( オーバロード ) が可能てあり , 引数の デフォルト値も設定てきる。コンストラク タの呼び出しは , クラス変数の領域が記憶 域上に割り当てられた時点て自動的に呼び 出される。そして , 引数を持つようなコン ストラクタては , Fig. 7 の形式て引数を指定 する。 ディストラクタの呼び出しは , クラスの 領域が変数の宣言によって確保されていれ ば , その変数の有効範囲が終了する時点に 演算子 new によって確保された領域てあれば delete によって解放される時点に自動的に呼 び出される。前述したようにディストラク タはクラスの後始末を行うためのもてある。 List 1 のようにコンストラクタによってクラ ス内部て領域を確保しているような場合に は , ディストラクタによって解放を行う。 List 1 ては , 〃 1 と / / 2 の処理において自動 的にコンストラクタが呼び出されている。 コンストラクタ内て記憶域を確保し , プラ X( char* p) len =•trlen( p ) : new char[len 十 1 ] : S delete CIen 十 l]s; strcpy( s, p) : 126 C MAGAZINE 1 1 9 delete bp: new *bp X X a( ” ABCD") : main() / / 1 / / 2 / / 3 / / 4 クラス名 * 変数名 = new クラス名 ( 引数の並び ) :

6. 月刊 C MAGAZINE 1991年9月号

-E(KEYRETURN コマンドの終了行 ) TabIe 2 W 爪 DOW コマンド ー W ( ウインドウの定義 ) WINNUM ウインドウ番号 まず行の先頭に〃マークを置く。次に 、、 K クが続くと KEYRETURN コマンドと認 識される。そして次の行から詳細な指定 を行う。指定コマンドには、、ノマークを先頭に つける。指定法は Table 1 のとおりてある。 Fig. 5 に示した指定例は , 各ファンクショ ンキーを押し下げた際に分岐する関数を指 定したものて、ある。ー KEY の後の 1 ~ 10 の番 号はキー番号てある。これは偶然ファンク ションキーの番号に対応しているが , 実際 には格納する変数の配列に与える番号なの て , ファンクションキーの番号には関係な い。どのキーてあるかの認識は , 次のキー の名前て、判断される。この名前は , あらか TabIe 1 KEYRETURN コマンド - K ( ウインドウの定義 ) -KEY : 1 : FI :winkind : 2 -KEY : 2 : F2 :winkind : 1 つ -KEY : 3 : F3 : winkind : 3 3 -KEY : 4 : F4 : winkind : 2 -KEY : 5 : F5 : winkind : 賃 2 -KEY : 7 : F7 : winkind : 2 -KEY : 8 : F8 : winkind : 賃 2 -KEY : 9 : F9 : winkind : 3 ・ 3 -FIELD : 1 : 1 : 4 : 日時照合を行わない -FIELD : 1 : 1 ・ ある。これらの関数には , それぞれ引数を どに使用するウインドウを表示する関数て きる関数てある。また selwin は , 二者択一な なウインドウの 3 種類のウインドウを表示て 可能なウインドウ , そして直接入力が可能 インドウ , ポックスカーソルによる選択が る owinkind 関数は , 単に内容を表示するウ は , winkind 関数 , lwin 関数が登録してあ 必要がある。今回提供する funcrun 関数に あらかじめ funcrun 関数の中て、定義しておく 先の関数名を表している。この関数名は , 次の winkind や selwin は , 実際に分岐する と同じものを使用する。 じめ fkey. h(List 1 ) て、定義されている定数名 与える必要があるが , これが、、 1A2 クやは いいえどっちもだめ〃などの最後のパ ラメータてある。各引数の間には , 区切り 記号として〃を使用する。 次にバージョンアップした機能を紹介し ・ WINDOW ウインドウの定義において , 分岐先の関数 名を指定てきるようにした [ 機能 ] サプウインドウを表示する [ 書式 ] *WIN DOW -WINCREATE;WINNUM ;XI ; Ⅵ ; ; Y2 ; KEYNUM KEYNAM E FUNC ARG キー番号 当該キーを認識するための名前 にの名前は , fke h で定義されているものと 同一のものを使甯する ) 分岐する先の関数名 関数に与える引数群 ( 各引数の間には″を挿入する ) X2 Y2 始点の X 座標 始点の Y 座標 終点の X 座標 終点の Y 座標 -C ( 表示色の指定 ) WINNUM COLORI COLO 日 2 ウインドウ番号 ウインドウ内の表示色 カーソル位置の表示色 Fig. 5 KEYRETURN 指定例 *KEYRETURN , -KEY : 6 : F6 : selwin : はしいいえどっちもだめ . -KEY : 10 : TAB : winkind : 3 2 -END -COLOR : 1 : 4 : 7 : -WINCREATE : 1 : 0 : 4 : 40 : 1 5 *WINDOW : SELECT Fig. 6 W DOW 指定例 : 3 : 厳密な検索を行わない : @addopt : 1 賃ー pO : : 2 : 厳密な検索を行う : @addopt : 1 賃ー pl : -FIELD : 1 : 1 : 1 : ディレクトリ名を追加しない : @addopt : 10 xo : -FIELD : 1 : 1 : O : ディレクトリ名を追加する : @addopt : 10 xl : -FIELD.• 1 : 1 -FIELD,• 1 : 1 ー F ( 各フィールド行の指定 ) -FIELD : 1 : 1 : 5 : 日時照合を行う -FIELD : 1 : 1 : 6 : 問い合わせを行う : @addopt : 12A-c 1 : : @addopt : 1 ?-cO : : @addopt : 13A-mO : WINNUM CONTENT @funcnam ARG ウインドウ番号 X 座標 Y 座標 表示内容 ボックスカーソルでその行を選択した場合に 分岐する関数名 ( 関数名の前には@マイを付 加する ) 上記の関数に与えるべき引数 -FIELD : 1 : 1 : 7 : 問い合わせを行わない ( 更新照合あり ) : @addopt : 1 , 8 : 問い合わせを行わない ( 更新照合なし ) : @addopt : 13A -END -COLOR : 3 : 7 : 5 , *INPUT,• Fig. 7 PUT 指定例 -FIELD : 0 : 3 : 20 : 1 : cboxbat : 13 : 0 : @addiparg : 2 0 : -m 1 : -m2 : ー E ( W DOW コマンドの終了行 ) 90 C MAGAZINE 1991 9

7. 月刊 C MAGAZINE 1991年9月号

S 日 0 プログラミング Fig. 4 メニュー画面 Fig. 5 窓口会計処理画面 簡易卩 0 S 窓口会社処理 処理を選択して下さい カド名価 人数 タの追加 商品デ 2. 商品データの修正 3. 窓口会計処理 燼 S を入力したい場合には , 商品名の入力時に List 4 は商品コードから商品名 , 単価など れている。しかしこのディスクは 5 インチ 2 ソ〃を入力する。すると個数入力のルーチン の情報を獲得する関数てある。本プログラ HD< あり , かっ MS ー DOS フォーマットもの に入るのて , そこて個数を入力する。ひと ムはもともとマルチューザ用に作成してい なの <,SPARCLT ないし SUN ワークステ つの商品の入力が終了すると , SP300 に商品 るのて , データを探索中は ISAM をロックし ーションて使用するためには , 媒体変換お コードと価格が印字される。商品名の入力 ている。この役割を担っているのが LKISA よびコンバートが必要てある。まず , 3.5 イ 時に一キーを空打ちすると終了とな ンチ 2DD フロッピーを MS ー DOS 上てソ 9 クつ M 関数てある。 り , SP300 に総合計が印字される。窓口会計 List 5 は , 外部変数を初期化する関数。 fld き <FORMAT する。次に MS-DOS 上てこ 処理自体を終了したい場合には , 商品名入 。 rd はフィールドの順序を指定する変数て のフロッピーにファイルをコピーする。最 カ時 * 〃を入力すればよい 後にワークステーション側 <MS-DOS/SU ある。 fldtyp は , 文字型 , 数値型などのフィー ルドのタイプを指定する変数てある ofldlen は NOS のコンバータを起動し , このフロッピ 以上の処理を行うには , あらかじめデー 各フィールドの長さを指定する変数てある。 ーから同ファイルを読み込めばよい。 SPA タベースに各商品に関するデータを入力し RCLT の場合には , 以下のような手続きて ておく必要がある。メインメニューにおい 付録ティスクの 行う。 て商品データの追加を選択すると , 商品デ 使用について % /bin/su ータ入力画面になるのて , 商品コード , 商 Password : ( パスワードを入力 ) 本プログラムは , 付録ディスクに収録さ 品名 , 売価などをそれぞれ入力する。 Fig. 6 markndb. P「2 プログラム 次のソースプログラムを参照してほしい List 1 はデータベースの定義に関する定数を 定義しているヘッダファイルてある。 List 2 は外部変数を定義しているヘッダファイル てある。 List 3 は main 関数てある。 markndb. pr2 (Fig. 6 ) は , データベースを定義しているパ ラメータファイルてある。画面表示に関し ては , curses ライプラリを使用している。ま た OPENISAM など大文字だけの関数は , c ー tree の関数てある。 utextke2 は , 前回紹介 した罫線表示関数てある。 12 6 4 3 0 marcust. dat 144 3 marcust. idx 8 0 8 0 4 20 114 16 0 1 marhin. dat 80 5 marhin. idx 10 0 10 0 2 marden. dat 50 6 marden. idx 4 0 4 3 7 16 8 0 8 28 10 0 1 2 8192 0 0 1 1 8192 0 8192 1 3 0 0 0 1 8192 1 1 32 1 0 32 1 0 1 0 8192 1 1 32 1 0 2 8192 1 1 0 1 0 32 1 0 32 1 0 1 1 12 14 SPARC LT プログラミング 107

8. 月刊 C MAGAZINE 1991年9月号

特集フレタ系言語研究 tako [ 4 : ] - → ' a pen tako ト 2 : ] # 負数をつけると終わりから数える tako [ : ー 2 ] → 'this is a p' のように文字列の一部分を取り出すことが て、きる。同じ操作をリストに対しても適用 て、き , C'asdf' 234 [ 2 3 ] 'oiu'] # 4 要素のリストを表す記法のとき → ['asdf' 234 ] ika [ 1 : 2 ] ika [ : 3 ] → ['asdf' 234 [ 2 3 ] ] ika [ ー 1 : ] → C'oiu'] 、、 [ ] 〃の中て、範囲指定を行うこ のように とて、文字列やリストの一部分を取り出すこ とがて、きる。加えて , リストについてはそ の一部分を削除したり , 真中に挿入したり することもて、きる。 もうひとつ python にはデータに型がある という点が perl や awk などと異なっている。 awk や perl て、は文字列と数字は演算の種類に よって自動的に変換が行われてきたが , python て、は型の合わない演算を行うとエラ 、、十〃は両辺が数値のときは算術的足し算 を , 両辺が文字列のときは文字列連結を行 い , 両辺の型が一致しないときはエラーに なる。 List 3 0 # $ 2 は , " [ tag ] ”のような形をしているので , 両端の 'Ci , ' 」 ' を # 取り除いてローカル変数 $ x に格納する。 local($x)=substr($2,1, length($2)-2); print TAG "$x $sections}n ”・ # 行頭に . ref が見つかった場合 if (!defined $tags{$l}) { # タグが定義されていなければ print STDERR "warning : undefined tag $ 1 ' at 1 ine $. }n ”・ } else { print "$tags{$l)*n ”・ } else { # 以上のパターンマッチに失敗した場合には単に行全体を出力する。 print; 、 1 りム CO 4- ロ 0 れ 0 8 0 ) 0 1 宀りなっ 0 4- L.D ^ 0 叮ーーワーワーワーワーロー叮ー 8 8 8 8 8 8 8 python で記述したサンプルプログラム LlSt 4 1 : #!/usr/local/bin/python 2 : 3 : # python では標準組み込みの機能はごく限られており , それら以外の機能を使う時には import でモ 4 : # ジュールを陽に読み込む必要がある。 sys では stderr などのシステム定数を定義し , regexp は正規 5 : # 表現を , string は文字列操作関数を提供する。 6 : 7 : lmport SYS 8 : lmport regexp import string 9 : 10 : 11 : # 値を設定していない変数を参照するとエラーになるのでプログラムの先頭で全て初期化する。 # { } は空リストを表す。 12 : already—compi led—patterns=() 13 : tags={) 14 : sect ion=o 15 : subsection=O 16 : subsubsection=O 17 : 18 : # awk で , string-/pattern/ に相当する手続きをここで定義する。 python ではパターンマッチの前に こでは同じパターンを何回もコンパイルしな 19 : # パターンを内部表現にコンパイルする必要がある。 20 : # いようにすでにコンパイルされたパターンを連想配列 already ー compil ー patterns に記憶しておく。 21 : def regexp_match(string, pattern) : # プロック構造はインデントの量で指定する。 22 : # クラスの中で定義されている手続きの呼び出しは classname. procedure' 23 : # あるいは variablename. procedure のように行う。 24 : if (not already_compiled—patterns. has—key(pattern)) : 25 : already_compi led—patterns[pattern]=regexp. compile(pattern) 26 : # exec はコンパイルされたパターンに対してパターンマッチを行わせる # ための手続き。返り値は , マッチに失敗した場合 0 , 成功した場合には 28 : # (... ) でくくられたパターンの出現位置を示すリスト。 29 : return already_compi led_patternscpattern]. exec(string) 30 : 32 : # この関数は awk , perk でも使われていた 33 : def substitute_fi lename extension(filename, newextension) : 34 : try : return fi lenameCO:string. index()i lename' ' . ' ) ] + newextension 35 : 36 : except string. index_error: return filename 十 newextension 38 : 39 : # ここでは例外ハンドラを使っている。 RuntimeError という種類の例外に対して except RuntimeErro 40 : # r 以下のプログラムをハンドラとして定義する。 RuntimeError はこの関数の中では open に失敗した 41 : # 時に発生する可能性がある。 try : 以下が最初に実行されるプログラム。 42 : 43 : def read_tag-file()i lename) : 44 : try : tagfp = fi lename—extension()i lename• '. tag' ) , ' r' ) 45 : line ニ tagfp. readline() 10 十 10 → 20 'asdf' 十 qwer' → 'asdfqwer' ERROR 'asdf' 十 20 そのほか , pyth 。 n の特徴的な機能を列挙 する。 ・例外処理を提供する。例外ハンドラを定 義しておけば , I/O などの処理を行うごと にエラーチェックをしなくてもエラーが 発生したときは自動的にハンドラに制御 を移すことがて、きる ・クラスを定義する機能を持っている。正 ま 規表現を使ったパターンマッチや , awk' perl て、は常識的に用意されている多彩な文 字列処理関数はクラスを使って標準関数 特集フィルタ系言語研究 39 0

9. 月刊 C MAGAZINE 1991年9月号

実力養成講座 5 イベートなメンバ変数 s によって領域を管理 している。 〃 3 て , 〃 2 によって確保されたクラスの領 域を解放する。解放される直前にディスト ラクタが自動的に呼び出され , プライベー トなメンバ変数 s が管理している領域の解放 を行う。ディストラクタが終了した後て , クラスの領域が解放されることになる。 〃 4 ては , クラス変数 a の有効範囲は終了 こても , し , 変数の領域が解放される。 『 ! された構造体ーークラス いやしくも「スタートアップ C 十十』なる ものの読者ともあろう方は , クラスとはな んぞや , という記事を以前にも読んだことが あるかもしれません。いわく , ユーザ定義 のデータ型てある。いわく , 個々のインス タンスの性質や属性を抽象した概念集合て ある。うんぬん。 そういうご託宣はとりあえず棚上げして , ありていにいってしまえば , C 十十のクラス とは構造体のことてす。 構造体の仕様は拡張されて , 変数だけて なく関数もフィールドに含めることがてき るようになりました。データもコードもま とめあげることのてきる構造体 , それがク ラスと呼ばれる代物てす。合わせて用語も 変更して , フィールドはメンバといい直さ れ , クラス内変数のことをメンバ変数と呼 び , 関数のことをメンバ関数と呼びならわ します。また , このクラス型の変数は ( クラ ス ) オプジェクトまたはインスタンスと呼び ます。 もっとも単純なクラスの例を List 1 に示し ます。用語を整理して List 1 を解説すると , 「メンバ変数 value と , メンバ関数 lnit, Print とを持つクラス A が宣言されており , a はク クラス変数 a の有効範囲の終了直前一 トラクタが呼び出されることになる。 こディス メンバ関数なのか明示しなくてはなりませ 解決演算子 . : を使って , どのクラスの メンバ関数を定義するときは , スコープ ということになります。 ラス A のインスタンス ( オプジェクト ) てある」 実践編 ールの部品化を容易に実現し , 再利用性を 作をひとまとめにすることにより , モジュ 利点としては , データとデータに対する操 抽象化によりデータを保護する。クラスの クラスは , データの抽象化を実現しその ん。 はすてに説明済みの項目てすが , 以前解説したときは , といった形てした。今にして思えば , これ は ( 空 ) : : a て「トップレベルの a 」を表す という特殊な用法 , ということがわかりま す。 メンバ関数は , 普通の関数と同じように オーバロードもてきるし , デフォルト引数 void Print(FlLE * fp void Print( ) ; struct A { ロードして , も使えます。たとえば A : stdin) : : Print をオーバ メンバ関数をインライン関数にすること などというものを設けることもてきます。 fprintf (fp, "%d*n", value) : void A : : Print(FILE * fp) スタートアップ C 十十 高められるということがあげられる。 C 十十プログラミングては , このクラスを どのように用いるかというプログラム設計 段階のクラス設計が重要になるてあろう。 クラスをどのように用いるかは , 本連載後 半て述べる予定てある。 次回はこのクラスの応用的な機能てある フレンド関数 , 演算子の多義化 , 派生クラ スといった機能を解説する。 白倉伸一郎・山本浩文 もてきます。このとき , キーワード inline を つける必要はありません。クラス A のメンバ 関数をインラインにした List 2 を見てもおわ かりのとおり , inline がなくても誰がどう見 たってインライン関数ばく書けるからてす ( もちろんつけてもかまわない ) 。 それはともかく , なんとも味気ないサン プルてす。用語や書式はたしかにカッコい いのてすが , 実際に行っている処理内容は 大したものてはありません。 A : : lnit ( ) が List 単純なクラスの例 pri ntf ("XdYn", value) : 14 : void A::Print() value 9 : void A::Init(int n) void Print(); vo i d i t ( i nt れ ) : int value; 3 : struct A { 1 : #include く stdiO. h> 24 : 23 : 22 : 8 : 6 : 5 : 4 : 2 : return 0 : a. Print(); a.Init(2); 19 : main() スタートアップ C 十十 127

10. 月刊 C MAGAZINE 1991年9月号

Q Turb0 C 十十を使ってアセン プラで List 1 のような関数を作って います。モデル指定を huge として いるのですが , リンク時に Fig. 1 の ようにデータが 64K バイトを越えて いるというエラーメッセージが出 てしまいます。 huge モデルですか ら , このエラーは出るはずがないと 思うのですが。 A List 1 の datal. asm, data2. asm て使用している疑似命令 . model は , 簡略セグメント疑似命令 に対してメモリモデルを設定しま す。簡略セグメント疑似命令とい うのは . code, . data などて、す。し たがって , . model に huge を指定し , データセグメントの指定に . data を 使えば Turbo C 十十て、 huge モデル のデータセグメントが , モジュール名十 DATA ( たとえばファイル名が datal. c だ とすると DATAI DATA) という 名前て、すから , うまく設定てきるよ うに思えます。しかし , 実際には , . model<huge を指定しても . data は DATA SEGMEN T WORD PUBLIC 'DATA' と同等の意味し かありません。また DATA セグメ ントはグループの対象になってい るためにリンカは datal. asm, data2 . asm て定義している arrayl, array2 というデータを同 じセグメントに配置しようとしま す。 arrayl と array2 はそれぞれ 50 K バイトずっ確保しますのて , 合計 すると 64K バイトを越えてしまいま す。て、すから , datal . asm, data2. asm の簡略セグメント疑似 命令はセグメント疑似命令を使っ て書き換える必要があります。た 150 C MAGAZINE 1 1 9 ホーランドジャパン lnformation from Compiler Makers 5 : 7 : とえば List 1 は List 2 のように変 更すればうまくリンクてきるはず て、す。また , List 1 の function. asm て、 arg 疑似命令が使われているの て , それぞれのプロシージャの先 POP bp mov sp,bp 後のほうの mov bp,sp push bp 頭ての は削除し , さらにプロシージャの最 も削除してください このままだ 原則としてお答えてきませんが , 具 体的なご指摘をいただければ , わ かる範囲てアドバイス程度のお答 えをしています。 List 3 を TCC. EXE< コンパイル させる場合 , MS-DOS のプロンプ トから , tcc -ml test. c work. asm と入力すると思います。マップフ ァイルを作成して , セグメントの配 置がどうなっているか見ると Fig. 2 のように , ユーザ側て、定義したセグ メントが最後に配置されています。 最後から 2 番目が STACK となっ ていますが , これが問題になってい るようて、す。 Turbo C 十十て、スタ ックサイズはスタートアップルー チンて決定されますが , このセグ メントが基準になるのて , 指定しな ければ 4K バイトのエリアがスタッ クとして割り付けられます。 これはユーザ側て定義した Soun Turbo C 十十 Ver. 1.0 のように変更してはいかがてしょ 指定してセグメントの配置を Fig. 3 うにセグメントに ' DATA ' クラスを す。これを回避するには List 4 のよ ていますのて、 , 暴走してしまいま 関数への戻り番地が壊れてしまっ CIearWorkArea 関数から main BiosWorkArea を 0 クリアした後は , ェリアを飲み込んてしまい S 。 und StackBiosWorkData がスタック kData て定義してしまうと , 今度は 30K バイト以上も SoundBiosWor えす問題が起こらなかったのてす。 クの底のほうにあるため , とりあ は IK バイト程度て , これがスタッ イト , ューザ側て定義したエリア た理由は , スタックのトップは 4K バ 域を追加する前に正常に動いてい しまった状態て、す。 30K バイトの領 がスタックエリアに飲み込まれて dBiosWorkData というセグメント とオーバードライプしてしまいま す。 Q Turbo C 十十で PC -9801 シリ ーズ用のサウンド B ℃ S ライプラリ を作成しようとしています。サウ ンド引 OS では B ℃ S 用のワークエリ アを設定する必要があり , オフセッ ト 0 でセグメントの ES に設定しなけ ればなりません。はじめは fa 「 m 訓 oc か allocmem を使用しようと考えま したが , fa 「 m 訓 oc ではオフセットが 必ず 0 になるとはかぎりませんし , 訓 ocmem 関数は m 訓 oc と共存で きないのでライプラリを作成する 上では使用しないほうがよいと考 えました。結局 , List 3 のように新 しいデータセグメントを定義して それをワークエリアとして使うプ ログラムを作りました。最初はう まく初期化できていたのですが , 3 番目のデータ領域を追加した途端 に初期化ルーチンから返らずに暴 走してしまいます。プログラムは ラージモデルで作成しています。 A サポートセンターてはユーザ の作制されたプログラムが動かな いというようなお問い合わせには Turbo Link Version 3.0 Copyright (c) 1991 Borland lnte 「 national E 「「 0 「 : Segment DATA exceeds 64K E 「「 0 「 : Segment DATA exceeds 64K E 「「 0 「 : Segment DATA exceeds 64K E 「「 0 「 : Segment DATA exceeds 64K E 「「 0 「 : Group DGROUP exceeds 64K Available memory 226256 List 1 datal. asn 1 : . 一 huge c 2 : .data 3 : publ ic c arrayl 4 : arrayl db 50 事 1000 dup(?) 5 : ends 6 : end ta2. asm 10 : 9 : 8 : 6 : 3 : 1 : for (i = 0 : i く 50U 事 10000 : i + + ) 0utChara(array2[i]); AllBit0n ( 50U 本 1000U. array2) : for (i : 0 : i く 50U 事 100 側 : i + + ) 0utChara(array1[i]): AllBit0n ( 500 事 1000 乢 arrayl) : long int i : 3 : nain() 2 : extern c 「 a 時 2 [ 500000 ] : 1 : extern 0 r arrayl [ 5000 圓 ] : 6 : end 5 : ends 4 : array2 db 50 事 1000 dup(?) pub lic c array2 2 : . data 加 d huge 0