出力 - みる会図書館


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

1. 月刊 C MAGAZINE 1990年2月号

しているのて、はなく , 標準出力というファ イルに出力しているのて、す。何も指示しな い場合には , 端末が標準出力とみなされて 端末に出力されます。これは , 必要に応じ てほかのファイルに切り換えることがてき ます。 標準出力が , どうして端末への出力にな るのて、しよう。 UNIX て、は , 端末やプリンタなどの装置も ファイルのように扱える仕組みになってい ます。実際には , ディスク上のファイルと 端末はまったく違うものて、すが , その違い を UNIX が吸収してくれるのて、す。だから , コマンドにとっては , ディスク上のファイ ルに出力するのもプリンタに出力するのも 違いはありません。このおかげて、 , 「プリン タ出力用」 , 「ディスクのファイル用」などの コマンド群を作成する必要もなく , あるい は大型機の OS などて、使われるややこしくて ごく 使いにくい指示を用いる必要もなく , 簡単て、柔軟な操作がて、きるのて、す。 こまて、の説明て、「「端末』というファイル」 の意味がご理解いただけたて、しようか。、、〉〃 記号は UNIX に「標準出力をこちらのファイ ルに切り換えてくれ」と指示するもて、す。 こて、注意しておかないといけないのは , 、ツ′ て、指示したファイルがすて、に存在している 場合 , そのファイルは破壊され , 新しいフ ァイルが作成されるということて、す ( Fig. 4 ) 。不用意に標準出力をリダイレクト すると , 大事なファイルを壊してしまう可 能性があります。これを防ぐために set nocl obber をしておきます。こうすると , 存在するファ 、、〉クを用いてリダイレクトしようと イルに してもエラーになります。その場合に強制的 に書きたしたいときは、ツ〃を用います。 似たような記号て、すが , 、、 > 〉〃とい うのもあります。これは既存のファイルの 末尾に書きたしてほしいという指示て、す。 先ほども書きましたが , MS-DOS とは違 い , UNIX のテキストファイルはファイルの 末尾にコントロール D がありませんから , そ のまま書きたしてもまったく支障はありま せん。もし , 指定したファイルが存在しな い場合には , 新しいファイルが作成されま す。先ほどの、、 set noclobber" をしておき ますと , 指定したファイルが存在しなかっ た場合はエラーになります。その場合 , 強 制的に存在しないファイルにリダイレクト するには , 、、〉〉 ! クを用います。 日記のファイルを例にとると , 当日に書 いた部分を前日まて、のファイルの最後に、、〉〉ク を使ってつなげばいいわけて、す。こうする ことによって , 日記のファイルはその日の 部分が書きたされて更新されます。 UNIX には標準ェラー出力というものもあ ります。これは MS-DOS にはありません。 コンパイラなどのエラーメッセージは , の標準工ラー出力に出力されます。通常は 端末が標準ェラー出力て、す。標準ェラー出 力は、、〉クや、、〉〉〃などて、は切り換えること はて、きず , 端末につながったままて、す。て、 すから , 何か異常が起こったときにはすぐ わかるわけて、すが , コンパイラのエラーメ ッセージを紙に書きうつして , 後て、その紙 を見ながらデバッグするというのはあまり スマートとはいえません。ファイルに出力 したほうがなにかと便利て、す。ファイルに 出力するときは , 、、〉 & クや、、〉〉 & クを用いま す。ただし , 、、〉 & 〃は標準出力と標準工ラー 出力との両方を切り換えるものて、すから , 別々に切り換えたいときは Fig. 5 のようにし てください。これも , 、、 set noclobber" して 、、ゾや、、〉〉〃と同様に , 工ラーを おくと , 出してくれます。強制的に実行したいとき には、、〉 & ! 〃 , 、、〉〉 & ! クを用います。 入力にも , 出力と同じメカニズムが存在 します。各コマンドは「標準入力」というフ ァイルから入力しているのて、す。そして、、くク を用いて標準入力を切り換えることがて、き ます。これが何の役に立つのて、しよう。 例をあげると , 「たくさんのファイルに , あ る単純な編集をしたい」ときに役立ちます。 たとえば , UNIX のエデイタのひとって、あ る ex に , ex に対して行うべき ex のコマンド を書いておき , これをリダイレクトして使 えば ( Fig. 6 ) , ファイル名が、、 sample. 1 クて 大特集・最新 UN Ⅸ考察 大特集最新 UN Ⅸ考察 55 DOS のパイプて、はてきないことも , UNIX 違いは処理速度だけてはありません。 MS- MS-DOS のパイプと UNIX のパイプとの 理速度が速いわけてす。 を作成することなく , 並列動作するのて、処 して処理し始めるからて、す。中間ファイル more コマンドがそれを自分への標準入力と コマンドが標準出力にデータを送り出すと , ンドと more コマンドが同時に動き始め , cat 実行時間は変わりません。これは , cat コマ 合と違って cat コマンド単独のときとさほど とを UNIX て、行うと (Fig. 9 ) , MS-DOS の場 す。先ほど MS ー DOS て、行った操作と同じこ く , 複数のコマンドを同時に動かしていま イル ( テンボラリファイル ) をつくることな それにくらべ , UNIX のパイプは中間ファ す (Fig. 8)。 せているだけなのて、 , 時間がかかるわけて、 ァイルを用いてふたつのコマンドを実行さ MS-DOS のパイプは , たんにテンボラリフ 時間がかかったのて、 , 驚きました ( Fig. 7 ) 。 ころ , TYPE コマンドにくらべてずいぶん の出力をパイプて、 MORE につないて、みたと を操作したとき , ちょっと TYPE コマンド りもずっと優れています。初めて MS-DOS し , UNIX のパイプは MS-DOS のパイプよ て、す。 MS-DOS のパイプもそうて、す。しか 後ろにあるコマンドの標準入力にすること の前にあるコマンドの標準出力をパイプの ることだと思います。パイプとは , パイプ 標準入力の最大の利点は , パイプが使え バブ トロール D はファイルに含まれません。 なお ,MS-DOS のコントロール Z と違い , コン いつまて、もファイルの終わりになりません。 がないと , 端末から読み込んて、いるときに るしにすり換えてくれます。この約束ごと 文字をファイルの最後に到達したというし す。そうすると , UNIX がコントロール D の を示すために , コントロール D を入力しま て、きます。端末からの入力が終わった あるファイル中にある空白行をすべて削除

