List - みる会図書館


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

1. 月刊 C MAGAZINE 2001年2月号

す。空行のあとの「く ! DOC' Ⅳ PE ・・・・・・」から ざまなプロトコルは TCP / IP を前提とした るなどの理由で , 指定された U 糺とは別の U 糺に飛ばすものです。このプログラムは , の文字列が指定した U 糺にある HTML ファ ものです。 引数に H 盟、 P U Ⅲ陸渡すと標準出力にその この I--H 丁 P やド PP などのサービスを利用 イルの中身ですが , その前に 10 行ほどよぶ 結果を出力します。作りとしては HITPUR んなものが付いています。これは HITP に するためには , アドレスのほかにポートと よる応答の結果です。 HITP はヘッダと呼 L クラスを作り , そのメソッドとして get を いうものを指定するのが TCP/IP のセオリ 用意しています (Python ふう ? ) 。次にポ ばれる制御用のメッセージと , ボディと呼 ーです。ポートは番号で指定します。たと ばれるデータを 1 つの I / O で送るので , 混ざ イントとなる所を説明します。 えば HITP は 80 , ド PP は 21 を使うのが標準 って送られてきます。この混ざり方は HIT Net::HITP は net/http で定義されていま です。こういった標準的なポートはウェル P で決められているので , それに従えばこ す (List 2- # 1 ) 。プロクシは環境変数 h 叩ー prox ノウンポート (wel ト known port) と呼ばれ , の中からデータにこでは空行以降 ) だけを y が設定されていればそれを HITPURL::PR とくに UN Ⅸでは特権ユーザでしか利用で OXY にセットして用います ( List 2-#2)0List 取り出すことができます。でも , そういう きません。たとえば , 自分のマシンのポー めんどうな作業をやってくれるライプラリ ト 80 を HITP サーバとして利用するために 2- # 3 にある@myheader の Accept-Language は特権が必要です。詳しくは , 2000 年 12 月 を Ruby ではすでに標準で用意しています。 と Host' は , それぞれ言語とサーバのホス 号の特集 2 や [IPRI] などから読み始めると Net::HTI 、 P というものがそれです。 ト名を表します。 Accept-Language' が利用さ れるかどうかはサーバしだいです。 よいでしよう。 Net::HTTP を利用してみる List 2-#4 で Net::HTI 、 P オプジェクトを作っ 、 TCPSocket クラス そこで , Net::HTI 、 P を使って List 1 をさっ ています。省略できる第 2 ~ 4 引数でサーバ のポートとプロクシを指定しています。 job そく作り直してみましよう。しかし , ただ TCP を使うならば , アドレスとポートの というのはデバッグ用のメッセージを出す 作り直すだけでは強力な Net : : HTPP が泣く 組みで , ほかのホストを指定できます。そ ので , HITP のリダイレクションとプロク ためのものです。これはソースコードの下 して交信には読み出しと書き込みの両方が のほうで定義しています。 シに対応しました。 List2 がそれです。リダ できる I / 0 を利用します。この I/O が「 TCP イレクションというのは , たとえば Ruby の List 2- # 5 の部分になると HTI 、 P オプジェク ソケット」と呼ばれるものです。 TCP ソケ ホームページ (http://www.ruby-lang.org/) ト h のメソッド get を使って CJMP しています。 ットは , サービスを指定するためにアドレ その際 , 省略可能な第 2 引数に@myheader で利用されているもので , 引っ越したとか , スとポートの組み合わせで開かれます。 プラウザの設定で日本語か英語を切り替え を渡しています。 Ruby では TCP ソケットを TCPSocket という 名前のクラスとして提供しています。これ Fig. 1 List 1 の実行結果 をさっそく使ってみましよう。 HTTP/I . 1 200 OK List 1 は http://www.notwork.org/ipr/te 1 5 Dec 2000 04 : 39 : 23 GMT Date: Fri, st. html" というところから資源を取得する Server: Apache/1.3.9 (Unix) mod ゴ uby / 0.2.1 Ruby/1.6.1 ( 2000-09-27 ) プログラムです。わずか 5 行ですが , これ Last-Modified: F 「 i, 14 Apr 2000 06 : 59 : 36 GMT でも H"ITP クライアントです。 TCP ソケッ ETag:" 1 b39e - c5-38f6C1 d8 トを開いて , そこに「 GLT …」を書き込んで , Accept-Ranges: bytes Content-Length: 197 読み取っていることがここからわかります。 Connection: close Content-Type: text/html く !DOCTYPE HTML PUBLIC" -//W3C//DTD HTML3.2 FinaI//EN" > く head> く title>test</title> <link rev=made h 「 ef= mailto:gotoken@notwo 「 k. 0「g > く /head> <bodY> く hl >test</hl > く p>test, test, test_. </bodY> コニ Net::HTTP List 1 の実行結果は Fig. 1 のようになりま TCP ソケットの利用例 (socketdemo. 「 b) require ” socket ″ s = EPSocket. new( ”げ w . notwo て k. 0 て g ” , 80 ) s. write "GET /ipr/test.html 叩 p / 1.0 \ r 基 n \ て当 n ″ print s. read 1 89 極めよ Ruby 道 伝授 !

2. 月刊 C MAGAZINE 2001年2月号

