Ⅸ .2 に準拠している C ライプラリを持つシ ステムなら Linux に限らずどれでも利用可 能なはずです。 C ライプラリから提供されているヘッダ ファイル regex. h では , 正規表現関連の関数 として , regcomp ( ) , regexec ( ) , regerror ( ) , regfree() の 4 つの関数が宣言されています。 これらは , manvx—ジ regex(3) に詳しい説 明がありますが , ちょっとわかりにくいと ころもあるので , これらの関数を補足説明 します。 簡単に説明すると , 正規表現ライプラリ 正規表現パターン文字列をコンパイル 関数を使うときは , 次のような流れで使用 Column を . ・ ・ regcomp ( ) します。 ・ regexec ( ) 対象バッフアと正規表現パターンの検 索処理を行う ・ regfree ( ) コンパイルしたパターンをフリー int regcomp (regex—t * preg, 各関数の書式は , 次のようになります。 土 n cf lags); const char * regex, TabIe 1 「 egcomp ( ) の引数 cf gs に指定する値 土 n セ regexec (const regex—t * preg, const char * string, size—t nmatch, regmatch—t pmatch ロ , int ef lags); VOid regfree (regex—t * preg); 関数 regcomp ( ) の regex に正規表現パタ ーン文字列を指定して実行することで , pr eg が指す構造体の中にプリコンパイルされ たパターンが格納されます。また関数 regc omp ( ) の cflags に Table 1 の値を指定するこ 説明 値 REG EXTENDED REG ℃ ASE REG NEW 凵 NE REG_NOSUB 正規表現を使ったことのない方は , 正規表現パターンを謎めいた文 : 字列のように感じるかもしれません。次のように grep などのツールで コツをつかんでみましよう。慣れてくると離れられない存在になると 思います。 $ egrep て 00 ビ /etc/passwd ・・・「 00t がある行を表示 $ egrep *r' /etc/passwd ・・・「で始まる行を表示 $ eg て ep bash $ ' /etc/passwd TabIe A よく使われる正規表現 メタ文字 POS Ⅸ拡張正規表現を使用 大文字小文字の違いを無視 すべての文字にマッチするオペレータに改行をマッチさせない 部分文字列にマッチさせない ・・・ bash で終わっている行を表示 $ egrep ' [ 0 ー 9 ] { 3 } ' /etc/passwd ・・・ 3 桁の数字がある行を表示 $ egrep putsl printf' simp le-grep. c ・・・ puts または printf がある行を表示 TableA によく使われる正規表現のメタ文字を紹介しておきます。ま た manv<—ジ regex ⑦で文字クラスの説明がされています。表や man ページを参考に , chkinetcfg. c で使われている正規表現パターンを解析 してみてください。 マッチ対象の内容 {min, 十 max} 任意の文字 1 個にマッチする。・・ . " ( ドット ) だけにマッチさせたい場合は¥. を使う ロ内の任意の 1 文字にマッチする。 . [abc] の場合 , a, b または c が含まれる文字列にマッチする ロ内で指定された文字以外にマッチする。 . CAabc]] の場合 , a, b または c が含まれない文字列にマッチする UnixlLinux は , Un ⅸまたは Linux にマッチする min 以上に max までマッチする。 . [ 0-9 ] { 3 , 4 } は , 3 桁または 4 桁の整数にマッチする 0 または 1 個の要素にマッチする。 . string(s)? は , string, st 「 ings を含む文字列にマッチする ーの前後のバターンとマッチする。 行末位置にマッチする 行頭位置にマッチする 1 個以上にマッチする 0 個以上にマッチする ク、ルーピング。 ( ) 内でマッチしたものは , 参照可能なことを意味する 1 1 6 C MAGAZINE 2001 4
Fig. 8 回転軸 転を回転面のみでの計算に変換できます。 Fig. 9- ( a ) から回転後も成分ルに変化がない ことは明らかです。 Fig. 8 の右側の図が回 転面を上から見た図になります。 もう 1 つ補助になるべクトルを定義して おきましよう。それがです。このべクト ルは回転平面上にあり軸″に直行していて , なに対しても直行していることとします。 このような 2 軸に直行しているべクトルと いえば外積の登場です ( Fig. 9-(b))0 もと もとなに関しては分解成分であり , れは正 規化べクトルですから , この補助べクトル 氤おをと r との外積で求めることができます。 これでもう話は回転平面上での説明にな ります。回転先べクトルの垂直成分はな とを利用して Fig. 9- ( c ) のように表すこと ができ , 回転により変化しないルと合成し てやると , 回転後のべクトルドを作ること ができます。これが Fig. 9- ( d ) です。ちょっ とわかりにくい式のような気がするかもし れませんが , このように回転軸と回転角 度汐によってべクトル回転を表現できるこ とがわかりました。実はこの回転軸表現で あれば , 問題であったジンノヾルロックは回 0 避できるのです。「なんだ , じゃあそれで いいや」といわずにクオータニオンでの回 転も見ていってください。 クオータ二オンでの回転 さっそく始めましよう。まず , 回転され るべクトル r をクオータニオンで表すこと にします ( Fig. 10- ( a ) ) 。純虚数のべクトル 部によってべクトルを表現するわけですね。 それとまだ正体は明かせませんが , ある正 規化クオータニオンを用意することにし ます。 これらを使って , Fig. 10- ( b ) のような変 わった形の数式について考えてみましよう。 この数式ではある正規化クオータニオンに 純虚数を掛けて , それに最初の正規化クオ ータニオンの逆クオータニオンを掛けてい ます。いったい何を行っているのか想像が つきません。そこでこれを展開して調査し てみます。これには正規化クオータニオン の逆クオータニオンは , 共役と等しくなる ということが利用できます ( Fig. 10- ( c ) ) 。 少し省略しましたが , 最後の式に持ってく るまでに内積や外積の特性をうまく利用し ています。時間のある方は実際に計算して みるといいでしよう。 何だかいわくありげな形まで持ってきた ところ , 正規化クオータニオンだとしか教 えられていなかったが , 実は Fig. 10- ( d ) のような形をしていたとします。べクトル れが正規化べクトルだという前提で代入を 行ってみると , Fig. 10- ( e ) というふうに数 式を変化させることができます。このよう Fig. 9 べクトルを 2 つに分解して回転を考える ( a ) べクトル成分の分解 ( b ) 2 軸に直行しているべクトル (c) 回転先べクトルの垂直成分 r;=(cos )叮 + (sin ル ( d ) 回転後のべクトル =% + (cos 8 ) ら + (sin 8)v ″・加 + ( cos の ( ← ( ルわ司 + ( sin のれ x =(cos の r + ( 1 ー cos の可れす ) + ( sin のれ x ′ Enter The 3D Programming 1 1 1
LjIlllX 0 Ⅷ lll 腿 吉井一友 kazutomo@tu 「 bolinux. co.jp Linux で正規表現してみよう grep などのツールで文字列検索によく使われる正規表現が使えたらとても便利にな るプログラミングの場面はよくあります。今回は Linux のプログラムで , 正規表現を 用いたプログラムとそうではないプログラムを用意し , それぞれを比較してプログラ ミングでの利点を探り , 正規表現の使い方とそのプログラムへの組み込み方法につい て解説します。 でしよう。通常の string. h で定義されてい 正規表現を使わない実装と使った実装がど る文字列関数では限界があったり , ポイン の程度違うのかを比較してみましよう。 タでゴリゴリ書くのは , 思わぬバグを誘発 説明するまでもないと思いますが , 念の 今回は , 1 度はまってしまうと抜け出せ したりするものです。 ために /etc/hosts のフォーマット (Fig. 1 ) なくなる便利な正規表現について , C プロ その 1 つの解決法として正規表現ライプ を再確認の意味を含めて説明します。何ら グラムからの扱いを説明し , いくつか有用 ラリ関数を使用する方法があります。正規 かのファイルのパーサを実装する場合 , 対 な実装例を紹介します。 表現の書き方さえ理解していれば , 少々複 象ファイルのフォーマットを正しく理解す ある程度の規模のプログラム ( とくにネ 雑なファイルのパースも実装しやすくなる ることは非常に重要だからです。 Fig. 1 の ットワークデーモン系 ) を書く場合 , コン ようにまとめておくことをお勧めします。 ことでしよう。 フィギュレーションファイルの利用や操作 このフォーマットに基づいて , わざと先 正規表現を使わない実装 がつきものです。しかしコンフィギュレー 頭にスペースを入れたりした , ちょっとば vs 使った実装 ションファイルのパース ( 解析 ) を C 言語で かり意地悪なサンプル ( Fig. 2 ) を作成して とりあえず /etc/hosts のパースを例に 実装しようとして苦労した方も少なくない みました。 hosts. example のようなファイル Fig. 1 /etc/hosts のフォーマット Fig. 3 出力例 IP = ' 127.0.0.1 ' FQDN='localhost. localdomain' ALIAS='localhost' ・旧アドレスとホスト名を関連付けるファイルである " # " 文字から行末までは , コメントになる IP= ' 192.168.0.1 ' FQDN= gateway.localdomain' ALIAS= 'gateway IP = ' 192.168.0.2 ' FQDN='hoge.localdomain ・各フィールドは , ( 半角 ) スペースまたはタブで区切られる IP = ' 100.1 圓 . 0. ' FQDN='badip.locaIdomain ・有効な行は , 少なくとも旧アドレスとホスト名の組み合わせからなる ・旧アドレスとホスト名のあとに , 工リアスを記述できる 第⑦回 はじめに Fig. 4 正規表現を使わない実装での処理手順 1 行読み込む ・ StepO ・ # ' または \ n ' を発見したら , そこに NULL 文字を入れる ・ Step1 空の行の場合 , StepO へ ・ Step2 トークンセバレートを行う ・ Step3 1 つ目 ()P ) , 2 つ目 ( ホスト名 ) のトークンがある場合 , それらの ・ Step4 情報を出力する。さらに 3 つ目 ( 工リアス ) があれば , その情報を 出力する Fig. 2 hosts ファイル ( 設定サンプル ) # /etc/hosts # IPaddress (IPv4) FQDN (FulIy Qualified Domain Name AL I AS localhost .localdomain localhost 127.0.0.1 gateway.localdomain 192 .168.0.1 gateway 192.168.0.2 hoge コ OC 引 domain # comment badip.localdomain 100 . 100 . 0. 1 14 C MAGAZINE 2001 4
Fig. 10 クオータニオンでの回転 ( a ) 回転されるべクトル「をクオータニオン〃で表す ( b ) 正規化クオータ二オン 4 を用いて考える (c) (b) を展開 = ( 0 , @2 純・可r+2ル@x = ( 0.@2 ー冖ツ + 2 ” ) + 2 x ゆ ( d ) 正規化クオータニオンの内容 q=(cos の , sin のれ ) ( e ) べクトル″が正規化べクトルだという前提で ( d ) を代入したもの = ( 0 , ⑩→・ + 2 可・小 2 朝 x = ( 0 , (cos2 Ø-sin2 Ø)r + 2sin2 のれ ( れす ) + 2cos Øsin の ( れ x = ( 0 , cos2 + ( 1 ー cos2 の可ル r) + sin2 の ( ″ x ゆ ( f ) クオータニオンによる回転 q=(cos(9/2), sin(9/2)n) Fig. 11 行列によるクオータニオンの表記 ( a ) クオータニオンの乗算を行列として表記 花も—Z ア 2 十 ) ・ド 2 十工ル も + 肥鰺ー占 + ア ー ) ' さ 2 十十ド 2 十 Z ー占も一 ) ・一 z ド 2 十ルル アル 04 っ ~ っ 4 4 2 = ( b ) ん ( のの内容 Z 肥一 ( c ) 右から掛けることと同じ働きをする行歹衄 ー 2 鰺 ル Z ー 2 ェアもル 42 = ( 吶 ql = (d) 回転行列 4 = = ん ( の町加 2 い + 司 0 ル 2 イ 2 い一同 2 い一 ) 0 2 い + ル 2 → 2 を 2 ーっ 2 + 三 0 2 い一司 2 い + ) 0 0 0 に変化させると , 任意軸回転を行うための 順が加わるのなら , クオータニオンの採用 行列を作用させると , クオータニオンを左 数式とほとんど同じものが手に入ることが , は見送ろうかとさえ思ってしまいます。 から掛けた場合と同じ結果を得ることがで こからわかります。つまり , クオータニ そこで登場するのが行列による表記です。 きます。同様の考え方で , 今度は右から掛 オンでも任意軸回転ができるのです。違う ある行列を用いるとべクトルに行列を掛け けることと同じ働きをする行列 ( のを求 ところは , 結果が純クオータニオンである るだけでクオータニオンによる回転を行う めてみます ( Fig. 11- ( c ) ) 。 ということと , 回転角度が 2 / になってい ことができるのです。 このように左から掛けるような行列と右 ることだけです。 から掛けるような行列の 2 つを用いて回転 回転行列 回転についてまとめてみましよう。任意 行列を作成できるのです。回転用のクオー の正規化べクトルれを軸として回転角度〃 タニオンは正規化クオータニオン , 回転 ぶんの回転をベクトル r に適用するには , r まずは行列によって , クオータニオン同 の対象であるをは純クオータニオンである を純クオータニオン〃として取り扱い , F 士の乗算を表現できないか考えてみます。 ことに留意しながら , Fig. 11- (d) といった ig. 10- ( f ) のようなクオータニオンを用い クオータニオンの 4 つの要素を一軸 , J 軸 , 行列が手に入りました。長い道のりをたど K 軸 , 実軸の順番に並べたべクトルとして て , 1 の演算を行うということになり ってきましたが , どうやら一応の収穫があ 行列を作ってみます。 Fig. 11- ( a ) の式を見 ます。 ったみたいです。この 4 x4 行列はまさに回 これがクオータニオンによる回転の正体 てください。左側が乗算の計算結果を 4 要 転行列として使用することができます。回 素のべクトルとして表したものです。並ん だったのです。 転したい軸と , その角度から x, 乙Ⅳを でいる順序に注意しながら以前の乗算の式 算出し , このような行列を作成すると , も と同じものであることを確認してくださ うそれでジンバルロックを起こさない回転 い。右側のん ( に相当する行列を見つけ 方法が手に入るのです。 出すことによって , 行列によるクオータニ 1 つ注意を促しておきましよう。実軸を クオータニオンによる回転を見てきて , オン同士の乗算を表そうというわけです。 行列の 4 行目に持ってくることによって , どのような感想を抱かれたでしようか。た 見つかりやすいように並べておきました オイラー角での回転行列と同じような表現 ぶん卿ゲ 1 という演算に違和感があったの から , ん ( 4 ) はすぐに求めることができま が可能になったのですが , 同次座標系でい ではないかと思います。こんな不自然な手 すね。 Fig. 11- (b) のようになります。この うところのⅣとはまったく意味が違います。 行列での表記 1 1 2 C MAGAZINE 2 1 4
Fig. 5 クオータニオンの加減乗算 ( a ) 例となる数式 ql = 十も i 十 J = 肥 2 十も i 十 ) ・ 2j 十 z 講 ( b ) 加減算 ql+q = 0 町 + 朝 + + も ) i + 伝ザ万 + は + z 謎 ql ー 2 = 0 町一吶 + ( も一も ) i + づ万 + 6 ー z 謎 ( d ) 乗算 sq = s 肥十 & 十当ノ十 sz 為 ( c ) スカラー倍 逆クオータニオンを求めるために オンの乗算で行います。 に , クオータニオンの除算も逆クオ =@匙2ー町ら , ル画 + ル 2 ら + ら XV2) ー 4 = 朝广肥 2 , ら一朝 ql 十リ2=@げル2 , 十ら ) (b)Fig. 5 の加減算に , を用いた例 = く x , 鰺 z> ( a ) 3 次べクト丿いを用いた表記 べクトルを用いた表記方法 +@声2+肥2 + も ) ' 2 ー ) 2 十 0 町十ル 2 十 . X2 ー声 2 +@き2 + 肥げ ) ド 2 ー名 2 ) i ql =@卩む2 ーもも一 ) ・げ 2 ー z 声 2 ) (e) ( d ) をれえを用いて整理 + もん 0 + 2i + z い j + に + J 肥 2 十お 2i + の ' J 十第 十工き肥 2 十 X ー壟十ーり・ 2J 十工 Z = 7 町 2 十ル壟十ル 2J 十ル卩 2 ータニ いく つかの概念の説明を先にしておきましよう。 まずは , 絶対値です。これは複素数のとき に触れたようにべクトルと同じように求め ることができます (Fig. 7- (a) ) 。直感どお りですね。もちろん答えはスカラー ( 実数 ) になります。いわば長さを求めることがで きたので , 正規化べクトルのような正規化 クオータニオン (unit quaternion) というも のも考えられます。スカラー倍が可能であ るなら , スカラー除算も当然可能になるの で , Fig. 7- (b) のように長さが 1 のクオータ ニオンを作ることができます。この長さ 1 10 C MAGAZINE 2001 4 Fig. 7 逆クオータニオン ( a ) 絶対値 ( b ) 正規化クオータニオン rm 浦記 ( の = イ ( c ) 共役 ( d ) クオータ二オンと共役を掛け合わせる = 肥十・ ( e ) 同じもので割る / 2 = 1 ( f ) 逆クオータニオンの数式 4 4 / 2 が 1 のクオータニオン , あとで回転のこと を考える際に非常に重要になります。 また , 共役 (conjugate) というものも知 っておきましよう。複素数にも存在します が , 共役とはスカラー部分以外にマイナス を掛けたクオータニオンのことを指します (Fig. 7-(c))0 名前まで与えられているだけ あって , この共役にはいろいろとおもしろ い性質があります。たとえばクオータニオ ンとその共役を足せばスカラー部分が残る というのもそうですが , もっと利用価値の 高いものとしてクオータニオンとその共役 を掛け合わせてみましよう (Fig. 7-(d))0 れも答えがスカラーになります。それだけ ではなく長さの 2 乗なんていうできすぎた 答えが手に入りました。 そこで , ちょっとひねって Fig. 7- (e) のよ うな式を考えてみましよう。同じもので割 っているので , 答えは 1 になるのがあたり まえですが , この式はに何かを乗算する と 1 になるということも表しています。つ こで掛けているものが求めている まり , 逆クオータニオンです。 Fig. 7- (f) のように 逆クオータニオンは共役を絶対値の 2 乗で 割ったものになります。また , このクオー タニオンが正規化クオータニオンだった 場合 , 逆クオータニオンは共役そのものに なります。 逆クオータニオンが手に入って , 除算が 行えるようになりましたので , 不思議な i , j, から生まれた演算の仕組みはここまで になります。それにしても思っていたより 難しいところはありませんでしたよね。内 積や外積のほうがよっぱど理解しにくい 気がします。 回転との関係 それではいよいよ 3D プログラミングの 話題 , 回転の説明に進みます。クオータニ オンが回転をどう表すのか , またどう取り 扱うのかを見ていきます。 回転軸表現 いざクオータニオンでの回転に進む・・・ その前に , 回転軸表現 (Axis-angIe represe ntation) の説明をしておきましよう。問題 の多かったオイラー角表現では , X ) 努各軸 における回転角度によってオプジェクトの 姿勢を表現していましたが , 回転軸表現は 回転軸となるべクトルと , 回転角度によっ て姿勢の表現を行います。努軸にとらわ れない , 自由な軸を中心に回転させること から , 自由軸回転あるいは任意軸回転とも 呼ばれます。 ここで Fig. 8 の図を見ながら考えていき ましよう。回転軸となる正規化べクトルを れとして角度″の回転を行うとします。回 転の対象となる点を指すべクトルを r とし て回転後のべクトルをドとします。 こで話を簡単にするために , べクトル ′を 2 つのべクトルに分解することを考えま す。回転軸″に沿った平行成分べクトルル と , れに対して垂直に回転面を構成する垂 直成分なに分割します。べクトル成分の分 解といえば内積の登場です。 Fig. 9- ( a ) のよ うに分割することによって , べクトルの回
LiIlllX 舮間川川 TIPS たか ? 意味不明な文字列がある ? そう 名で保存しておいてください。 る List 1 のような実装にしてみました List 1 のコンパイルと実行方法は 思った人は , コラムのほうを参考にしてく このサンプルファイルを標準入力から読 $ cc -Wa Ⅱー 0 parse—hosts み込んで , 標準出力に Fig. 3 のような必要 ださい。 とりあえずここでは , な情報だけ出力するプログラムを記述して parse—hosts. c $ . /parse—hosts く hosts. examp 厄 $ cc -Wa Ⅱー 0 parse—hosts—regex みましよう。 のようになります。 parse—hosts—regex ・ c 正規表現を使わない実装 $ . /parse—hosts—regex く 正規表現を使った実装 まずは正規表現を使わないパーサを実装 hosts. example してみます。実装方法にはいろいろ考えら 次は正規表現 ( ライプラリ関数 ) を使って のようにコンパイルと実行をして , 前述の れると思いますが , 今回は Fig. 4 のような プログラムと同じ結果が得られるかどうか hosts ファイルのパーサを実装してみまし 手順で実装してみます。 よう。 List 2 がその実装例になります。いく 見ておいてください。 トークンを取り出すトークンセパレート ぶんソースコードが短くなったことに気づ 正規表現ライブラリ関数に をする場合 , 関数 strtok ( ) を使うとちょっ くでしよう ( ただし , ソースコードを短く ついて するのがここでの目的ではありません ) 。 とだけ楽になるかもしれませんが , あまり お勧めしたくないので , 1 文字ずっ走査す それ以外はどのようなことに気づかれまし 実は , 正規表現ライプラリ関数は , POS List 正規表現を使わない実装の例 ( pa 「 se ー hosts. c ) #include く std 土 0. h 〉 #include く string. h> #include <ctype ・ h> static VOid analyze—etchosts—noregex(void) char buf[BUFSIZ]; char tokens [ 3 Ⅱ BUFS 12 島 char *p; while( fgets(buf,sizeof(buf) ,stdin) ! = (char* )NULL ) { / * reset tokens buffer * / *tokens[0] = *tokens[ll = *tokens[2] = (char)NULL; / * eliminate comment and newline*/; if( (p=strchr( buf,(int)'#')) ! = ) *p = (char)NtJLL• if( (p=strchr( buf,(int) ' ' ) ) ! ま NULL ) *p = (char)NULL• / * search IP address * / p buf; for( ) { while( ! (isgraph( (int)*p) ! = 0 Ⅱ *p==(char)NULL) ) P 十 if( *p ! = (char)NULL ) { char * 場 t = tokens[n]; / * copying tO tokens buffer * / while( ! (isgraph((int)*p)==011*p==(char)NULL) ) * し十十 = * p 十十一 社 = (char)NULL; n 十十一 if( n==3 ) break; } 引 se break; List 1 int main ( 土 n argc , char *argv [ ] ) ana ー yze—etchosts—noregex ( 0 return 0 ー List 正規表現を使った実装の例 ( pa 「 se ー hosts ー「 egex. c ) #include く s 記土 0. h > #inc lude く string. h> #include <regex. h> static VOid ana ー yze—etchosts—regex ( VOid ) regex—t preg ー char buf[BUFSIZ]; regmatch—t pmatch [ 5 while( fgets(buf,sizeof(buf) ,stdin) ! = (char*)NULL ) { if( regexec(&preg,buf,5,pmatch,O) ! = REG—NOMATCH ) { printf("IP='%. *s' FQDN='%. *s' pmatch[ll . rm-eo-pmatch[ll . rm—so,&buf[pmatch[l] . て m ー SO ] , pmatch[2] . rm-eo-pmatch[2] . rm—so.&buftpmatch[2].てmー SO ] ); if( pmatch[31. rm-eo!=-l ) { printf( ″ ALIAS='%. *s' pmatch[4] . rm-eo-pmatch[4] . rm-so,&buf[pmatch[41. rm-so] if( strIen(t0kens[O])>0 & & strIen(tokens[1])>O ) ( printf("IP='%s' FQDN='%s' ",tokens[0] ,tokens[l] if( strlen(tokens[2])>0 ) { printf ( ″ ALIAS='%s'n,tokens[2] 潺 puts( regfree(&preg); int main(int argc, char *argv[ ] ) ana ー yze—etchosts—regex ( return 0 ー 1 1 5 Linux Prog 「 amming Tips
TabIe 2 取り出される部分文字列の内容 ・ユーザ INDEX 0 1 2 3 4 文字列の内容 全体 旧アドレス ホスト名 スペース + 工リアス 工リアス れるかもしれません。でも , このケ 場合は , 5 つが正解なのです。 まず基本的に r exec ( ) は , 全体に とで , 正規表現の検索動作を変更できます。 これらの値を論理和で接続することで複数 指定することが可能です。 regexec ( ) の基本動作は , s ⅲ ng が正規表 現パターンにマッチした場合 , 関数の戻り 値として 0 を返すといった簡単なものにな っています (grep のようなものだと思って ください ) 。マッチした部分文字列を取り 出そうとしようとした場合 , 若干ややこし くなります。 regexec() では , 正規表現パ ターン中でグルーピング指定している場 合 , 部分文字列のマッチング位置情報を得 ることができます。 nmatch で指定された個 数だけ , 構造体 regmatch-t が並んだ配列 pmatch にマッチした文字列の位置情報が 格納されます。 regmatch—t は typedef struct regoff—t rm—so ー regoff—t rm—eo ー } regmatch—t ー のような構成になっています。この中の rm so の値が -1 の場合 , マッチしていないこと を意味します。 parse hosts regex. c のー音5 もう 1 度 , parse_hosts—regex. c (List 2 ) を 見てみましよう。この例では regexec() で 5 つの部分文字列を取り出そうとしているこ とがわかると思います。ホストファイルの 書式ではフィールドは最大 3 つなのに , な ぜ 5 つ指定する必要があるのか疑問に思わ ースの , マッ ません。 ーンを記述しておくのもおしゃれかもしれ イルのコメントにマッチする正規表現パタ ルを作るような場合 , そのコンフィグファ のです。また , 何らかのコンフィグファイ 変えることができる強力でクールなものな だけを変更することで , 処理自体を大きく このように正規表現は , パターン文字列 イルではそうもいかないはずです。 か判断できますが , ほかのコンフィグファ 数 inet-aton() の戻り値で妥当な IP アドレス んどうかもしれません。 IP アドレスなら関 ェックルーチンを付けるのは , ちょっとめ いないプログラムに , この IP アドレスのチ 一方 , List1 のような正規表現を使って 思います った IP アドレスを検出しないようになると してみてください。これだけの変更で間違 に変更して , もう 1 度コンパイルと実行を を , ましたが , IP アドレスにマッチする , この間違った IP アドレスにもマッチしてい たか ? parse—hosts-regex. c の実装では , い文字列を入れていることに気がつきまし わざと IP アドレス ( I 内 4 ) としては妥当でな ちなみにホストファイルのサンプルでは , able 2 のようになります。 指定しなければなりません。まとめると T グループを定義しているので , 合計で 5 っ います。その中に " 工リアス " だけのサプ それがある場合のみマッチするようにして リアス " を 1 つのグループとして定義して , ションとして扱われるので , " スペース + 工 になります。もう 1 つは , 工リアスがオプ チした位置情報を返します。これで 3 + 1 で 4 LiIlllX pr 川川 lll ⅲ TIPS ちょっと便利なプログラムを 実装してみよう こまで紹介した regex ( ) を使って , 読む にはちょうどよい長さのプログラムを 2 つ ほど用意しました。 grep を実装してみよう 普段よく使う grep の実装例を示します。 名前は , simple - grep と名付けることにしま す ( 付録 CD-ROM に収録 )。標準入力や複 数ファイルの指定が可能だったり , よく使 われるオプション -c , -n , -1 , -i もサポート しているので , 本物の grep と見分けがつか ないかもしれません ( 冗談です ) 。 読者のみなさんに宿題を出します。 grep に実装されていて , このサンプルプログラ ムに実装されていないオプションの実装を 行ってみてください。たとえば , オプショ ン - q の実装などです。 inetd コンフィグ・ユーティリティを 実装してみよう インターネットスーパーサーバ inetd (ne tkit 版 inetd) の設定ファイルのパースや変更 を行うプログラムの例を紹介します。 Red Hat 系 Linux にあるシステムサービスの設 定ツール chkcon g の名前にちなんで , chk inetcfg と名付けることにします田 st3 ) 。 まず最初に , /etc/inetd. conf の書式を説 明します。 " # " 文字から行末までは , コメ ントになります。基本的に , 次に示すよう な 7 つのフィールドから構成されます。 ・サービス名 ・ソケットタイプ ・プロトコル ・フラグ ・サー / ヾ / ヾス ・サーバ引数 Linux Programming Tips
その証拠に , の第 4 要素は 0 になっていま すよね。とはいえ , この形の行列であれば , 回転をつかさどる 3X3 部分でしか影響があ りませんので , 今までの行列演算にそのま ま組み込んで使用することができます。 回転の合成 回転の説明のしめくくりとして , クオー タニオンの回転は合成できるという話をし ておきましよう。最初に ql だけ回転して , 続けて回転を行う場合を考えます。する と Fig. 12- ( a ) のような式で表すことができ ます。 2 度回転の手順を行うことと , ql とい うクオータニオンで 1 度に回転を行うこと はまったく同じになります。これを用いて , さらにクオータニオンの導入を楽にするい い方法があります。 Fig. 12- ( b ) のような体を作成して , それ を回転行列に変換させれば , 今までのオイ ラー角での 3D プログラミングへひそかに クオータニオンを潜り込ませることができ ます。努軸回転で指定をしつつ , ジンバ ルロックも回避することが可能になり , イ ンタフェイスはまったく変更することな しに扱うことができます。ただし , 回転 の順番には注意が必要です。 クオータニオンによって任意軸による回 転が行えるようになりました。最後の話題 は補間に関する説明です。感覚的な説明を 先にしておくと , ある回転を表現するクオ ータニオン ql と別の回転との間に , 新た に中間のクオータニオンを作成することで 補間を実現しています。また , そのような クオータニオンを生成できること自体に意 味がある場合もあります。 球面線形補間の説明を 2 次元で図示しな がら行ってみます。 Fig. 13- ( a ) の図のよう に , 2 次元べクトルとが存在していて , それぞれ正規化された ( 長さが 1 の ) べクト 補間の仕組み Fig. 12 回転の合成 ( a ) 最初にだけ回転して続けて q2 回転を行う場合 ( ql 四「耳ルり = 4 加匠尸 Fig. 13 ( a ) グラフ 回転軸 ( b ) クオータニオンを回転行列に変換させる数式 , 0 , 0 > ) く 2 , く 0 , sin—2,O>) く 0 , 0 , sin > ) qz=(COS 4 =(COS ーユ ( b ) 中間べクトル p の数式 sin(8(1-t)) sin(80 ルであるとします。 t は 0 から 1 の任意の数 であるとします。このとき中間べクト丿ゆ , は , Fig. 13- ( b ) という数式で表すことがで きます。中間べクトルは [ が 0 に近いほど 1 寄りに位置し , 砿 1 に近づくにつれ , ル 寄りに存在するという式です。この式の導 き方に関しては , 常微分や角速度などが登 場してくるので , こでは数式の紹介のみ にとどめます。 正規化されたべクトルは , 半径 1 の円周 に沿って移動することになります。弧を描 くわけですね。これを利用すると , から ルに向かって滑らかに補間されるべクトル を生成することができるのです。 次に , クオータニオンの場合の補間です が , 実はまったく同じ計算式でこれを行う ことができます。 t の関数である各係数を , クオータニオンに対してスカラー乗算して やれば同じことが行えます。 実際に使用する際には , パラメータとし て存在する″はクオータニオン同士 , つま り 4 次元べクトルでの内積から求めること ができます。注意すべきこととして , 角度 ″が 0 度や 180 度に近い場合 , つまり sin ″ が 0 になってしまいそうな際には 0 除算を回 避する策を用意しておかなければいけませ ん。また , 180 度を超える角度の補間は行 えません。日本から南極経由で北極に行き たくても , 飛行機は勝手に北上してしまう のです。 今回は , 3D プログラミングに登場する クオータニオンにまつわる話を網羅してみ ました。実際に使用するにはまだまだ説明 の足りない部分も多いのですが , それでも 読み始める前と比べると , クオータニオン に対する印象がずいぶん変わったのではな いでしようか さて , 次回はまたまったく違った分野の ことを取り上げてみたいと思います。以前 光の話をしたときに「まじめに計算しよう なんてどうかしている」と表現した話題 , ラ まとめ ジオシティの登場です。 Enter The 3D Programming 1 1 3
nd です。これを使うと , List 3 のようにな ります。 こでは , File::Find モジュールの findde pth というサプルーチンを利用しています。 このサプルーチンは , finddepth (*&zip—it , $name); という書式で用い , $ name 以下のディレク トリを順番に巡回 ( スキャン ) し , 工ントリ が見つかるごとにサプルーチン & zip ー it を コールバックします。コールノヾックされた サプルーチンの中では , $File::Find::name にディレクトリ名付きのエントリ名が格納 され , $ ーにそのディレクトリ内のエントリ 名が格納されます。 List3 ではいったん配列@ⅱles にエントリ 名を格納してから , addFiIe を呼び出して います。 zip ファイルから readme を抽出する 今度は , zip ファイルからファイルの内 容を抽出してみましよう。ただ展開しても つまらないので , zip ファイルの中に「 REA DME ファイルらしきものが含まれていたら 表示」するようなスクリプトを書いてみま しよう。 zip ファイルの中には , ファイルの内容 を説明した README というテキストファ イルが含まれることが多いです。しかしそ のファイル名にルールがあるわけではない Readme. 1 st README readme. txt ので , 0 List 4(readme-zip1. (l) に示します ( 実行結 でいたらその内容を表示するスクリプトを れ , ともかく readme という文字列を含ん 現」を使いましよう。ファイル名が何であ こういうときには PerI お得意の「正規表 せるにはどうしたらいいでしようか とわかるのですが , それをスクリプトにさ 人間が見れば「あ , これが README だな」 などのようなバリエーションが生じます。 果は Fig. 6 ) 。 こでは , elist にファイル名を得て , そのあとの forea ch 文でその中から , /readme/i いったん配列@fil List if (@ARGV く = 1 ) { use Archive: :zip , ( :ERROR—CODES); use strict; zip ファイルを作成する (makezipl. pl) ています。 / i というのは大文字小文字を無 という正規表現にマッチするものを見つけ 視する指定です。 もし , 拡張子が . ⅸ t のもののみを表示し たかったら , . txt$/i のように指定します。もしも , 拡張子が . c , ・ cpp, . h, . java のもののみを表示したいと print STDERR "Usage: perl makezipl. pl zipfile. zip d 土て -0 て - f e ex 辻 ( 0 my $zipfilename = shift @ARGV; my $zip = Archive: :Zip->new( foreach my $name (@ARGV) { &zip—recurse($zip, $name); my $result = $zip->writeToFiIeNamed($zipfiIename); if ()d $name) { my ($zip, $name) = 釭 sub zip—recurse { ex 辻 ( 0 die ”引” if ($result ! = AZ-OK) { opendir(DIR, $name); foreach (readdir(DIR) ) next if ( / 、 . / &zip—recurse( $ziP' ) elsif ()f $name) { print "Adding $name%nn $zip->addFile($name, } else { . /$name" # ファイルを追加 print STDERR ” ? $name%n"; push(@files, $name); print "Adding $name%n" return unless ()f $-); my $name = $FiIe: :Find: :name; sub zip—it { exit(0); die ″引” if ($result ! = AZ-OK) { my $result = $zip->writeToFileNamed( $zipfilename); $zip->addFile($name, ″ . /$name" foreach my $name (@files) { finddepth ( *&zip—it , $name foreach my $name (@ARGV) { my @files; my $zip = Archive: :Zip->new( my $zipfilename = shift @ARGV; ex ( 0 p て土 n セ STDERR "Usage: perl makezip2. pl zipfile. zip d 土て一 0 て一 f e if (@ARGV く = 1 ) { use File: :Find; use Archive: :Zip Ⅱ :ERROR—CODES); use strict; File::Find を使ってディレクトリをスキャン (makezip2. pl) List 88 C MAGAZINE 2 1 4
、 Bookends 3 月発売予定の新刊 ( 0 は CD-ROM 付 ) 書籍名 U N IX/Li nux コマンドリテラシー Am ⅳ Afzal UN Ⅸコンピュータリテラシー第 2 版ーネッ 渡辺成良 , ほか トワーク時代の計算機利用とモラルー 砂原秀樹 , 石井秀治 U 改訂版プロフェショナル BSD 植原啓介 , ほか パワーアップ Free BSD 技術評論社編 X Sandra Henry-Stocker, So ぬ ris 管理ガイド Evan R. Marks Gary V. Vaughan, GNU Autoconf/Automake/LibtooI Ben Ellison, ほか コンピュータグラフィックス James D. FoIey, Andries 理論と実践 van Dam, ほか ひとはなぜコンピューターを人 Byron Reeves, CIifford 間として扱うか ? Nass ソフトウェア見積りのすべて一規 Capers Jones 模・品質・エ数・エ期の予測法ー 井上直 正規表現の達人 コンピュータサイエンス誌「 bit 」別冊 小林龍生 , ほか編 インターネット時代の文字コード CODE ーインターネットの合 Lawrence Lessig 法・違法・プライバシー 小山仁 コンサルタント入門 引地ー男 , テクノクエス 図解入門インターネットのしく ト株式会社 み インターネット・ルーティング Christian Huitema 高速 Ethernet の理論と実装 Breyer & RiIey Marcus Goncalves, Kitty 旧 v6 プロトコル徹底解説 ¥ 3 , 800 Niles マネシャーのためのテータベー Michael Blaha ス技法入門 PHP + RDBMS Web サーバーで 0 伊藤博康 のデータベース活用術 Windows プログラミング Windows プログラミング Vol.6 0 愛好会 Oracle 500 の技 Ben Chang, Mark ORACLE XML ハンドブック Scardina XML と Java による EAI JP Morgenthal 通信・ネットワーク用語辞典 井上孝司 2001 年版 情報技術用語大事典 オーム社編 内容 出版社 UNIX, Linux を初めて習う人を対象に , 基本的なコマンド ¥ 3 , 400 を演習形式で丁寧に解説。 Linux などのパソコン UNIX ユー ピアソン・エテュケー ンヨン ザ向けの演習書 , 独習書として最適 UN Ⅸワークステーションの利用技術入門書。第 2 版では , 共立出版 BSD を SVR4 に変更 BSD/OS 4.1 はもちろん、 FreeBSD4.2, XFree86 4.0 にも ¥ 2 , 800 対応。付属 CD - ROM には著者自身のドットファイルやリ アスキー ンク集、 PDF を収録 TS0ftware DesignJ の FreeBSD 関連記事を大幅に加筆 / 修正し , ¥ 1 , 880 技術評論社 最新安定版 & オリジナルセレクションの FreeBSD RELEASE 4.2 を付録として添付。これ 1 冊で快適な F 「 eeBSD ライフ ! So ね「 is システム管理者の初心者から熟練者までを対象読 ¥ 4 , 200 者とした , SoIaris システム管理の行き届いたネットワー 翔泳社 クを実現する方法に関する総合的な解説書 さまざまなプラットホーム上でソフトウェアを動作させ ¥ 3 , 800 るための開発ツールである GNU Autotoo について紹介す オーム社 る , 国内初の解説書 CG プログラミングのバイブル "Computer Gra hics:Princi ples and Practice(Second Edition in C ) " の待の翻訳版。 ¥ 12 , 000 オーム社 基礎から応用まで , CG の理論と実装のヒントを紹介 メディアにとって大事なのは形だけの「ユーサビリティ」だ 翔泳社 ¥ 2 , 600 けじゃない。 Mic 「 0S0 負の製品開発に大きな役割を果たした 2 人が , 新しいメディアデザインの原理を提示する 開発遅延やコスト超過などの悲劇を避け , ソフトウェア 構造計画研究所 / 共立出版 開発を成功に導くための必読の書。冨野壽監訳 Linux ユーザ・システム管理者 , Web 制作者・管理者 , プ ソフトバンクバブリッシング ¥ 2 , 800 ログラマなどが直面しやすい問題に対する正規表現を使っ た解決策を多くあげ , 業務でのさまざまな応用方法を解説 文字化けなど文字コードをめぐる問題を提起。国語審議 会から答申が出された表外漢字体表を含め , 豊富な討議 共立出版 資料を用意 Microsoft の独占禁止法裁判において連邦裁判所に「スペシ ャルマスター」に任命されたサイバー法の第一人者レッシ 翔泳社 グ教授が、インターネットによる変化と法の対応を説く 戦略立案を含めたぼイヒ計画からツールの導入など , 江経営 とは何かがわかる。注目の新資格日 T コーディネータ」につ ¥ 1 , 800 アスキー いての情報も掲載 インターネット、ホームページや通信・メールの仕組みか ¥ 1 , 900 ら XML などの最新動向まで , インターネットに関するす アスキー べてをやさしく解説 本書は , B の長 , Christian Huitema が書いたベストセラ ーの完全改訂書であり、ネットワーク・プロフェッショ 翔泳社 ナルのための「古典」ともいえる必携書の日本初訳出書 わずか 2.94Mbps でスタートした Ethernet が , 今 10Gbps に ¥ 4 , 200 至ろうとしている。本書は Ethernet の歴史とネットワーク アスキー 配備や実装について解説する 本格普及のフェーズに入り始めた旧 v6 の全容を知るため 日経 BP に必携。現行の旧 v4 との混在 / 移行手法について詳説 各部門マネジャー , 技術関連スタッフなどを対象に , 実 ¥ 2 , 800 践的情報も盛り込みながらデータベース技術に関連する ピアソン・エテュケー ンヨン 基本事項を解説 レンタルサーバを利用した Web 構築において , 掲示板を 工ーアイ出版 ¥ 3 , 200 作成したりショッピングカートなどの受注システムを作 成するための必須知識を解説 Orac との接続で利用される 0040 , ASP, 捜査に必要な P ¥ 2 , 180 L/SQL などの必須知識から , Java との連携 , データベース 技術評論社 チューニングなど , 幅広く知ることができるテクニック集 定評ある弊社ロングセラーの 0 「 ac 厄 P 「 ess シリーズの 1 冊 ¥ 3 , 800 で , 実践的サンプルを元に XML と 0 「 acle8i を利用した Web 翔泳社 アプリケーション構築法を実践的に解説 Java と XML を活用して EAI( 工ンタープライズアプリケー ¥ 5 , 200 ション統合 ) を実現するための方法を , 手順や実例を示し ピアソン・エデュケーンヨン ながらわかりやすく解説 LAN, インターネット , 衛星通信 , 電話など , 通信・ネッ トワークに関する 4 , 000 の用語を , 最新の情報で解説した 秀和システム 用語辞典。複雑な用語・略語の氾濫に悩んでいる方に最適 ( 情報技術 ) に関連する基本用語から実用用語 , 専門用語 , ¥ 15 , 000 ビジネス用語まで 1 万語を , 正確な定義と簡潔明撩な解説 オーム社 により信頼性の高い事典として発行。相磯秀夫監修 著 者 ¥ 2 , 400 ¥ 5 , 000 ¥ 4 , 286 ¥ 2 , 800 ¥ 5 , 800 その他 ¥ 2 , 800 1 イ / Cmaga Bookends