2. 月刊 C MAGAZINE 1990年2月号

ればならないため , 各自が定義したクラスは , 十分 な機能をもっことがて、きません。 C 十十のクラスライプラリて、提供されている入出力 機能は , Strea 爪クラスおよびそれに関する演算子〉〉 (get from), くく (put t0 ) の定義により実現されてい ます。この Stream クラスを使って , あの有名なプロ グラムを記述すれば , 以下のようになります。 cin 〉〉 sh 〉〉 du; double du; short sh; VOid main( ) #include く stream. h 〉 同様に入力も以下のように書くことがて、きます cout くく "HeIIo, WorId" VOid main( ) #include く stream. h 〉 istream は入力用のクラスとして定義されています。 ostream は出力用のクラスとして定義され , extern ostream cerr; extern ostream cout; extern istream Cin; stream. h て、以下のように記述されています。 cout, cin は , Stream クラスの変数て、あり , 演算子出力関数 ( outputope 「 ato 「 s ) ostream& fO 「 m(constcha 「 *fmt. OSt 「 eam& ostream . :put(const char* St 「 ): OSt 「 eam& OStream fiush(void); 0S1 「 eam& ostream : : ut(cha 「 c) : 基本出力関数 ( p 「 im はⅳ e output functions) 関数のÄÉ(inte 「 face function p 「 ototype) [ 表 1 ] ost 「 eam の出力関数 用意されているのて、 , 例のような記述がて、きます。 は , 基本データ型などについての演算子くく , 〉〉は 入力からのデータが格納されます。 Stream クラスて、 WorId" は標準出力に出力さみつ sh および du は標準 する入力や出力を意味します。上の 2 例て、は、、 HeIIo , のリダイレクト記号のように使われ , cin や cout に対 呼ぶ ) 。例のように演算子〉〉 , くくは , UNIX や DOS ファイルに接続された Stream の変数をストリームと stdin, stdout, stderr に相当します (cin のように そして , cin, cout, cerr は , C の標準ライプラリの 実際に内部的には型のチェックが行われ , 適当な演 算子関数が呼び出されます ( 用意されている演算子関 数については表 1 , 2 を参照 ) 。次は , Stream クラス のインタフェイスの解説て、す。 入出力関数 表 1 に ostream クラスの出力関数の一覧を示しま す ( 注 12 ) 。 ostream の基本出力機能は , put( ) および flush( ) により提供されます oput(char) は stdio. h の putchar( ) に相当し , 引数の文字をストリームに書 き込みます。 flush ( ) は ostream のノヾッフアに残って いる文字を強制的に吐き出させます。ただし , ostream のディストラクタは flush ( ) を勝手に呼び出すため , flush( ) を意識して呼ぶ必要があるのは , exit ( ) など て、プログラムが終了するときだけて、しよう。 同様に , 表 2 に istream クラスの入力関数一覧を示 します。 istream の基本入力機能には , get( ) および putback( ) があります oget(char&) は単に 1 文字を ストリームから読み込み , get(char*, int, char) は 文字列をストリームから読み込みます。 putback( ) は読み込みすぎた文字をストリームに戻すための関 な形式て、連続して出力て、きます。定義されている出 operator 〉〉が定義されている型て、あれば , 例のよう す。表 1 , 2 に示したように演算子関数 operator くく , ます。そして連続した呼び出しが可能になっていま みに使った iostream 変数 ( この場合 cin ) の参照を返し す。 istream の演算子関数 operator 〉〉て、は , 読み込 使った ostream 変数 ( この場合 cout ) の参照を返しま ostream の演算子関数 operator くくは , 書き込みに たが , 処理系は Fig. 5 のように解釈します。 れます。先ほどの例て、も , 演算子関数を使用しまし 算子くく , 〉〉に多重定義された演算子関数が多く使わ 常あまり使われません。実際のプログラムて、は , 演 し , Stream の基本入出力関数 (put, get など ) は , 通 数て、あり , stdio. h の unget( ) に相当します。ただ OSt 「 eam& OSt 「 eam& OSt 「 eam& OSt 「 eam& OSt 「 eam& 0 St 「 ea rn & OSt 「 eam& OSt 「 eam& ostream& OSt 「 eam& ostream& OSt 「 eam& ostream : OSt 「 eam : OSt 「 eam : OSt 「 eam : OSt 「 eam : OSt 「 eam : OSt 「 eam : OSt 「 eam : OSt 「 eam : 0S1 「 eam . OSt 「 eam : OSt 「 eam : :operato 「くく (const streambuf& sb); : ope 「 a10 「くく ( const whitespace& (s) : :operato 「くく (cha 「 c); : ope 「 at0 「くく ( sh0 「 t n) : :ope 「 ator くく (unsigned sh0 「 t n); : ope 「 atO 「くくい nt n); :ope 「 atO 「くく (unsigned int n): : ope 「 atO 「くく (long n); :ope 「 at0 「くく (unsigned long n); : ope 「 at0 「くく (float n) : : ope 「 atO 「くく ( doub 厄 n); :ope 「 atO 「くく (const char* s); 関数の機能 (interface function description) c の値を書き込む st 「 eambuf に残っているものを書き込む s なの内容を書き込む fp 「 intf 形式の書式で書き込む 引数 sb の内容を書き込む 何もしない 整数値 c を書き込む 整数値 n を書き込む 整数値 n を書き込む 整数値 n を書き込む 整数値 n を書き込む 整数値 n を書き込む 整数値 n を書き込む 浮動小数値 n を書き込む 浮動小数値 n を書き込む 文字列 s を書き込む 補足 (GNU) (GNU) (AT&T) (AT&T) (GNU) (GNU) 注 12 GNU の Stream は AT&T のものと多少異な る。表の機能の欄に GNU と あるのは GNU のライプラリ のみ , AT&T とあるのは AT&T 1 . X のライプラリの みの機能てある。 C + 十プログラミング入門 97

3. 月刊 C MAGAZINE 1990年2月号