メ五ロ ス万第七十四語 劬言例外 ( 1 ) 千 きだあきら い処理内容が何であるかが一見してわかり チェック づらくなっている。 細かく分析すると , List2 で使われている ふだん , どのようなプログラム言語を使 チェックの技法は 2 通りある。 1 つは事前チ っているのか , プログラマがどれほど良心 ェックとでもいうべき方法で , 部屋から出 的にコーディングしているのかにもよるの る前にはドアスコープを慎重にのぞき込ん だが , 多くのプログラムでは , 本来行うべ で , 玄関先に邪悪なモノが迫っていないか き処理だけでは構成されていない。その処 を確認したうえでなければドアを開けては 理を行ってよいかどうか , 想定していなか ならないという戒律に従うものである。も った事象が起きていないかを調べ , そうし う 1 つが事後チェックであって , たとえば た事態に対処するために数多くのステップ 部下に命令した仕事が完了した報告を受け 数が費やされる。 場合 , 無条件にそう言いきるか , あるいは る際に , 何かしら手落ちがなかったか , ま ごく簡単な例として , 1 から順に 100 まで ずいことをしていないかを根ほり葉ほり問 の値をファイルに書き込むようなプログラ せいぜい「晴れていたら」と条件を付けるく いただす方法である ( 部下から嫌われるこ らいではないだろうか。そうした場合に , ムを考えてみよう。これを C で , 工ラーチ とは言うまでもない ) 。 「自然災害で公共交通機関が壊滅していな ェックを何も入れずに書くと List 1 のよう くて , かっクーデターが勃発して戒厳令に になる。もちろん , List 1 はあまりにも工 深い論理の底からの脱出 なっていなくて , しかも会社が倒産して職 ラーに対する配慮がなく , C に慣れたプロ C 言語でプログラムしていて , 本処理に を失っていなければ」などと事細かに条件 グラマの目で見ればいろいろと気がかりな を付けたりしないだろうし , もしそうした 先だってある種の前処理を行う必要がある 点があるプログラムである。 これに対して , さまざまな注意を払った としたら奇人変人扱いされるだけだろう。 としよう。ただし , 前処理を行った結果 , 何らかの異常事態 ( 工ラー ) が発生したら本 残念ながら , C のプログラミングに慣れ プログラムを書くと , List 2 のようになる。 た人ほど , こうした事細かなチェックを入 処理はスキップするものとする。 ⅱ stl に比べると 2 倍以上のステップ数にな こで前処理が複雑になる場合 , それら れている List2 の不自然さ , いびっさを感じ っていて , 本来の処理よりもむしろ工ラー 取る感性が失われている傾向がある。まず を関数としてくくるのは悪くない考えだ。 処理にステップ数が割かれている。このよ 前処理を別の関数として定義し , 本処理側 大きな問題は , 可能性として十分ありそう うな逆転現象は , なにもこのプログラムだ から呼び出すのである。その場合 , 前処理 けの特例でないのは先に述べたとおりであ なことも , およそありそうもないことも , の途中でエラーが発生したら即 re ⅲ rn 文で 必ずチェックを入れるという方針だ。「明 る。 復帰すればよい。当然 , 本処理側では戻り 日遊園地に行こう」という場合の前提条件 プログラミング ( とくに C のプログラミン に , 「火星人の UFO が地球を侵略しに攻撃 値を検査してエラー発生の有無を調べる必 グ ) に慣れた人にとっては , List 2 のような をかけてこないこと」なんていう ( ありそう 要がある。 コーディングは当たり前に受け入れている もない ) チェックを入れないと気が済まな ものだろう ( もっとも , 慣れた C プログラ ところが , 前処理の論理が複雑になると , マでも stdout への出力に対するエラーチェ 1 つの関数では収まらなくなる。前処理自 いところが List 2 のスタイルである。 もう 1 つの問題は , 仮に「かなりありそ 身が複数の関数を呼び出す構造になり , さ ックだけは省略してしまうかもしれない ) 。 う」なことでも , いちいち事前にチェック らにその先で別の関数を呼ぶという具合 一方 , プログラミングの初心者は , 往々に して List 1 に近い書き方をしがちだ。とに を入れたり , 何か処理をするごとにそれが に , 関数の呼び出しが深くなることがある。 かく「やりたいこと」を表現するだけで精 起きていないかを確認したりしていると , そうすると , ネストの深いところである関 数がエラーを返したとして , その戻り値が 一杯になり , それが失敗するかもしれない 本来やりたいことが何であるかがばやけて 呼び出し側でチェックされ , それがまた工 ということまで気が回らない傾向がある。 しまうことである。 ラーを返すからその呼び出し側でチェック そういう観点で List1 と List2 を見比べる チェックは自然か されといった具合に何度も何度も「エラ と , ⅱ stl ではチェックが何も入っていない しかし , である。本当に List 2 のような書 のでプログラムとしては明らかに不備では ーである」ことが繰り返しチェックされな き方が「自然」なのだろうか ? 日常生活で あるが , 逆に「何をしたいか」は明快である ければトップレベルのロジックにエラーが 伝わらない (List 3 ) 。深いところで発生し のに対して , List2 では不慮の事態に対する は , 子供と , あるいは恋人と , 「今度の日曜 た異常事態がトップレベルに届くにはずい 日には遊園地に行こう」という約束をする チェックは万全である半面 , 本当に行いた 1 66 C MAGAZINE 2001 2

3. 月刊 C MAGAZINE 2001年2月号