のパイプだとて、きることがけっこうあります。 tee コマンドは , ファイル名を引数として とり , 標準入力のデータを , 標準出力と引 数て、示されたファイルのふたつに出力する こに載せた操作例も , この tee ものて、す。 コマンドを用いてファイルに記録して編集 したものて、す。それには csh を起動するとき に , パイプを通して tee につないて、おけばい いのて、す ( Fig. 10 ) 。 MS-DOS のパイプには こんな芸当はてきません。 なぜて、きないかというと , tee が csh と同時 に動作し , csh の入出力を妨げることなく , ファイルへの出力を続けなければならない からて、す。いい換えると , csh は端末に対す る入力に応じた動作を行い , 対応する出力 を標準出力に対して行います。この出力は ただちに tee コマンドによって処理され , tee コマンドの標準出力に出力されなければな りません。そうて、ないと , ユーザは自分の 命令に対して csh が行った動作をそのときに 見ることがて、きないのて、す。これに近い とを MS-DOS て、試してみましよう。ただ し , MS ー DOS システムには tee コマンドがな いのて、 , 代わりに MORE を使います。ユー ザの入力に対して COMMAND.COM がいっ ものように反応し , かっ記録のファイルが 正しくて、きていればいいわけて、すが , うま くいきません ( Fig. 11 参照 ) 。 COMMAND. COM はユーザに対して対話的に動くものて、 A>type sample. 1 ー mo 「 e This is "sample. 1" file. Fig. 8 ( MS ー DOS のバイプに相当するコマンド群 ) す。 MS ー DOS て、のパイプは , 順にコマンドを 起動していくものて、すから , 対話的に動作す るコマンドて、ある COMMAND.COM をパイ プとともに用いることはて、きないのて、す。 実は D-SheII も同じ欠点をもっています。と いうよりこれは MS ー DOS の欠点なのて、す。 UNIX のパイプがなぜ強力かというと , 標 準入力 , 標準出力の切り換えと , 複数のコ マンドが同時に動くからて、す。 て、は , パイプて、つなぐような関係にない コマンドを , 複数同時に動かすことはて、き ないものて、しようか。 ノ、クグラウンド プセス UNIX て、は , ハードディスクをユーザ全員 て、使用しているのて、 , 大きなファイルはほ かの人の迷惑になります。 Fig. 12 を見てく ださい。大きなファイルがあります。人の 迷惑になりますから , compress コマンド を使って圧縮しましよう ocompress コマン ドは , LHarc のように複数ファイルを圧縮す ることはて、きませんが , 同じようなコマン ドて、す。なお , compress すると , 元のファ イルは削除され , 代わりに元のファイルの 名前の最後にツ Z" をつけた名前をもつフ ァイルが作成されます。これが compress さ れたファイルて、す。圧縮されたファイルを Fig. 10 解凍するときには uncompress コマンドを用 います ( Fig. 13 ) 。 処理内容からすれば当然て、すが , かなり 時間がかかります。 UNIX て、は , このような 場合 , 処理が終わるまて、待っている必要は ありません。コマンドの最後に、、 & 〃をつけ て実行を開始を指示すれば , 次のコマンド を動かすことがて、きます ( Fig. 14 参照 ) 。 たとえば compress コマンドの最後に、、 & 〃 をつけて実行させると , すぐにプロンプト が帰ってきますが , compress コマンドが速 くなったわけて、はありません。 コマンドの最後に、、 & クをつけると , コマ ンドの実行を開始しただけて、 , 終了する前 にプロンプトが帰ってきて , 次のコマンド の実行がて、きるようになります。もちろん , compress コマンドはきちんと実行されてい ます。 ls コマンドを実行してみると確認て、き ます (Fig. 15 参照 ) 。まだ compress て、圧縮さ れていないファイルもありますが , いくっ かのファイルの名前の後ろに 、、 Z" 力すつい ているのて、 , compress コマンドがきちんと 働いていることは確かて、す。 コマンドに、、 & 〃をつけて実行すると , 続 行中のコマンドと並行して , ューザは別の 仕事にかかれるわけて、す。 このように、、 & 〃をつけてコマンドを実行 させたものを「バックグラウンドプロセス」 と呼びます。バックグラウンドプロセスに % csh ー tee sample. ope 「 ations sample. 1 sample . 4 sample. 2 sample. 5 % cat sample. 1 This is "sample. 1" file. % D % cat sample. operations sample. 1 sample. 3 sample. 2 sample. 4 This is "sample. 1 " Fig. 11 command ー more sample. 3 sample. 5 A>type 「 eadme. doc > く一時的ファイルの名前 > A> more くく一時的ファイルの名前 > % cat sample. 1 ー more This is sample. 1" 56 CMAGAZINE 19 2

4. 月刊 C MAGAZINE 1990年2月号