特集 1 XMLX 門 は , 変数 itemld に保存する (List 9 の 7 行目 ) 。 を読み込み終えてから処理を行うように設 べる。 chiIdNodes コレクションで item プロ パティを参照すれば , その子要素の保持す HTML 文書中で定義したデータアイラン 定する。 る値が取り出せる。 item にも 0 から始まるイ ドに変数血 ame の保持する XML 文書を読み parseError は DOM のエラーを保持するオ ンデックスを与える。要素「品番」は最初の 込ませるため , parse 関数を呼び出す。 XM プジェクトで , parseError プロバテイから 要素なので , item ( 0 ) とする。その保持す 参照できる。もし文書の読み込みに失敗す LDOMDocument オプジェクトへの参照が る値は text プロバティで取得できる (List 9 れば , parseError. errorCode が 0 以外の値と 返り値となるため , それを変数 document に の 45 行目 ) 。 受け取っている (List 9 の 12 行目 ) 。 parse 関 なる。このとき parseError. reason でエラー キー項目 (itemld) と「品番」の値が一致し メッセージが参照できる (List 9 の 25 , 26 行 数の処理は次項で説明する。 目 ) 。 たら makeList 関数を呼び出し , ループ内で XMLDOMDocument オプジェクトの doc 現在処理中の要素 ( child が示すオプジェク umentEIement プロバティには , 読み込んだ 最後に , 文書を読み込んだ XMLDOMDo cument オプジェクトへの参照を返す (List 9 ト ) からその子要素の値を文字列として生 XML 文書のルート要素が保持されている。 これを変数 t 叩 vel に受け取る (List 9 の 13 の 28 行目 ) 。 成する ( List9 の 48 行目 ) 。 ループを最後まで繰り返しても該当する 行目 ) 。 searchltem 項目が見つからなかったときは , 処理結果 最後に , 先頭要素 t 叩往 vel , 出力先。 u ゆ を保存する変数 text が初期化されたままと ut, 検索キー itemld の 3 つを引数にして , 実 XML 文書の先頭要素 ( ノード ) , 出力先 , なっている。その場合は , 工ラーメッセー 際の検索処理を行う関数 searchltem を呼び 検索のキー項目を引数に , 項目「品番」の値 ジを出力する ( List9 の 52 ~ 54 行目 ) 。 出す ( List9 の 13 行目 ) 。 がキー項目に合致する要素を探し , その子 要素をすべて出力先に表示する。 parse 引数 n 。 de は XML 文書に記述された構造 の先頭要素にの例では「商品一覧」 ) を指し 引数として要素 ( 商品 ) を受け取り , その finditem から呼び出され , データアイラ 子要素の値を文字列として整形して返す。 ている。そこで , 処理の対象を 1 っ下の要 ンドに XML 文書のリストを読み込む。引数 素 ( 商品 ) に移動して , 要素「商品」の数だけ 品番 , 品名 , 単価の 3 つの要素に対して , として XML ファイル名と XMLID を受け取 List9 の 63 ~ 65 行目のように項目名を示す 処理を繰り返す。子要素は childNodes オプ る。 文字列と要素の保持する値とを連結し , 1 ジェクトに保持されており , その集合 ( コ XML ID で示されるデータアイランドに レクション ) である childNodes を通じて参照 つの文字列にするだけである。 XML 文書を読み込ませるには , 以下のよう できる。子要素の数は childNodes の length もし要素名を示す文字列が不要なら , 以 にする。 プロバテイから取得できる ( List 9 の 40 行 下のような for ループで処理することもでき ・ async プロバティを f se ( 偽 ) に設定す 目 ) 。 る。 る for ループの中では , 要素「商品」のさらに ・ XML 文書を指定して load メソッドを実 子要素である「品番」の値を調べなければな 行する らない。そこで , 変数 child に子要素への参 ソースコードでは List9 の 22 , 23 行目のよ 照を受け取る。ここで child に受け取るのは うになる。 ルートのすぐ下の要素ーー「商品」である。 async プロバテイも load メソッドも IE5 固 chiIdNodes コレクションでは , インデック 有のものである。したがって , この処理は XML データアイランド スによって「何番目の子要素」かを指定でき IE5 以降のプラウザでしか正常に機能しな る。 インデックスは 0 から始まる。カウンタ ここでは , XML データアイランド (Data async はデフォルトでとなっており , lsland : 以下「データアイランド」 ) と呼ばれ 変数 i をインデックスに用いることで , for 文書の読み込みとデータ処理が非同期で実 ループ内ですべての要素を操作させている 行される。すると , XML 文書がすべて読み る機能を利用した。 データアイランドは , HTML 文書中に X (List 9 の 43 行目 ) 。 込まれないうちにデータ処理が実行されて ML 文書を埋め込んで操作する場合に用い 変数 child のさらに子要素を参照して , 品 しまう場合がある。これでは都合の悪い場 番の値と itemld の値が等しいかどうかを調 合が多いため , false としてすべてのデータ られる機能だ。 特集 1 XML 入門プログラミング基礎の基礎 2 / makeList var for (i = 0 ・ i く 3 ; i + + ) textList + = child. chiIdNodes.item (i) . text

4. 月刊 C MAGAZINE 2001年2月号