( = 命令 ) はないのだな」と判断して終了して トロール J がこなければならないということ はありません。 C 言語を勉強された方は、、 \ n ク しまいます。 いま , 「「端末』というファイル」と書きま が改行動作を示す 1 文字て、あることをご存じ したが , 「端末がファイルだって。そんな馬 て、しよう。 鹿な ! 」と思われる方もいらっしやるて、しよ 余談て、すが , MS - DOS て C 言語の処理系を う。しかし , これは決してまちがってはい 使う場合には , C 言語流の「改行は 1 文字」と いう考え方と , MS ー DOS 流の「改行は 2 文字」 ません。 という考え方の調整をしなければなりませ されています。コントロール Z はテキストフ ん。もともと C 言語は UNIX 用に開発された ァイルの末尾のしるして、す。 ものて、すから当然のことてすが , この点て、 UNIX のテキストファイルの構造も MS- UNIX は , MS-DOS よりも C 言語と親和性が DOS のそれとよく似ています。 UNIX のテ 多くのコマンドは , 端末に実行結果を出 高いといえそうてす。 キストファイルて、は , 改行はコントロール 力します (Fig. 2 ) 。たとえば ls を実行する UNIX て、は本質的にファイルの種類は 1 種 J の 1 文字て、表されます。ただし , UNIX のテ と , 自分がどんなファイルをもっているか 類しかありません。ただ , その中に改行文 キストファイルには末尾のしるしはありま 字やそのほかのコントロール文字があれば , わかります。この結果をファイルにとって せん。ファイルの大きさからファイルの最 おくにはどうしたらいいのて、しよう。 MS- それに従った動作をするだけのことて、す。 後が決まります。 UNIX が C 言語て、記述され DOS と同様に , UNIX て、も、、〉〃記号を使っ この約束ごとは UN Ⅸの世界て、は広く守られ ていることはご存じだと思います。つまり , て , ファイルに出力することがて、きます ています。 sh や csh なども , 「端末」というフ UNIX て、はテキストファイルとしての特別の こに UNIX のすばらしい仕組み ァイルから入力を受け取っているのて、 , コ (Fig. 3)。 ただ , 文字コードが入ってい 構造はなく , コマンドは端末に出力 ントロール D を受け取ると「これ以上の入力 があります。実は , るだけて、す。コントロール M の次にはコン login: cmaga passwd. % D login. くみに準出力 , Fig. 3 Fig. 2 % > contents % cat contents total 5 tOtaI 5 30 Jan 1 8 06 : 1 7 sample. 1 . 2 30 Jan 18 06 : 17 sample 30 Jan 1 8 06 : 1 7 sa m ple. 3 30 Jan 1 8 06 : 1 7 sam ple. 4 30 Jan 1 8 06 : 1 8 sample. 5 1 cmaga 1 cmaga 1 cmaga 1 cmaga 1 cmaga 30 Jan 1 8 06 : 1 7 sample. 1 30 Jan 18 06 : 17 sample. 2 30 Jan 18 06 : 17 sample. 3 30 J a n 1 8 06 : 1 7 sa m ple. 4 30 Jan 18 06 : 18 sample. 5 1 cmaga 1 cmaga 1 cmaga 1 cmaga 1 cmaga sample. 1 sample. 2 sample. 3 sample . 4 sample. 5 % (cat sample. 6 > output) > & e 「「 0 「一 output % cat output % cat e 「 ro 「一 output sample. 6: NO such file 0 「 directory sample. 1 sample. 2 % cat sample. 1 This is "sample. 1" % > sample. 1 % cat sample. 1 sample. 1 sample. 2 sample. 3 sample. 4 sample. 5 sample. 5 sample. 3 sample. 4 % cat ex. orde 「 9 だ $/d : wq % ex sample. 1 < ex. 0 「 de 「 sample. 1 " 5 lines, 45 characters 54 CMAGAZINE 19 2

5. 月刊 C MAGAZINE 1990年2月号