Java programmingTips て現在の日時を取得しています。まず , Ca javac CurrentTime2. java DateFormat クラスを でコンパイルし , lendar クラスの s ねⅱ c メソッドである getlnsta 用いた書式指定 nce() メソッドを使って CaIendar オプジェク java CurrentTime2 で実行します。実行結果は List 1 と同じく , トを得ます。そして Calendar クラスの getTi List 1 , 2 では日時の表示に DateFormat ク 現在の時刻が表示されます。 me ( ) メソッドを用いて , 現在の日時を表す ラスを使いました。今度はこの DateFormat List2 は List1 とほとんど同じですが , List Date オプジェクトを得ています。 DateFor クラスに注目します。 DateFormat クラスは 2- ①の部分だけが少々異なります。 こは mat クラスを用いた表示部分は List 1 とまっ いくつかの表示用メソッドを持ち , 引数で List 1- ②に対応し , CaIendar クラスを使っ たく同じです。 書式を指定することによってさまざまな形 式で日時を表示 ( あるいは文字列に変換 ) す Fig. 1 日時をさまざまな形式で表示するアプリケーション ( 1 ) の実行結果 ることができます。 次にあげるのはさまざまな形式で日時を getlnstance( ) : 00 / 11 / 29 20 : 48 getDateInstance( ) : 2 圓 0 / 11 / 29 表示するプログラムです田 st3 ) 。 getTime I nstance ( ) : 20 : 48 : 34 getDateTimeInstance() : 2000 / 11 / 29 20 : 48 : 34 javac FormatTime1. java : 00 / 11 / 29 SHORT : 2000 / 11 / 29 MEDIUM でコンパイルし , : 2000 / 11 / 29 LONG FULL : 2000 年 11 月 29 日 java FormatTime1 : 20 : 48 SHORT で実行します ( Fig. 1 ) 。 MEDIUM : 20 : 48 : 34 : 20 : 48 : 34 : JST LONG Fig. 1 の最初の 4 行は , DateFormat オプジ FULL : 20 時 48 分 34 秒 JST ェクトを取得するいくつかの sta ⅱ c メソッド の使い分けを示しています。おのおののメ ソッドを用いて取得した DateFormat オプジ ェクトに関して , format() メソッドを呼び 出しています ( List 3- ① ) 。 getlnstance() メ ソッドは List 1 , 2 でも使っていますが , 日 時を短い形式で表示します。 getDateInsta nce() メソッドは日付のみ , getTimeInstan ce() メソッドは時刻のみ , getDateTmeInsta nce() メソッドは日付と時刻の両方を表示 します。メソッドの名前のままですね。 Fig. 1 の中央の 4 行は , getDateInstance ( ) メソッドに引数を与えて書式を指定する方 法を示したものです ( List3- ② ) 。 DateFor mat クラスに定義されている SHORT , ME DIUM, LONG, FULL という定数を getDa telnstance() 引数に与えると , それぞれ実行 結果に示した表示になります。 Fig. 1 の最 後の 4 行も同様で , こちらは getTimeInsta nce ( ) メソッドに引数を与えて書式を指定 したものです ( List3- ③ ) 。 SimpleDateFormat クラス を用いた書式指定 次に , 書式文字列によって表示形式が指 定できる SimpleDateFormat クラスの使い方 Java Programming Tips 1 25 List 日時をさまざまな形式で表示するアプリケーション ( 1 ) / / 日時の表示フォーマット ( 1 ) import java. uti に * ー import java. text. * ー public class FormatTime1 ( public static void main(string args[ ] ) { 〃現在の日時を取得 Date d = new Date( 〃日時の表示 ( 1 ) system. out. print ln( "getlnstance( ) 十 DateFormat. getlnstance( ). format(d) system. 0uし . print ln( "getl)atelnstance( ) 十 DateFormat. getDateInstance( ) . format(d) system. ou し print ー n ( ngetTime lnstance ( ) 十 DateFormat. getTimeInstance( ) . format(d) system. ou し print ー n ( DgetDateTime lnstance ( ) 十 DateFormat. getDateTimeInstance( ) . format(d) リ System. out. println( / / 日時の表示 ( 2 ) System. out. println( DSHORT 十 DateFormat. getDateI nstance ( DateFormat. SHORT ) . format(d) system. 0uセ . println( "MEDIUM : 十 DateFormat. getDate lnstance ( DateFormat. MEDIUM ) . format(d) system. 0uしPて土n凵n( ”も ONG 十 DateFormat. getDate lnstance ( DateFormat. LONG ) . format(d) system. out. println( "FULL 十 DateFormat. getDateInstance(DateFormat. FULL 。 ) . format(d) System. out. println( / / 日時の表示 ( 3 ) system. out. println( "SHORT 十 DateFormat. getTimelnstance(DateFormat.SHORT ) . format(d) system. 0uセ . println( "MEDIUM : 十 DateFormat. getTimeInstance(DateFormat. MEDIUM) . format(d) system. 0uセ . println( "LONG 十 DateFormat. getTime lnstance ( DateFormat. LONG ) . format(d) System. out.println( "FULL 十 DateFormat. getTimeInstance ( DateFormat. FULL ) . format(d) ①

5. 月刊 C MAGAZINE 2001年2月号

ーテク講 真紀俊男の 第回 2 次元の巻 ほかのプログラム言語から C 言語に移った ではこうだったから」という思い込みで , 場合 , 以前に知っていたプログラム言語の C 言語にないものねだりをすることだ。もち ろん同じことは C 言語から C + + 言語に移っ 常識と食い違うことが多く , とまどうとい うことはありがちである。困るのは「ほか てもいえるわけだが。 としたとき」にあやふやな理解がドッポの か」と勘違いしてはいけない [ 1 ] 。たしかに 1 元になる。当然 , 2 次元配列の動的確保で 次元配列の場合はポインタと配列の混同を も同じ問題が起きる。 していても一見問題なかったのだが , 2 次 以前に説明したことがある 2 次元以上の たとえば , 2 次元配列を確保する List 1 の 元配列の場合はこれが命取りになる。とい 配列の動的確保 ( 1996 年 5 月号「さまよえる ようなコードがあったとする。まずは , うのも 2 次元配列では空間の折り返しをコ 思い出の巻」を参照 ) であるが , 当時は C + + れがどのように機械語に落とされるかを観 ンパイラが勝手に判断しているからだ。 言語のことを考えていなかったので , その 察してみよう。 List3 では 3X4 の領域を確保しているつも 点も含めて再度このテーマを取り上げてみ りになっているが , 4 の折り返し点を誰も gec -S たい。ただし , 同じことの繰り返しでは意 でアセンプラのソースを生成してみると , 指示していない。また , コンパイル結果を 味がないので省略する部分もあるがその点 List 2 のようになっている。つまり 3X4X4 見ると , 先ほどのシンプルなコンパイル結 ( 最後の 4 は int のサイズ ) の合計 48 バイトの はご容赦願いたい。 果とはまったく別物になっている (List 4 ) 。 C / C + + 言語でよくある勘違いの 1 つが , 空間がスタック上に確保されて , そこに 0 , 全部を説明すると長くなるので「 theD2M 「ポインタと配列は同じである」 1 , 2 , 3 が書き込まれたわけだ。 [ 0 ] [ 0 ] = 0 ; 」のコンパイル結果だけを見てみ だが , 「メモリの動的確保をして配列のよ こで , 「ということは , もし 3X4 の int の よう。 List 1 のように 2 次元配列として確保 うに見せかける」とか , 「ほかの関数の呼び 2 次元配列を動的に確保したいなら , ポイ した場合 , 出しで引数に配列やポインタを指定しよう ンタを使って List3 のようにすればいいの movl $ 0 , -48 (%ebp) 2 次元配列 2 次元配列 ( List 1 ) のコンバイル結果 2 次元配列の動的確保 static void TestMain1(void) int theD2Mt 3 Ⅱ 4 theD2M[0][0] theD2M[ 0 Ⅱ 3 ] = theD2M[2][0] = 2 theD2M[2][3j TestMain1: pushl %ebp movl %esp,%ebp subl S48 ,%esp movl $0 广 48 ( ebp ) 洋 heD2 甌 0 Ⅱ 0 ] movl $1 广 36 ( ebp ) ;theD2M[01[31 = movl $2 广 16 ( ebp ) ;theD2M[2][0] movl $3,-4(%ebp) ;theD2M[2][3J leave ret C MAGAZINE 2 側 1 2

6. 月刊 C MAGAZINE 2001年2月号

現する。 目 ) 。フォームを示す引数 form から , XML スは List 9 のようになる。 個々の関数の仕様を見ていこう。 文書名を入力したテキストボックス fname HTML 文書 を参照し , XML 文書名を取り出して変数血 finditem ame に格納する (List 9 の 5 行目 ) 。処理結果 HTML ファイルの解説をしておこう。基 は , 同じく form のテキストボックス output 本的には「フォームを使ってデータを入力 HTML 文書のコマンドボタンクリックでを変数 ou ゆ ut に格納しておく ( List9 の 6 行 し , コマンドボタンのクリックでスクリプ 呼び出される。引数は HTML 文書内のフォ 目 ) 。 トを実行する」という , ごく一般的な構造だ。 ームを示す識別子と XML ID だ (List 9 の 3 行 テキストボックスに入力された「品番」 XML 文書から商品検索を行う java スクリプト (finditem. js) スクリプトの指定と入力領域 1 : 〃 finditem ~ フォームから商品番号を受け取って該当するデータを返す Java スクリプトは "finditem.js" というファ 3 : function finditem(form, xmldocument) イルに記述し , List8 の 4 行目のように呼び / / 元テータを記録した文書名 var fname = form. fname. value, 5 : 〃結果表示用テキストボックス 6 : output = form. output, 出す。短い処理なら , HTML ファイル内に / / フォームに入力された品番 itemld = form. itemld. value; 8 : 記述してもかまわない。 〃テキストを初期化 output. value = 10 : / / データアイランドに文書のリストを読み込む 「品番」を入力するためのテキストボック 11 : var document = parse(fname, xmldocument) , 12 : topLevel = document. d0C5ent引55場 / / ルートノードを取得 13 : スを , Ⅱ st8 の 12 行目のように定義する。 / / 検索処理 14 : searchItem(topLevel , output, itemld); 15 : } 基礎データを記録した XML ファイルも , 16 : 17 : / / データアイランドに皿文書のリストを読み込む 同じくテキストボックスで入力できるよう 18 : / / 19 : function parse(docname, ocumen セ ) にしている ( List8 の 14 行目 ) 。 20 : { 〃文書の読み込み ( a mc プロバティと load メソッドは固有 ) 21 : 22 : xmldocument. async = false; mldocument.load(docname); 23 : コマンドボタンと結果表示 24 : 土 f ( 005en し pa て seEr て or. e てて 0 て ! = 0 ) 25 : 引 e て t ( OC en し . pa て se ror. て eason 26 : コマンドボタンは ONCLICK イベントで 28 : return mldocument; Java スクリプトの血 ditem を呼び出す。この 30 : 31 : / / リストから品番が emld と一致するノードを探す 32 : / / とき引数にフォーム名 ( con 仕 ols ) と XML 文 33 : function searchltem(node, output, itemld) 34 : { 書を示す XMLID を渡す (List 8 の 17 行目 ) 。 / / 子ノードを保持するオブジェクト 35 : var 0 , 36 : XML ID は , List 8 の 24 行目のようにく xml > / / 検索結果 ( 表示用 ) text = 38 : タグによって識別子 " id " に値を代入するこ 〃子ノードの数 ( レコード件数 ) だけ繰り返す 39 : fo て ( 土 = 0 く node. childNodes. 厄 ngth 十十 ) とで定義される。 41 : 〃ルートから 1 つ下のノード ( 商品 ) を処理対象とする これによって XML 文書を HTML 文書内で 〃最初のレコードを処理 / / 最初の要素 ( 品番 ) を調べる 44 : 扱うための構造ーーー XML データアイランド if(child. childNodes. 土セem(0) . text = = itemld) 46 : が定義される。後述するスクリプトでデー / / 一致したら文字列を生成 text = makeList(child); 48 : タアイランドに XML 文書を読み込ませると , 49 : 50 : それを扱う DOM への参照が可能となる。 51 : if(text = ” ) / / 該当レコードがなかったとき text = ”データが見つかりません。”十物て” スクリプトの処理結果は , List8 の 22 行 output. value = text ・ 55 : } 目のようなテキストボックス "output" に出 57 : / / 一致したノードの要素から文字列を作る 力する。 READONLY 属性を付け , ューザ 58 : / / 59 : function makeList(node) が値を変更できないようにしてある。 60 : { 61 : var textList = 〃 3 つの要素に対して、要素名と値とを連結 62 : 63 : textList 十 = ″品番 : ”十 node. childNodes. item(0) . セ ex セ十、て Java スクリプト textList 十 = ″品名 : ”十 node. childNodes. item(l) .text 十”て″ 64 : textList 十 = ”単価 : ”十 node. childNodes.item(2) . text 十” \ て″ 65 : 66 : return textList 実際の検索処理は , Java スクリプトで実 26 C MAGAZINE 2 1 2

7. 月刊 C MAGAZINE 2001年2月号

List 1 まず , 列挙したいレジストリの親キー「 H KEY_CURRENT_USERHSoftware 」をオー プンします (List 1- ② ) 。 こで取得した hk ey の値を基にして , 列挙が終わるまでルー プを回します。 こでは , SHEnumKeyEx 関数を利用し ます。 for 文を使ったループでこの第 2 引数 のインデックスを設定し , 得られた値をリ ストボックスに送っています (List 1- ③ ) 。 そして最後にレジストリをクローズします。 キーの列挙が非常にシンプルなソースコ ードになっているのがわかります。 ERROR-SUCCESS) { break; SendMessage(GetDlgItem(hWndmain, IILLISTI) , LB-ADDSTRING, 0 , (long)szKeyName)i RegCloseKey(hKey); regenumvalue void regenumvalue(void) HKEY hKey; DWORD n; char szKeyName[1000]; DWORD dKeyNameSize; DWORD ValueType; char szv 引 ue [ 1000 DWORD dValueSize; RegOpenKeyEx( HKEY—CURRENT-USER , "Software"MicrosoftWInternet connection Wizard" , 0 , KEY—ALL—ACCESS, &hKey); レジストリ値を列挙 次は , [ レジ区上値の列挙 ] ボタンの動作 です。上記のレジストリサプキーの列挙と 違い , 指定したキー ( ここでは「 So れ ware \ \ MicrosoftYYInternet Connection Wizard 」 ) に 設定してある値を列挙していきます。 この値を全部ピックアップするため , こで使用する SHEnumVaIue 関数の値が ER ROR_SUCCESS になるまで無限ループを繰 り返しています。注意すべき点として , 値 を取得するためのバッフアのサイズは毎回 設定する必要があります (List 1- ④ ) 。 このようにして列挙したキーから値を順 次取り出し , この値が文字列 ( G ー sz ) だ った場合には値とその内容を , 文字列以外 の場合はそのキー名のみをリストボックス に転送しています ( List1- ⑤ ) 。 指定したキー値の取得 次に , [ 指定王三取間ボタンです。これも 名前だけだとちょっとわかりづらいですが レジストリに設定している値そのものを取 得しています。たとえば , アプリケーショ ンのインストールバスやプロバティで設定 した値そのものを取り出します。 まず , バッフアのサイズを sizeof を利用 して取得 , 設定したあと (List 1- ⑥ ) , レジ ストリをオープンします。この時の hkey の 値を , SHGe Ⅳ alue 関数の第 1 引数に設定し , 第 2 , 第 3 引数に取得したい部分を設定しま す。今回は「 CursorsHSchemes 」および「ア 1 22 C MAGAZINE 2001 2 while(l){ dKeyNameSize = sizeof(szKeyName); dValueSize sizeof(szvalue); n 十十一 if(SHEnumValue(hKey,n,szKeyName, &dKeyNameSize,&Va い ueType,szVaIue,&dVaIueSize) ! = ERRRSUCCESS){ break; if(VaIueType ま = REG-SZ) { wsprintf(szData, ″ s [ s ] 基 n ″ , szKeyName, szValue); szData[IstrIen(szData) 1 ] ' 基 0 ' SendMessage(GetDlgItem(hWndmain, m—LIST1)„ LB—ADDSTRING, 0 , (long ) szData ) デ 引 se ( SendMessage(GetDlgItem(hWndmain, IILLISTI), LB—ADDSTRING, 0 , (Iong)szKeyName); RegCIoseKey(hKey); regenumget void regenumget(void) HKEY hKey ー DWORD dValueType; DWORD dValueSize; char szVaIue[1000]; dvalueSize = sizeof(szvalue); RegOpenKeyEx(HKEY—CURRENT-USER, ” Con し ro ー panel"", KEY—ALL-ACCESS, &hKey); SHGetValue(hKey, cursorswschemes", ”アニメーション砂時計物 &dValueType, szvalue, &dValueSize); if(dvaIueType = REG-SZ) ( SendMessage(GetDIgItem(hWndmain, IDC—LISTI) , LB—ADDSTRING, 0 , (long)szvalue); RegCIoseKey(hKey); を De leteKey void DeIeteKey(void) HKEY hKey; RegOpenxeyEx(HKEY-CURRENT-USER, "SoftwareWcmagazine", 0 , KEY-ALL—ACCESS , &hKey if (IDOK = = MessageBox(hWndmain, ″今回登録したレジストリデータを削除します % szAppName, ー OKC c 新 ) ) { SHDeleteKey(hKey, szKeyname); RegCIoseKey(hKey);

8. 月刊 C MAGAZINE 2001年2月号

cl = 引 * = 2200 圓 0 圓 0 -420 圓圓圓 0 = 引 * = 9206744073709551616 ー 420 圓 00 圓 0 ー 23000 圓圓 0 ー 470744073709551616 ー 8786744073709551616 は浮動小数同士になる。整数同士の除算で 演算対象は必ず整数同士であるか , あるい て二項数値プロモーションが施されるため , おり , 演算に先立って両オペランドに対し 数の場合について説明する。なお前述のと 数と浮動小数で動作が異なるので , まず整 ンドで除した商を求める。この演算子も整 除算演算子は , 左オペランドを右オペラ 除算演算子「 / 」 ていないのは少々残念なところである。 算では ) それを簡単に行う手段が用意され たい場合もあるのだが , ( とくに long の除 算では , オーパフローの発生をチェックし 外が投げられることはない。とくに整数乗 ーやアンダーフローが発生したとしても例 が整数であれ浮動小数であれ , オーパフロ 大原則として , Java の乗算では演算対象 は , 結果も整数となる。 Fig. 8 に除算の定 e hl Fig. 7 List 3 のサンプルラン akida: ¯/cmaga/javaref$ java List3 f = d * e = 2116967296 c = a * b = ー 50467296 ( 123.4 , ー 0.0 , } , { ー 123.4 , -0.0 , ), Java プロクラミングリファレンス 詳説 JDK 解体新ロ class List4 0 * 整数除算の例 / * List4. java 整数除算の例 a = 65 圓 0 b = 65300 d = 33000 -66 圓 0 ー 650 圓 ー 34000 1 static void dolt(int n0, 土れ t (0) { fo て (int i = 土 > - i - if ()0 く 0 & & 土くの continue ー for (int j = 1 引 j > ー j ー = 土 n セ n 言 0 * 土ー 土 n し d d0 * system. out.println(n 十新 / ”十 d 十”まを十 ( れ / d)); system ・ 0uセ . println("- int[ Ⅱ ] セ public static void main(string[ ] args) { -2084967296 = 428 圓 00 圓 0 = 420 圓 000 圓 fo て { 2147483647 , 1 , } , -2147483648 , 1 , } , ( 土北土 = 土く tbl.length; 十十 i ) doIt(tbI[i][01, tbl[i)[ll); 浮動小数除算の例 / * List5. java * 浮動小数除算の例 class List5 ( final double れ = Double. NaN; public static void main(String[ ] args) { final double inf = D0リb厄 . POSITIVE—INFINITY; doubIe[J[J tbl ( { 123.4 を inf, } , { -inf, -123.4 , し ( -inf, 123.4 , ) , { inf, 423.4 , し { inf, 123.4 ! } , { 十 0.0 , 十 0. の ) , { inf, inf, し ( nan, 土社 , し { 123. れ a 町 } , { ー 0.0 , 123.4 を ) , { 十 0 0 ー 123.4 , ) , { 十 0.0 , 123.4 , { -123.4 , -inf, } , { -123.4 , inf, } , { 123.4 , -infi し ー 123.4 を } , { ー 123.4 , 十 0.0 , ( 123.4 , 十 0.0 , system. out. println(n 十″ / ”十 d 十 = ”十 (n / d)); do 面厄 d = tb Ⅱ幻 [ 1 double n = tb Ⅱ土Ⅱ 0 嵭 モ 0 て (int i = の i く tbl.length; 十十土 ) ( 義を公式的に示した。この場合の大きな特 徴は , 数学的な商をゼロ方向に丸めて整数 値を得ることである。 List4 に示すプログ ラムはこうした除算の性質を説明するため 98 C MAGAZINE 2 1 2

9. 月刊 C MAGAZINE 2001年2月号

アクセスした結果を Fig. 2 に示します。 HITP#get はリダイレクトされていると を書いてみましよう。 List3 は , 筆者が実 きに例外を発生します (List 2- # 6 ) 。 Ruby の例では - d オプションで $DEBUG を設定し 際に使っている C を取得するためのプロ 1.6 から加わった rescue の構文を使って , ているので , リダイレクションに従う様子 グラムです。以前別のところで発表したも 例外オプジェクトを r に代入しています。 もわかります。 の [ Ⅳ RI ] に手を加え , すでに入手している List 2- # 7 のところで , 例外 r からリダイレク RFC はそのまま使うようにしています。た ト先を得ています。 だし , rfc - index は最後に入手して 1 か月以 List 2- # 8 で , 新しく作った URL である 10C 上経っていれば取得し直します。コマンド を使って呼び出しをやり直します。 ネットワークプログラミングは , ソケッ ラインから , List 2- # 9 が job の定義です。 $ DEBUG が トの使い方のようなライプラリ側の話とプ $ 2616 設定されているときにメッセージを出力し ロトコルに関する 2 つの技術から成り立っ とすれば , もし持っていれば C2616 をベ ています。プロックの評価結果を値として ています。ライプラリの使い方はサンプル ージャを使って表示し , 持っていなければ , 返します。 とドキュメントの両方を見ていくことで理 ドで取ってきてからページャを起動しま List 2- # 10 はこのプログラムのトップレベ 解できますが , プロトコルのほうは残念な す。 ルで , HTI 、 PU 糺 # get を呼んでいます。この がらライプラリのドキュメントだけではわ メソッドの値は HITP # net の返す値なので , かりにくい部分も少なくありません。イン ヘッダとボディの組みになっています。へ ターネットで用いられているプロトコルは ッダは $ DEBUG が設定されていない場合 RFC という形でまとめられており , FPP な さて , 次はサーバを書いてみたいと思い 使わずに捨てます。 どで誰でも入手し読むことができます。 ます。 Ruby ならサーバを書くのも実に楽で プロクシ経由で Ruby のホームページに そこでドで咫 C を取得するプログラム す。まずは , サーバの概略を見るために List 2 U 日 L で指定された資源を STDOUT へ出力 ( htget. 「 b ) 2 # ! /usr/bin/env ruby # htget.rb - get url and print tO stdout # usage: htget.rb url も を LL サーバも書こう class HTTPURL まを面ぎし社 6 朝 て . da [ 'location' ] ) if PRO [ 0 ] IOC. sub! ( 風Ⅳ [ 'http—proxy'] , ” h 鴕 p : / / れ② host } : # { 28r セ } つ job("forwarded: # い oc } つ { end rescue Net : : ProtoFata ー E てて 0 て STDERR. print 引 , ”れ” end def initialize(url) if URLPAT = ~ url @host = $1 @port = ()2 Ⅱ 80 ) . to ユ @port—given = $2 & true = $3 Ⅱ″だ "invalid url raise ArgumentError , end myhea 'Accept-Language' => ENV[ 'http—proxy'J ・ to—s [ $1 を ( $2. to ー土 ) ] # thost, po て t 」、 else [ れ土し n 土け def セ 0 ー s if @port—given "http:#{@host} :#{@port}#{@path}" ″ h 忱 p : れ@host } # {@pathド end private e Ob てま sg print msg,b»startinn if $DEBUG res yield if block—given? print msg をくくく done n をは f $DEBUG res end attr—reader : hOSt , : port , :path def get 00 夐れ ec れをい :HTTP. new(@host, *PROXY) ② po てセ , Net : begin job("getting: れ se げド ) { end if url = ARGV. shift if $DEBUG print ">>>>>>HEADER%nn header. each{lk,vl print "#{k} : # { v } ” } print ″くくくくくく日 EADER n 新 end print bOdy end 0 90 C MAGAZINE 2001 2

10. 月刊 C MAGAZINE 2001年2月号

も小さくなるという利点があります。 今まではこのインデックスリストはアプ リケーション側で管理しなければなりませ んでしたが , 今回からこれをビデオメモリ 上に置くことが可能になりました。これに より , インデックスリストに変更がない場 合に大きな性能向上が見込まれます。 作成方法については頂点バッフアとほば 同じです。インデックスのサイズは 16 ビッ トと 32 ビットの 2 通りが指定可能で , プリ ミテイプのサイズによって選択することが できます。これも頂点バッフアと同様 , ノヾ ッフア内にデータを詰め込んだあとは , デ バイスに有効であることを知らせておく必 要があります (IDirect3DDevice8::SetIndices ( ) , List2-(d))0 この第 2 パラメータには , 頂 点バッフアの中のオフセットを指定するよ うになっています。今回のサンプルでも , 頂点バッフアの中には 17 個目以降に lndexe dPrimitive() 用の頂点データを詰め込んでい ます。よって , このオフセットを 16 に設定 しています。 変換行列の設定 プログラマプルシェーダを使っていない ので , このサンプルではマトリクス演算を 今までどおりの Direct3D による演算で行っ ています (List 2- (e) ) 。 Direct3DX ライプラ リには非常に多くのマクロ関数があるので , これを使って簡単に投影変換行列やビュー イング変換行列などを作成することが可能 です。 もちろん今までどおりマトリクスを直接 定義することも可能になっています。透視 変換などでは演算効率をあげるためにユー ザ定義のものを選択することもありえるで しよう。 レンダリングステートの設定 設定方法などは以前のとおり , デバイス の SetRenderState ( ) を使っています。いく つかの設定項目が新設されていますが , こ こでは環境光の設定 (D3DRS-AMBIENT) イ 8 C MAGAZINE 2001 2 Fig. 6 サンプルプログラムに用いた立方体のモデル 19 0.14 22 1 8 10.12 23 1 6 3.5 21 を直接 DWORD で与えているくらいでしょ うか。テクスチャステージの設定も以前と 変史はありません ( List2- ( f) ) 。 最後に頂点に対するシェーディングをど のようにするかを設定する IDirect3DDevice 8::SetVertexShader ( ) を呼び出します。プ ログラマプル頂点シェーダを使う場合には ここでそのハンドルを渡すことになります が , それ以外の今までどおりのジオメトリ 変換処理を使う場合にはその頂点フォーマ ットを指定しておきます。このサンプルで は , マクロ定義しておいた , 1 テクスチャ , 座標 , 法線で構成されるフォーマットを指 定しています ( ⅱ st2- ( g ) ) 。 光源処理 , マテリアルの設定 こもほとんど変化はありません。サプ ルーチン化して切り出してありますが , れは List2-(h) を見ていただくだけで十分で しよう。 レンダリングループ 前処理が終わって , これから終了イベン トが発生するまでレンダリングを繰り返す ことになります。この部分が List2- ( i ) です。 List2- ( j ) はオプジェクトの変換行列を計算 しています。 こでは Direct3DX ライプラ リの行列演算用のラッパ関数を用いていま す。関数名からその機能が容易に推測でき ると思います。ワールド変換行列以外は固 定です。 これ以降も前述の Fig. 5 で示したフロー で処理が行われていきます。まずは IDirect3 DDevice8::BeginScene ( ) によってシーンの 描画開始を宣言しています。レンダリング ループの始めにシーンのクリアを入れてあ ります。ここではレンダリングターゲット のクリアと , PS ッフアのクリアを設定し ています。ステンシルを含める場合はさら にフラグを追加します。 IDirect3DDevice8:: 1 7 T 「 iangleListlndexed Primitive lndexedPrimitive として扱うために 頂点テータを共有している 6.8 STRIP Primitive 1 つの頂点に法線を 2 つ持たせるため にストリップエッジを重複させている 7.9 20 T 「 iangeIeList lndexed P 「 imitive