c 言語学講座 メインルーチンは , おおまかには , がどのような構成になっているかを知りま 味 ) て、す。 1 . ファイルをオープンする List3 て、はテープルは Table という名前て、 せん。 List2 の 124 行目にある , 2 単語を読み込む apply(printone); MAXENTS( このリストて、は 4000 ) 個のデー 3 単語を登録する (lookup, insert) という呼び出して、 , テープル管理ルーチン タを管理て、きる配列になっています。イン 4. ファイルの終わりまで 2 , 3 をループ に printone へのポインタが渡され , テープ デックスは Endp て、 , 配列の添え字て、はな 5. ファイルをクローズする ル管理ルーチンのなかから呼び出されます。 く , ポインタにしてあります。 Endp は Table 6 . 結果を出力する ( app ツ ) apply のなかにはループがあり , そのなかて、 を指すように初期化しておきます。 Endp が という処理の流れになります。 printone を呼び出すことによって , すべて 指しているのは「次に使用されるエントリ」 List2 がメインルーチンのプログラムて て、す。 Fig. 1 に Table と Endp の関係を示し の単語を出力しています。 す。 関数へのポインタをうまく使うことによ てあります。 MAXLEN は単語の長さの最大値を規定 って , メインルーチンのなかにテープル管 データを登録する install て、は , 先頭から 理アルゴリズムに依存する部分を埋め込ま しています。 順番にデータを登録していきます。まず , main て、はコマンドラインのパラメータの なくてもいいようにすることがて、きます。 配列に余裕があるかどうかを調 ~ ます : h 数を調べます。パラメータなして、起動され ー bound というマクロは配列の上限のアトレ たときには (argc = = 1 ) , 標準入力から単語 スを返します。 Endp が h—bound(TabIe) よ を読み込みます。パラメータをあたえると , り小さいときには , Endp が指しているエン そのファイルから入力します。複数のファ 線形法は記号表のもっとも簡単な構成方 トリにキーを登録します。そして , そのェ イルを指定されたときには , 順番にファイ 法て、す。この方法て、は , テープルは管理す ントリの ITEM 型構造体のアドレスを返し ルを処理していきます。 るべきデータの「配列」として実現されます。 ます。 getword は単語を入力する関数て、す。長 単純な配列を管理するだけて、すから , プロ もし Endp が h—bound(Table) と等しいか い単語が入力されたときて、も , 最後まて、認 グラムは小さくてすみます。 大きいときには , すべてのエントリを使い しかし , 配列て、はコンパイル時にテープ 識はしますが , len ー 1 文字まて、しか格納し 果たしたことを示しています。この場合は ルのエントリ数が決まってしまうため , 実 ません。文字列の終わりを示す、、¥ O クを格 NULL を返してエラーの発生を知らせま 納するために一 1 が必要て、す。 装されているすべてのメモリを効率的に利 す。 単語の終了を認識するのは「単語て、はない 用することが難しくなります。メモリをた lookup はテープル内のデータをキーて、サ 文字を入力した」ときて、す。つまり 1 文字余 くさん実装しているシステムて、は , ほとん ーチします。実際には単純に配列の先頭か 分に入力していますから , 最後に ungetc て、 どのメモリが使われずムダて、しようし , メ ら順番にキーを比較していきます。という 読みすぎた文字を戻しておきます。 モリをあまり実装していないシステムて、は , ことは , 配列の先頭のほうにあるキーは早 ファイルの終わりに到達したときには , この配列を実行時に確保て、きず , プログラ く見つかりますが , 後ろのほうにあるもの ムが動かないことがあるかもしれません。 getword は NULL を返します。単語を入力 を見つけるためには比較をかなりの回数繰 配列として実現したテープルには , どこ て、きたときには , バッファ buf を返します。 り返さなければなりません。この比較処理 まて、データを登録しているのかを管理する の平均回数は , n を登録されているキーの数 この関数のパラメータやリターン値は ,fgets とすると , n / 2 て、表されます。 n を 100 とする ためにインデックスが必要になります。配 と同じにしました。 列とインデックスを使ったテープル管理ル regword は入力した単語を登録します。 と 1 回のサーチに平均 50 回の比較が必要にな ーチンを List3 に示します。 まず lookup を呼び出して , この単語がすて、 りますから , はっきりいって「遅い」アルゴ List3 て、管理するのは ITEM 型構造体だけ リズムて、す。 に登録されているかどうか調べます。登録 てはなく , キーも必要て、す。今回の例て、は されていないときには lookup は NULL を返 lookup は , サーチに成功すると見つけた キーは工 TEM 型構造体のメンノヾて、ある word してきますから , そのときには install て、新 IT 刊 M 型構造体のアドレスを返し , 失敗す と同じなのて、すが , テープル管理ルーチン たに単語を登録します。 lookup が登録され ると NULL を返します。 て、必要こするデータは word とは別に格納し ている構造体へのポインタを返してきたと apply は Table に登録されているすべての ています。テープル管理ルーチンは ITEM きには , count をひとっ増やしてやるだけて、 工 TEM 型構造体に func を実行します。 型の構成と無関係にしておけば , 将来工 TEM 終わりて、す。 全体的に単純なループて、処理が記述され 型を変更しても List3 を変更する必要はあり printone は ITEM 型構造体を出力する関 ていることがわかると思います。 ません。配列の要素の型は , キーと ITE M 数てす。単語と出現回数をベアにして標準 線形法は単純て、すから , 管理すべきテー 型をメンバとする構造体 ENT ( ェントリの意 出力に書き出します。この関数はテープル プルが小さいときや , とりあえずプログラ C 言語雑学講座 129 線形法

6. 月刊 C MAGAZINE 1990年2月号

Fig. IO 「 m の使用例 1 5 : OO 04 : 1 7 02 : 45 1 9 ・ 41 1 5 : OO % -IF total drwxr—xr—x d 「込Ⅸ「一 X 「一 X d 「Ⅸ「一 X 「一 X % 「 m filel 2 shOji 2 shOji ShOji shOji 2 shOji shOji shOji file2 1 1 1 1 5 1 2 384 1 1 9 田 2 6 5 1 2 4053 mbox 405 mbox Apr Nov Nov Nov Ap 「 NOV Nov 1 1 6 1 6 1 3 1 1 6 1 6 1 9 1 9 . ・ 4 5 ・ 4 5 News/ data/ filel file2 mail/ mbox memo News/ data/ % 「 m file2 file2 : 444 mode ? % 「 mdir N ews/ % 「 m -f fiIe2 News/ News data/ mail/ data/ file2 mail/ mail/ ・ ( f ⅱ el を削除 ) memo ・・ ( f ⅱ e2 は書き込み禁止であることを表示。そのままリター ・ ( オプション f により強制的に削除 ) m e m 0 すると削除されない ) ン 「 mdi 「 : data: Di 「 ectory not empty % 「 m ー「 data News/ mail/ mbox mbox memo m e m 0 ・・ ( 「 mdi 「コマンドでは , ティレクトリの中にファイルがあると ティレクトリの削除はできない ) ・・ ( ここでオプション「を指定して「 rn コマンドを実行する ) ・・・ ( これで , ディレクトリこと削除された ) するというものて、す。この cat に対応するコ マンドは正確には MS ー DOS には存在しませ んが , 同様な使い方がて、きるものとして COPY コマンドが挙げられます。 A 〉 COPY くファイル名〉 [ 十くファイ ル名〉・・・ ] CON すなわち複数のファイルを連結してそれ をテンヾイスファイルのコンソールにコピー をするというものて、す。このとき , COPY は cat と同様な動作をします。 こて、は解説しませんが , リダイレクシ ョンて、 cat の出力先を変更することがて、きま す。そのオペレーション例を Fig. 13 に示し ておきます ( リダイレクションについては STAGE5 を参照してください ) 。また , cat の オプションの代表的なものに n がありま す。これは , ファイルの行番号もいっしよ に出力するものて、す。このほかの数種類の 38 CMAGAZINE 19 2 オプションは , こて、は省略します。 そほかのコマンド 以上て、ファイル操作の基本的なコマンド の解説を行いましたが , ーこからは MS-DOS と対応しているそのほかのコマンドについ て解説します。 ファイルの内容を表示させるコマンドと しては cat のほかには more があります。これ は画面単位て、ファイルの内容を表示させる のて、 , ファイルの内容を見落とさずにすみ ます。この占て、は MS-DOS の MORE とほと んど同じて、す。しかし MS-DOS の MORE に はファイルの 1 画面分の情報を表示し , ス ペースまたはリターンキーて、次の表示を行 うだけの機能しかないのに対し , UNIX の more はファイルの内容を 1 画面分表示する と , そこて、出力は停止されプロンプトを表示 しサプコマンド入力待ちの状態になります。 表示が停止したときの more のプロンプト に対して , スペースを入力すると 1 画面 , ー囿を入力すると半画面スクロールし 対して v と入力すると , このエデイタを起動 してⅵがありますが , more のプロンプトに UNIX 上て、サポートされているエデイタと は , プロンプトに対して q を入力します。 読み飛ばします。 more を終了するために て、指定すると適合するパターンの箇所まて、 索したい文字パターンを正規表現 ( STAGE3 ) をします。また , スラッシュ ( / ) に続いて検 ます。リターンを入力すると 1 行スクロール 日示 date ステムの時刻を変更することもて、きますが , 月日時分 ) て、現在の時刻 , 日時を指定してシ (GMT) て、表示されます oyymmddhhmm( 年 ョン -u を指定するとグリーツジ標準時 実際の表示を Fig. 14 に示します。オプシ % date C-uJ [ く時刻〉 ] に相当します。書式は次のとおりて、す。 date て、す。これは MS-DOS の DATE/TIME 現在の時刻 , 日付を表示するコマンドが 載せることがて、きます。 広く公開されているコマンドなのて、簡単に ドリングされているわけて、はありませんが , 能になっています。 UNIX にはじめからバン 画面表示コマンドて、 , 逆方向表示なども可 きました。 less はエデイタ並の機能を備えた 機能な less コマンドも使われるようになって 余談て、すが , 最近て、はこの more よりも高 移行することもて、きるのて、す。 を見るだけて、なく , そのファイルの編集に します。つまり , more て、はファイルの内容 一般ユーザには許されて これを変更することはスーパーユーザにの いません。 み許されており , ー数の乍

7. 月刊 C MAGAZINE 1990年2月号

C 十十 プログラミンク 入門 注 10 C のライプラリが関数 の集合て、提供されたように C 十十のライプラリはクラス およびインタフェイスの集 合て提供される。 注 11 近々 , oops は IDEA C 十十用に移植されるようて、 型のものて、あるか実行時にならないとわかりません。 こて、 , サンプルプログラムから具体的な例を流 用しましよう。 Bignum クラスて、は , 自分の型名を返 すメンバ関数 name をもっています。以下に signed Bignum クラスの name 関数を示します。 char * : name(void) { signedBignum : return "signedBignum"; 上の例の配列 pb のそれぞれの型名を知るため , 次 の処理を記述します。 0 ; pb [cp] ; cp + = 1 ) { for (int cp char * pbname = ( * pb [ cp ] ). name( ) ; このとき , 関数 name が普通のメンバ関数て、あれ ば , この処理は期待どおりの結果にはならず , これ はすべて bignum : : name( ) て、あり , 戻される値は 、、 bignum" のポインタになります。 こうした派生クラス独自の性質の損失を避けるた めに , C 十十には , 仮想関数 (virtual function) と呼 ばれる機能が実装されています。この name 関数を仮 virtual char * name(void); / / 仮想関数にはキーワード、、 virtual 〃が必要 public: class bignum { のように宣言します。 想関数にするために , 基本クラスの宣言時に , 以下 C 十十の標準ライフラリ C 十十のデータ抽象化機能はより強力になっています。 合を極めて容易に実現してます。この機能によって , りを扱う際に , 欠くことのて、きない動的な関数の結 しています。仮想関数の機能は派生クラスのまとま その関数を呼び出すべきて、あることを処理系に指示 が仮想関数て、あることを宣言し , 派生したクラスが スがもっています。キーワード、、 virtual" は , 関数 ます。実際 , 型が何て、あるかという情報は , 各クラ *bignum" 、、 fIoatBignum" のポインタが返され びだされます。先ほどの例て、も、、 signedBignum" く型が判断され , 期待どおりの型のメンバ関数が呼 て、なければ型がわからない場合にも , 実行時に正し す。このように宣言された仮想関数 name は , 実行時 実際の関数の定義は , 普通のメンバ関数と同じて、 ある。 96 こて、は , 標準ライプラリの解説をします ( 注 10 ) 。と はいっても , この「標準」とい 5 表現には , 少し難が あります。ここて示すクラスが標準になり得るか , い つまて、標準て、いられるかは難しい間題て、す。 たとえば ,AT&T の release 1. X て、入出力機能を提 供していた istream/ostream クラス (stream. h) は ( 以下 istream/ostream クラスを総称して Stream ク ラスと呼ぶ ),release 2.0 の機能拡張にしたがって強 化され , iostream. h に定義されています。また , 現 在多くの処理系て、は , 付属しているライプラリが貧 弱て、あり , それを補うためには , 各自の努力により , 十分なライプラリを用意しなければなりません。開 発者の配慮により , フリーウェアになっているいく つかのライプラリを入手するのもよいて、しよう。代 表的なフリーウェアのライプラリには , Keith Gorlen 氏の 0 叩 s(Smalltalk ライクな階層化されたクラス 群 ) , Doug Lea 氏の libg 十十 (GUN C 十十付属のク ラス群 ) , Mark A. Linton 氏の InterViews ( X11 対応 の Graphic Toolkit) などがあります ( 注 11 ) 。これらのラ イプラリについては , 次回以降て、解説する予定て、す。 今回は貧弱なライプラリに含まれるクラス群を解説 します。 前回および今回の解説によって , クラスはその実 現の詳細をインタフェイスて、あるメンバ関数より隠 した ( カプセル化した ) 抽象データ型て、あることが理 解て、きると思います。ライプラリの利用者にとって たいせつなのは実現の詳細て、はなく , そのインタフ ェイスということになります。以下の解説は , その インタフェイスの仕様を中心に進めます。また , 参 考に掲載する各クラスの要約された実現の詳細は , その設計の優れたお手本となることて、しよう。 入出力機能 これて、は , つねにクラスの内部構造を意識しなけ (void)fprintf(fp,"%f 十 j%f",c. real( ),c ・ imag( ) ) ; 〃複素数 ( complex ) 型の変数 c の出力 が , 一度実部と虚部を取り出し , 出力しています。 ばなりません。以下に複素数型の出力例を示します り , クラス型て、は一度基本データ型に変換しなけれ す。しかし , C の入出力機能が扱える型はわずかて、あ ログラミングて、は , 非常に多くのクラスを定義しま 不十分て、あるため , 用意されました。通常 C 十十のプ ラリの入出力機能て、は C 十十の言語仕様を活かすのに Strea 用クラスがあります。これは , C の標準ライプ に定義されクラスライプラリとして提供されている ていません。 C 十十の入出力機能としては , stream. h C + 十は C と同様に言語の仕様に入出力機能をもっ CMAGAZINE 19 2

8. 月刊 C MAGAZINE 1990年2月号

プロセス 大特集・最新 U N Ⅸ考察 本 STAGE は , 今まで MS - DOS を扱って きた方々に , UN Ⅸのプロセスを知っても らうことを目的としている。 M -b シングルユーザ , シングルタスの OS で あるのに対し UN Ⅸはマルチーザ , マ ルチタスクの OS である。したがうて , MS - DOS にできないことも UN Ⅸとできる。 MS - DOS は UN Ⅸをお手本のとっとし てつくられた OS なので , 似た部分も多い が , この点で両者は大きく異なっている。 りく 葉を聞い は , 複数 ことがで かせるこ ていただ くの方々か「プロセス」という言 ことかあると思うか , UNIX で 「プロセス」を同時に実行させる る。複数のプロセスを同時に動 かいかに便利であるか , 理解し たい。 本 STAGE て、 UNIX といった場合 , おもに BSD 系の UNIX を考えています。また , 最初 に注意しておきますが , UNIX て、は大文字小 文字は区別します。また , BASIC などとは 異なり , 大文字はめったに使いません。 UNIX て、は小文字を使うようにしてください UNIX を利用する上て、 , 必ず守らないとい けないマナーがあります。それは , ほかの 人に迷惑をかけないように注意するという ことて、す。 MS-DOS とは違い , UNIX はマ ルチューザ OS て、すから , たくさんの人が同 時に端末を通して UN Ⅸを操作することにな ります。 UNIX が各ューザを別々に管理して いるとはいえ , CPU の実体はひとっしかあ りません。自分が変なことをすると , ほか の人に迷惑をかけるかもしれないというこ とだけは忘れないてください。 よく「端末がおかしい」といってそのまま 放置する人がいます。これは , ほかの人が 三浦文 ンドインタブリタの sh, csh などを終了させ と , とくに設定しておかないかぎり , コマ また , うつかりコントロール D を・入力する ントロール Q を押してみてください てしまうことがあります。そのときにはコ くても何かの拍子にコントロール S を入力し いと思います。自分て、は押したつもりがな ル S よりは more コマンドを使ったほうがよ は解除てきません。もっとも , コントロー ル Q を押して解除します。それ以外のキーて、 コントロール S を押したときは , コントロー UNIX< も同じことがてきます。ただし , と思います。 を止められることはみなさんよくご存じだ きに , コントロール S を押すと一時的に画面 力が画面におさまりません。そのようなと クて、 DIR コマンドを実行するとコマンドの出 -DOS て、は , ファイルがたくさんあるディス してよくあるのが , コントロール S て、す。 MS この「端末がおかしい」状態になる原因と してはいけません。 い。 logout て、きないからといって端末を放置 ん。作業が終わったら必ず logout してくださ ティ上てもいろいろな問題が起きかねませ その端末を使えないだけて、なく , セキュリ てしまいます。場合によってはそのまま logout してしまいます (Fig. 1 ) 。 cat コマンドて、テキストファイルの中身を 見ることがてきます。このとき , まちがっ てテキストファイル以外のファイルを cat し てしまうと , 画面には通常の文字以外にさ まざまなデータが出力されます。その中に こて、あげたようなコントロール文字 は , も含まれています。したがって , cat コマン ドて、画面に出力するファイルがテキストフ ァイルて、ない場合 , 予期せぬ動作をする可 能性があります。くれぐれも , テキストフ ァイル以外は cat コマンドて出力しないよう にしてください U ー X における ストファイル UNIX のプロセスについて説明する前に UNIX におけるテキストファイルの構造につ いて簡単に説明します。 まず , MS-DOS のテキストファイルの構 造のおさらいをしましよう。 MS-DOS のテ キストファイルては改行はコントロール M, コントロール J の 2 文字が連続することて表 大特集最新 UN Ⅸ考察 53

9. 月刊 C MAGAZINE 1990年2月号

大特集・最新 UN Ⅸ考察 Fig. 13 % comp 「 ess data. ? total 460 ー代Ⅳ X 「一 ー代Ⅳ X 「一 ー代Ⅳ X 「一 ー rwxr ー Fig. 12 login: cmaga passwd : % total 760 ー rwxr ー ー rwxr ー ーハⅣ X 「一 1 86461 Jan 1 8 06 . ・ 33 data . 1 . Z cmaga 86461 Jan 1 8 06. ・ 33 . 2 . Z 1 data cmaga 86461 J a n 1 8 06 : 34 data . 3 . Z 1 cmaga 86461 Jan 18 06, ・ 34 data . 4. Z 1 cmaga 86461 Jan 1 8 06 : 34 data . 5 . Z 1 cmaga 1 1 51 2 7 3 J a n 1 8 06 : 33 data . 1 cmaga 1 51 2 7 3 Jan 1 8 06 . ・ 33 data . 2 1 cmaga 1 1 51 2 7 3 Jan 1 8 06. ・ 34 data . 3 cmaga 1 1 51 2 73 J a n 1 8 06. ・ 34 data .4 cmaga 1 51 2 7 3 Jan 1 8 06 : 34 data . 5 1 cmaga Fig. 14 Fig. 15 % total 588 ー代Ⅳ X 「一 ー rWX 「一 ー rWX 「一 % comp 「 ess data . ? & [ 1 ] 6516 % total 724 ー rwxr ー ー rwxr ー ー rVVX 「一 Fig. 16 86461 Jan 18 06 : 33 data . 1 . Z 1 cmaga 86461 Jan 18 06. ・ 33 data . 2 . Z 1 cmaga 86461 Jan 1 8 06. ・ 34 data . 3 . Z 1 cmaga 1 5 1 2 7 3 Jan 1 8 06 : 34 data . 4 1 cmaga 8 1 9 2 Jan 1 8 06 : 3 7 data . 4 . Z 1 cmaga ・ 34 data . 5 1 51 2 7 3 Jan 1 8 06. 1 cmaga 86461 Jan 1 8 06. ・ 33 data . 1 . Z 1 cmaga 1 5 1 2 7 3 Jan 1 8 06 : 3 3 data . 2 1 cmaga 24576 Jan 18 06. ・ 3 7 data . 2 . Z 1 cmaga 1 51 2 73 Jan 1 8 06. ・ 34 data . 3 1 cmaga 1 51 2 73 J a n 1 8 06 : 34 data .4 1 cmaga 1 5 1 2 7 3 Jan 1 8 06. ・ 34 data . 5 1 cmaga Fig. 17 % ps TIME COMMAND PID 幵 STAT 6509 co S O:OO csh 6 510 co S O:OO tee log 6525 co 日 0 : OO ps O:OI comp 「 ess data . ? 6391 co S % kill ー 9 651 6 Te 「 minated data . 2 . Z data . 1 data . 2 d ata . 3 . 乙 data . compress 4 . Z data . . 5 . Z data よっては必要ありません ) 。先ほどのプロセ して , ディスクに容量がない場合 , 仕事の リダイレクトやパイプが含まれてもさしつ ス ID をパラメータとして , kill コマンドを実 続行がて、きなくなり , compress コマンドは かえありません。 行すると , 止まります (Fig. 16 ) 。 立ち往生してしまいます。このような場合 , もっとも , すべてのコマンドがバックグ これて、あなたも今日からバックグラウン ラウンドプロセスに向いているわけて、はあ バックグラウンドプロセスを止めなくては ドプロセスが使えます。なお , プロセス ID いけません。しかし , バックグラウンドプ りません。リダイレクトしておかないかぎ がわからないときは , ps コマンドを使って ロセスは , 標準入力が端末につながってい バックグラウンドプロセスの標準入力 プロセス ID を確認してください (Fig. 17 ) 。 ないのて、 , コントロール D などを入力して止 はどこにもつながっていません。また , リ ダイレクトしておかないかぎり , 標準出力 めることはて、きません。 多少なりとも UN Ⅸのプロセスを理解して は端末にそのまま出力されます ( 設定によっ Fig. 14 を見てください。最初のプロンプ こて、説明したこ いただけたて、しようか。 ては出力を止めることもて、きます ) 。て、すか ト、、 % クの次の行に、、 6516 〃という数字が とは UNIX のプロセスのごく一部て、す。プロ あります。それは「プロセス ID 」という数字 ら , ューザとのやりとりを対話的に行うよ セスに限っても , まだまだ知るべきことは て、す。 UNIX て、は , プロセスはこのプロセス うなコマンド , たとえばスクリーンエディ たくさんありますが , 誌面の都合て、触れら タなどはバックグラウンドて、動かそうとし ID て、扱われます。この場合は , プロセス ID 、、 6516 〃のプロセスを止めればいいわけて、す。 れませんて、した。 てもうまくいきません。 とにかく , まちがいを恐れず , 一度 UNIX kill コマンドを使えばプロセスを止めるこ バックグラウンドプロセスがなんらかの をさわってみてください。きっと UNIX を気 工ラーて、止まるときはどうしたらいいて、し とがて、きます。オプションはいろいろあり に入っていただけることてしよう。 ますが , ここて、は強制的にプロセスを止め ようか。たとえばバックグラウンドプロセス る、、一 9 〃を用いることにします ( コマンドに の compress が中間ファイルを書き出そうと 大特集最新 UN Ⅸ考察 57

10. 月刊 C MAGAZINE 1990年2月号

五ロ はじめて学ぶ C プロクラミンク ます。今度は , 1 を 5 て、割ろうとしますが , ラーコードの 0 を返しています。これについ ます。 割る数 5 が割られる数 1 よりも大きいのて、 , ては , 今回詳しくやりましたね。 30 行目から 34 行目にかけては , 2 の因数を こて、プログラムは終了します。この計算 21 行目て、は , 入力が 1 だった場合の処理を 計算しています。 2 て、割りきれなくなるまて、 て 20 = 22 x 51 が求められたことになります。 しています。これは , つまらない解て、すが , 2 て割っていきます。 30 行目の、、 & & 〃とい このプログラムのアルゴリズムは , 基本 すべての場合に対応するためには必要て、す。 う論理積を表す論理演算子は , まず、、 i > = 的には上記のものと同じて、すが , 高速にす この際 , 正常終了を示すコードの 0 をシステ j" かどうかを判断し , 真ならば、、 i % j るためにくふうがしてあります。上記のや ムに返しています。 0 〃を判断します。両方とも真ならば , 式の り方て、は , 割る数を 1 ずっしか増加させてい 26 行目て、は , 後て、出力するときに必要な 値は真となり while 文が実行されます。 ないのて、 , 計算が遅くなります。このプロ のて、 , 変数 save に入力した値を保存してい 、、 i > = j" が偽ならば、、 i % j 0 〃は グラムて、は , まず 2 て、割っていきます。そし て , 2 て、割り切れなくなったということは , Fig. 6 初歩的な素因数分解の例 ( 20 の場合 ) 数字は絶対に奇数て、す。したがって , 3 より 大きな因数は , 2 ずつ大きくしていけばよい のて、す ( cf. 3 , 5 , 7 ・・・ こうすれば , 割る 数が 2 ずっ増えていくのて、演算速度が速くな ります。これて、 , もう十分だと思いますが , このプログラムて、はさらにひとくふうして います。素数を見ると Fig. 7 のように , 5 よ り大きい素数て、は , 2 増えて 4 増えて 2 増えて 4 増えて・・・・・・のようになっているのがわかる と思います。詳しい証明は数学に任せると こて、はこの性質を利用しています。 すると , さらに演算速度が速くなります。 それて、は List7 を見てください 1 行目て、は , 標準の入出力を宣言してある stdio. h をインクルードしています。こうす ることによって , 標準の入出力関数が使用 て、きましたね。ここて、 , # が最初についてい るということは , この #include も実はプリ プロセッサがやっている仕事なのて、す。 3 行目の #define は , この前に詳しく説明 したのて、もうおわかりて、しよう。定数を定 義しているのて、したね。 7 , 8 行目て、は , すべての変数を long 型て、 宣言しています。これは , て、きるだけ大き な数も因数分解て、きるようにするためて、す。 また , 8 行目て、宣言している p CMAX] , q [MAX] は , 素因数を入れるためのものて、 す。配列 p には素因数を代入していき , それ に対応する配列 q には , べき乗を入れていき ます。つまり , pg となっています。 10 行目から 13 行目にかけては , 配列の中 身を 0 に初期化をしています。この作業をし ないと , 配列の初期値が不定になってしま うのて、 , 配列の初期化は必要て、す。 18 行目て、は , 負の数だった場合のエラー 処理をしています。この際 , システムに工 START i ← 20 k ← 0 Yes i が j 以上 NO Yes i が j で割 NO きれる ? 灯」直を攵として格納 k の直をその , ヾき乗として格納 k ← 0 、灯】直を攵として物 k 直をその、くき乗として格納 END ⑧で i = 10 , j=2, k=l ⑥で i = 5 , j=2, k=2 k=O ( 22 ) ◎で j = 2 が素因数 , k = 2 がそのべき乗 = 5 , j = 3 , k=O ( 3 。 ) = 5 , j=4, ◎で j = 3 が素因数 , k = 0 がそのべき乗 k=O ( 40 ) = 5 , j=5, ◎で j = 4 が素因数 , k = 0 がそのべき乗 ⑧で i= 1 , ◎で j = 5 が素因数 k= 1 がそのべき乗 22X30X40X51 = 1X22X51 = 20 よって ( 51 ) Fig. 7 素数の並び 素数 2 増分 1 4 十 2 2 十 4 2 4 2 2 2 4 ・・・と増えていく 2 , 4 , 2 , 5 以上では , 2 , はじめて ; : C プログラミング 125