List pe 「でコマンドラインから入力された引数を表示する が , 正規表現のメタ文字として使われてい す。ひとつはシフト JIS コードを使わずに る記号が検索文字列に含まれているときに 日本語 EUC コードを使うことです。日本 は注意が必要です。たとえば C 言語の配列 語 EUC の文字コードは最上位ビットが立 (a [i] のようなもの ) を検索するため " [ " を っているので , 1 バイトの英記号で使われ 含む行を表示しようとしたとします。 ている範囲と重なることがありません。 でたとえば , もうひとつの方法は日本語対応になって print grep(/[/, く FILE>) ; いる JPerI を使うことです。 JPerI では日本 # 誤り のようにすると , プログラムは , 語の文字を 1 文字として認識するので 2 ノヾ / [ / : unmatched [ ] in regexp . イト目がほかの文字と誤解されてしまうと というエラーメッセージを出して終了して いう心配がなくなります。 しまいます。このエラーメッセージは「正 ・コマンドラインの引数 規表現 ( regexp ) のなかで " [ ] " が対応して いません」という意味です。実は " [ " と " ] " 検索する文字列をプログラムのなかに埋 は正規表現のなかで文字クラスというもの め込んでしまうと , 検索文字列を変更する を表現するためのメタ文字で , 必ず " [ " と " ] " 必要が生じたときにいちいちプログラムを と書くことができます。配列@ARGV を数 が対になっていなくてはなりません ( 文字 修正しなくてはなりません。これを避ける 値比較である = = 演算子で使っていますね。 クラスというのは , 正規表現のなかで " [ a ー には , コマンドラインから検索文字列を入 このとき , 配列@ARGV は要素の個数を返 z ] " で英小文字 1 文字を表したり , " [ 13579 ] " 力することです。コマンドラインで perl ス すことになります。 C 言語ではコマンドラ で奇数の数字 1 文字を表したりするための クリプトに与えられた引数は , 特殊な配列 , インの引数は , もの ) 。 " [ " のメタ文字としての効果をな / * C 言語 * / @ARGV くすためには前に " \ " を置いて次のように に格納されています ( ARGV の部分は大文 main (int argc, char * argv[] ) します。 字 ) 。これは引数列 (argument vector) を表 の argc と ar のふたつの仮引数で知ること print grep(M/, く FILE>] ; しています。個々の引数は順に # 正しい ができました。 Perl では配列@ARGV だけ たとえば , [i] という文字列を探すには $ARGV [ 0 ] で知ることができます。ちなみに Java 言語 次のように書きます。 $ARGV[I ] の配列も自分の長さを知っているので , print grep(/%[i%]/, <FILE>) ; # 正しい $ARGV[2] 三五 * / / * Java= ⅱロ 個々の記号の前に \ を置く代わりに全体 $ARGV[3] main (String [ ] args) を }Q—YE でくくることもできます。 }Q— の args というひとつの仮引数でコマンドラ \ E の範囲にあるメタ文字は自動的に \ が付 としてアクセスできます。何個の引数が与 インからの引数を知ることができます。配 えられたかは , 別の特殊な変数 $ ARGC で いたのと同じように扱われます。 列の要素数は args. len h で得られます。 与えられま・・・・・・いいえ , 違います。 perl の print grep(/YQ[i]YE/, <FILE>) ; # 正しい コマンドラインから入力された引数を表 配列は自分の大きさを知っています。 perl 示するプログラムを上記の 3 種類の言語で ・日本語を扱ううえでの注意点 の配列をスカラコンテキストで評価すれ 書いてみましよう ( List4 ~ 6 ) 。比較してみ 日本語を扱う場合には注意が必要です。 ば , 配列の要素数を得ることができます。 てください。ただし , 0 番目の引数の意味 2 バイト文字のなかに検索する文字がたま つまり , 引数がないときの if 文は , は C 言語だけ異なります。 C 言語だけ 0 番目 たま含まれてしまう場合があるからです。 if (@ARGV = = 0 ) { の引数はコマンド名になるからです。 Perl たとえば Windows で使われている文字コ die ”引数がありません¥ n ” で $ ARGV [ 0 ] はコマンドではなく引数です。 ード ( シフト JIS) では , 「データ」や「コンピ List Java でコマンドラインから入力された引数を表示する ュータ」で使われている「一」の 2 バイト目 が [ と同じ値になります ( 16 進数で 5B ) 。つ まり , / \ [ / を使って検索すると , 「データ」 や「コンピュータ」にマッチしてしまうこ とになるのです。 これを避ける方法は大きくふたつありま 92 C MAGAZINE 2000 4 1 foreach $arg (@ARGV) { print ” $arg%nn; 2 List c 言語でコマンドラインから ) 功された引数を表示する 1 : #include <stdio. h> 2 : 3 : void main(int argc, char * a て [ J) int 新 5 : 6 : 7 : 8 : for ( 土 = i く argc; i 十十 ) { printf("%s%n", argv[i] 1 : class Test { public static void main(String[ ] args) { 2 : f0 て (int 土 = i く args.length; 土十十 ) { 3 : System. out. println(args[i] 4 : 5 : 6 :
Java フロクラミングリファレンス 詳説ル K 解体新斟 Fig. 3 0. 0.0 0d OF 0. D 0d 0. OD 0. F 0. OF 0e1 0e + 1 0e -1 0e1d 0e + If .0 浮動小数リテラルの例 ″ double リテラル 〃 double リテラル //double リテラル / / double リテラル ″ float リテラル //double リテラル ″ double リテラル //double リテラル 〃 float リテラル ″ float リテラル ″ float リテラル / / double リテラル //double リテラル / / double リテラル ″ double リテラル //float リテラル TabIe 1 型 int long TabIe 2 型 float double TabIe 3 整数リテラルの値の範囲 幅 32 64 範囲 -2147483648 ~ 2147483647 -9223372036854775808 ~ 9223372036854775807 浮動小数リテラルの範囲 内部形式 旧 EE754 単精度 旧 EE754 倍精度 ビット 範囲 32 士 ( 1 .40239846e -45 ~ 3.40282347e + 38 ) 64 士 ( 4.94065645841246544e -324 ~ 1 .79769313486231570e + 308 ) Unicode 工スケープ以外のエスケープシーケンス もっとも簡単な浮動小数リテラルである。 もちろんフルコースの「数字 + 小数点 + 数字 + 指数 + サフィックス」という形式であって もかまわない。 浮動小数リテラルは意外にバリエーショ ンが豊富で , 形式定義や言葉による説明だ けではわかりづらいので , いくつかの例を Fig. 3 に示した。たとえば「 ld 」とか「 OF 」な どは一見すると 16 進リテラルを記そうとし て , 先頭に「阪」を書き忘れたのかと誤解す るかもしれないが , これらはれつきとした 浮動小数リテラルであるから注意が必要で ある。また , 浮動小数として許容される値 は , Table2 に示した範囲になる ( この場合 も符号を付けると厳密には単項式になる ) 。 double の値は , 指数が正負で対称になって いない点に注意が必要である。 「論理リテラル」は true か false のいずれか であって , boolean 型である。文法上はこれ 3.14159e + 304 ″ double リテラル 3.14159e + 304d / / double リテラル 3.14159e + 304f / / float リテラル Fig. 4 8 進工スケープの構文 8 進工スケープ : ¥ 8 進数字 ¥ 8 進数字 8 進数字 ¥ 0 から 3 8 進数字 8 進数字 8 進数字 : one of 0 1 2 3 4 5 6 7 0 から 3 : one of 0 1 2 3 工スケープシーケンス ¥ b ¥ t ¥ n vf 8 進工スケープ Vu0008 : バックスペース 水平タブ 改行 ( ソース中に・¥ uOOOa ・と記すことはできない ) Vu000c . フォームフィード ( 改ページ ) 復帰 Vu0022 . ダブルクオート「 " 」 %u0027 . シングルクオート「・」 Vu005c . バックスラッシュ「¥」 ¥¥ u00ff : 該当する 8 進値 意味 Vu000d Vu000a Vu0009 らのトークンはキーワードではないが , 予 約語である。したがって , プログラマが tr ue, false という綴りの識別子を利用するこ とはできない。 「文字リテラル」は , シングルクオート円 で囲まれた 1 文字であり , char 型になる。 ただしこの「 1 文字」には , バックスラッシ ュ「 \ 」およびシングルクオート円を除く任 意の入力文字 ( すなわち行末文字以外の Uni code 文字 ) か , あるいはエスケープシーケ ンスを指定することができる。シングルク オートやバックスラッシュ自身 , あるいは 行末文字を指定する場合には , ェスケープ シーケンスを用いる必要がある。 代表的なエスケープシーケンスは Unico de 工スケープと呼ばれるもので , 「 \ u 」のあ とに 4 桁の 16 進数字を用いて指定する。た とえば卩 \ u0041 リは「 'A' 」と同じである ( 特 別な形式として , 「 \ 」のあとには「 u 」を複数 指定してもかまわない ) 。 こで , 工スケープシーケンスとしては Unicode 工スケープ以外に Table 3 の最後 に示すような 8 進表記のエスケープシーケ ンスも許す。この詳しい構文規則は Fig. 4 に示すとおりであり , 最大 8 桁までの 8 進数 で文字コードを指定するもので , C の同様 の構文とよく似ている。これまた正確にい えば , Java では 8 進 3 桁で指定する場合 , 最 初の数字は 0 ~ 3 でなければならないとなっ ているが , C の場合任意の 8 進数字でよい。 たとえば , 「判 56 リという文字定数は C では ( いちおう ) 正しい文字定数と認識されるが , Java ではエラーである。 ちょっと話が先走るが , 文字リテラルで はなく文字列リテラルでもこの点は同じで , 「 " \ 456 " 」といった 8 進工スケープを用いた場 合には「 " \ 4 " + " 56 " 」とか「 " \ 45 " + " 6 " 」のように 解釈するのではなく , 工ラーになる ( 少な くとも JDK 系の処理系ではそうである ) 。 また ANSI C が許す卩 la リといった形 式の 16 進表記によるエスケープは Java には 用意されていない。 Unicode 工スケープが あればこれは不要だからである。 なお Unicode 工スケープで注意すべきは , この表現形式はコンパイルフェーズのきわ めて早い段階で展開され , それが表してい る本来の文字に置き換えられるということ である。たとえば卩 \ u0041 リは早い段階で Java プログラミングリファレンス詳説 JDK 解体新書 111
if( Character. isspaceChar( ch ) ) { / / スペース文字 if ( cur_chnum 《 1 ) { て e セⅡて n ( gotSpace = false ) ー 3 : 7 : 9 : 10 : 11 : 12 : 13 : 15 : 16 : 17 : 18 : Fig. 2 List 1 候補語の直後の 1 文字を調べる 1 : 日セ at 土 0 final string 。 = " がはをだでもとにや、 ( ) / ′ ( ) 物 / / 直後の 1 文字 2 : boolean isVa1idPostfixChar( char postCh ) { “など”だけ Korn シェル・・・これは OK 4 : if( gotNO = = true ) return true; / / , の , を含む語は無条件に OK とする return( vpc. indexOf ( ( 土 nt ) PO 日セ C れ ) ! = -1 ) ー List 2 語の直後の複数文字を調べる 1 : boolean isVa1idpostfixStr( String po 日し S にて ) { return( po 日 ts セて . BtartSWith( 。など " ) / / 今は List 3 索引候補語を構成する文字なら t 「 ue を返す 1 : boolean 土 sVa1 idForrndex ( char c れ′ int cur—chnum ) { } / / 冒頭のスペース } / / 連続しているスペース else if ( gotSpace ) { return false; else{ return( gotspace = true ) / / それ以外のスペースは true / / ↑スペースを拾ったよ ! gotSpace = fal 日 e ー / / スペースは拾っていません ! if( 土日 NO ( 0 ) & & cur—chnum 》 0 & & gotNO = = false ) { return( gotN0 = true / / 語間の ' の ' は一つだけ拾います }else if( isKatakana( ch ) Ⅱ土日 Ran 」土 ( ch ) Ⅱ iBA1phaOrDigit ( ch ) ) { return true ー }else if( isSpecia1Symb01 ( c れ . cur—chnum ) ) { return tru 町 / / アンダスコア文字などプログラミングで使う特殊文字 }else{ return false; 一部の重要語句を拾えない場合 (a) パラグラフ ( 行 ) のサンプル シェルの設定ファイル」 ogin は C シェル , . P 「 Of ⅱ e は KO 「 n シェルのものであり , 前者は bash でもその ままの名で使用できる。それでは java. text バッケージと java. swint. text バッケージを見てみよう。と ころで私は , JDK 1 . O をあまり使い込んだことがない。 (b) 上の例文から拾われる語句 [ 拾いたい語句 ] 」 ogin C シェル p 「 OfiI e Ko 「 n シェル bash java. text)t ッケージ java. swing. text ノヾッケージ JDK 1 . O [ 実際に拾われる語句 ] シェルの設定ファイル 私 -NA- text)t ッケージ 使用 名 bash 前者 p 「 OfiIe C シェル login ・これは O K ・・これは O K " ばかり " とか " から " , " より " などなど , もっと多くの文字列を調べたいでしよう。 ックの開始です。今後スペースに出会った は , スペース文字以外の文字に関するチェ isVaIidForIndex ( ) メソッドの 7 行目以降 ほど説明します。 ッド adjustCharTraiIer ( ) については , のち 語から , 要らない末尾文字を取り去るメソ のちほど , それを取り去る処理をします。 字は語の末尾にあることになりますから , ただしそのような場合に拾ったスペース文 字とみなされ , そこで語を終結させます。 そのスペース文字は 4 行目により非有効文 ペースの直後にさらにスペースがあると , ペースーっだけを拾います。その拾ったス ペースは拾いません。 5 行目で , 最初のス す。語頭のスペースと二つ以上連続するス では拾うべきスペース文字を拾っていま 分は説明が必要かもしれません。 1 ~ 6 行目 ( 10 行目以降 ) は単純明快ですが , 前半部 この isVaIidForIndex ( ) メソッドの後半 ( ) を見ましよう (List3)0 文字種を判定するメソッド isVaIidForIndex えましたから , 次は候補語本体を構成する 文字 ~ 文字列に関する判定部分の説明を終 以上で , 候補語本体ではなくその直後の ックする必要はありません。 ッドで ue になりますから , こちらでチェ 初の文字が上の isValidPostfixChar ( ) メソ ただし " だから " とか " によって " などは最 C 言語フォーラム 139 いないために , 一部の重要語句を拾えない リオド文字・ . ' を候補語構成文字とみなして 上の文字種判定メソッドでは ASCII のピ OK をだしています。 する特殊文字 ( アンダスコア文字など ) に 英数字 , および Java や C プログラムで使用 部分 ( 10 ~ 14 行目 ) では , 片仮名 , 漢字 , isVaIidForIndex ( ) メソッドのそれ以降の て OK をだします。 語中で初めて出会ったーっの・の ' に対し ます。そして 8 , 9 行目では , 語頭ではなく てないよ " というフラグをセットしておき ときのために , " スペース文字はまだ拾っ
特 : 別 : 記 ! 事 インターネットをはじめとするネットワーも注目されている技術のひとつである。こ クを利用する際に , 悪意のある不正なアクの記事では , カシオ計算機 ( 株 ) より提供さ セスからデータを保護する方法のひとっとれた資料を元に , 同社が開発した多次元べ して「暗号」の利用がある。日音号は , 今後のクトル回転を利用する最新の暗号技術「 M 「 e - 」ビジネスの発展とともにさらに重要な DSR 」の技術内容や特性について紹介す 技術となることが予想され , いま , もっとる。 多次元べク N レ回転による暗号化技術 M ロ SR 太田純 だ。情報が守られるべき財産とみなされる 速に進む。 14 世紀ごろイタリアで使われ はじめに ようになったころから , 人間はさまざまな るようになった隠語表による暗号は , その 暗号化手法を作り出し , 活用してきた。 後フランスで高度に発達し , コードブック 近年になってさまざまな企業が暗号技術 現代はインターネットに代表される情報 暗号として結実した。これは暗号化の途中 メディアが高度に発達し , さまざまな情報 で換字表をつぎつぎに取り替えていくもの に参入しているが , カシオ計算機からも M DSR(MuIti-Dimensional Space Ro ねⅱ on ) と が開かれたパイプラインのなかを日々流れ で , “多表式”と呼ばれることもある。この 呼ばれる暗号化手法が発表されている。 ている。このため暗号の利用はきわめて重 手法はその後何世紀にもわたって使われ , 暗号の用途も外交暗号から軍事暗号 , 商業 れは多次元べクトル回転によって生成され 要で切実なものとなり , これを実現するた めの暗号化手法も多種多様なものが開発さ 暗号へと広がっていく。 る乱数列を利用したもので , 暗号化と復号 れている (TabIe 1 ) 。 20 世紀になると無線通信の発達により に一般的なハードウェアが利用できるので 暗号の必要性が高まり , 暗号化を自動的に 応用範囲が広い。同社ではとくに携帯情報 暗号の歴史 行う暗号機の開発が盛んになる。第二次大 機器分野での応用に期待しているようだ。 暗号の歴史は遠く古代エジプトやギリシ 戦でドイツが軍事・外交用に使ったェニグ この記事では MDSR の中核となる多次元 マ暗号機は多表式暗号を機械化した暗号機 アの時代にまでさかのばる。 べクトル回転の実現方法とそれを用いた暗 古典的な暗号としては , 平文 ( 暗号化さ としてよく知られている。 号化手順について解説する。また , カシオ バーナム暗号はテレタイプで平文と乱数 計算機の提供による Windows 用のサンプ れる前の文。人が読んでそのまま理解でき ルプログラムが付録 CD - ROM に収録され 列のさん孔テープを同時に流すことによ る文 ) 中の文字を規則的に別の文字で置き り , ビット単位の排他的論理和による暗号 ているので , 暗号化のようすを実際に確認 換えて暗号化する“換字式暗号”や一定の手 化を行う手法だ。電子化も容易であり , 平 することも可能だ。 続きに従って文字位置の交換を行う“転置 暗号技術を理解するにはその背景をある 文と同じ長さの乱数列を使い , 同じ乱数列 式暗号”が有名だ。 程度知っておく必要がある。そのため , スパルタではスキュターレと呼ばれる棒 を二度と使わないかぎり , 原理的に解読不 こではまず暗号一般についての仕組みと性 可能という特徴を持つ。その後 , 計算機の を用いた転置式暗号が使われた。ジュリア 質を概観し , その後 MDSR の技術的詳細や 利用によって短い鍵からきわめて長い擬似 スシーザーが発明したといわれるシーザー 特性に触れることにしよう。 暗号は , アルファベットを 4 文字シフトし 乱数列を作ることが可能になり , 現在では て別の文字に置き換える。また , 日本では これを利用したさまざまな暗号化手法が開 戦国時代に換字表を用いた「字変四十八の 発されている。 法」が使われていた。ポーの小説「黄金虫」 ストリーム暗号とプロック暗号 暗号とは簡単にいえば情報を秘匿したり に出てくるのも換字式の暗号だ。 特定の相手に伝達したりするための技法 暗号の利用は近代外交の発達とともに急 “ストリーム暗号”は平文を一定ビット 特別記事最新暗号イヒ技術「 MDSR 」 99 暗号とは
ァイルハンドル FILE に関連付けられてい るファイルのすべての行を要素に持っリス トになります。結局 , grep(/CVS/, <FIL E > ) という式は , FILE に関連付けられてい るファイルの内容をすべて読み込み , パタ ーン " / CVS / " にマッチする行のみからなる リストを作り出すことになります。 print はそのリストを受け取ってすべての要素を 表示します。 grep のこの使い方を理解すると , リスト や配列のなかから目的のパターンを見つけ 出すことができるようになります。たとえ ば , 次の文は # で始まる行のみを表示しま す。 print grep(/A#/, <FILE>) ; 記号 ^ は「文字列の始め」を表す正規表現 のメタ文字です。次の文は , # で始まる行 「以外」を表示します。 print grep(!/A#/, <FILE>) ; 表示するのではなく別の配列に代入して もかまいません。次は , Copyright を含ん でいる ( らしき ) 行を集めて配列@list に代 人しています。 @list = grep (/copyright/i, く FILE>) ; /copyright/ の後ろに付いている "i" は , 大文字小文字の違いを無視する (ignore) と いうオプションです。さらに 2000 年の COPY ⅱ ght を含んでいる行を得るために @ⅱ St2000 = grep ( / 2000 / , @list) ; のようにすることもできるでしよう。次の ようにもできます。 @ⅱ St2000 = grep ( / 2000 / , grep (/copyright/i, <FILE>) ) ; CVS の検索をするときに , 工ラー処理を やらず , とにかく短く書くため close や clos edir もやめてしまうと , List3 のように書 くこともできます。 for は foreach と同じ処 理を行います。 「ところで , 正規表現や "/i" って , どう やって調べるの ? 」もっともな質間です。 私は Perl のマニュアルで調べています。本 になっているものとしては「プログラミン ・ perldoc List カレントディレクトリ中のファイルから CVS を見つけ出す例 2 ( g 「 epl. pl) つ 0 て die "opendir:$!%nn; 1 : opendir(DIR, 2 : foreach $filename (readdir(DIR) ) ( 3 : 4 : 5 : 6 : 7 : if ()f $filename) { open(FILE, $filename) 0 て die "$filename:$!*n" ・ print grep(/cvs/, ぐ I > リ close(FILE); Fig. 2 perldoc で正規表現を調べる C ・ WVORK> perldoc perlre NAME perlre ー Perl regular expressions DESCRIPTION This page describes the syntax Of regular expressions in Perl. FO 「 a description Of hOW tO * use * regula 「 expressions in matching ope 「 ations. plus va 「 ious examples Of the same, see discussion Of 、 m / / ・ , 、 s / / / し q 「が and 、 ? ? ・ in the section on "Regexp Quote-Like Operators"in the perlop manpage. ( 以下略 ) 9 : closedir(DIR); List カレントディレクトリ中のファイルから CVS を見つけ出す例 3 ( g 「 ep2. pl) 1 : opendir(DIR, 2 : for (readdir(DIR) ) { print grep(/cvs/, <FILE>) if $-); 3 : Fig. 3 perldoc で使えるセクション名を調べる C ・ YWORK> perldoc perl ( 中略 ) perl perldelta per15004deIta perlfaq pe 「は0C perldata perlsyn perlop ( 以下略 ) Perl overview (this section) Perl changes since previous version Perl changes in version 5.004 Perl frequently asked questions Perl documentation table Of contents Perl data st 「 uctures Perl syntax Perl ope 「 ators and precedence グ perl 』 ( オライリー・ジャパン ) を読みます。 ほかにも , たとえば正規表現について知り たかったら , コマンドラインから , perldoc perlre と入力すると , 説明が表示されます ( Fig. 2 ) 。 perlre の re というのは正規表現 (Regular Ex pression) の頭文字をとったものです。 perl re 以外に何を調べることができるかは , perldoc perl と人力しましよう。すると , perldoc の後 ろに書くことができるセクション名が表示 されます ( Fig. 3 ) 。ご想像のとおり , perld oc perldoc と入力すれば , perldoc そのもの の説明が読めます。 ・記号を検索するときの注意点 さて , CVS のような英文字のみから成る 単語を検索する場合には問題はないのです perl プログラミングの楽しみ 91
の解答です。 こでは JPerI を使い , また 暗黙のうちに while ( ◇ ) にコでくくってく れるオプション -n を使っています List 12 ではパターン全体を ( ) でくくっ て $ 1 で受けるのではなく , 特殊変数 $ & ( マ ッチしたパターン全体を表現 ) を使ってい ます。つまり , 以下はすべて同等です。 もっとも , このように汎用な重複文字に した場合 , テキスト中の「ここ」や「Ⅵ」な どにも全部マッチしてしまうので , 必ずし もテキストの編集ミスを見つける目的には 向きません。 文書のアウトライン表示 ・記号に応じたインデント 数 $file に指定したファイルをオープンし この応用として , http : や : から始まる 長い文章をテキストエデイタで書いてか て , その各行をスキャンしつつパターンマ 行にマッチさせるには , ら , 全体のアウトラインや目次を作りたい $line /A(http:lftp:)/ ッチを行います。 ときも文字列検索は便利です。大項目 ( 章 ) Fig. 7 は拙著『 Java 言語プログラミングレ という式を使います。いまあなたが持って や小項目 ( 節 ) のタイトルの前に , 自分で ッスン』の文書ファイルのアウトラインを いるテキストファイルにはどういう特徴が 決めた記号を書いておくと簡単に文章の全 表示したものです。 ありますか。あとで検索をかけるときに便 利な記号を埋め込んでおくのもよいです 体像を把握できます。 こで使われているパターンマッチは , ね。たとえば「ここはまだ未完成 , あとで $line = ~ / ^ ◎ / です。この連載のための用の原稿を書くと 再考する」ということを示すために , 「 ? ? ? 」 というものです。これは変数 $ line が◎と きにも , これらの記号を使って見出しにし いう記号で始まっているときに真になる式 や「※」という文字列を入れておけば有益 です。パターンのなかの ^ は「文字列の始 ています。 でしよう。 List 14(outline0. (l) はこのような記号を め」にマッチするメタ文字です。この ^ が C 言語をやっている人は , PerI の elsif の ないと , 行の途中に◎が出てきたときにも 検索し , その記号に応じて字下げ ( インデ つづりに注意してください。 else if でも els ント ) を行うスクリプトです。 こでは変 マッチしてしまいます。 eif でもなく elsif です。 List 記号に応じてインテントを行うスクリプト (outIine0. pl) out ⅱ neO をシンプルにしたもの ( out ⅱ nel . pl) 14 Fig. 7 List 14 の実行例 C:\WORK> perl outline0. ■この章では・ ■例題 1 . HeIIo! を表示する Java プログラム ◎ List(He110. java) ・画面に Hello! と表示して終了するプログラム ・コンバイルして実行してみよう ◎ Fig : He Ⅱ 0. java のコンパイルと実行 ・例題 1 のプログラムを読んでみよう 1 行目 . public class HeIIo ー ◎まるごと覚えよう : クラスの名前は大文字ではじめる習慣になっている 2 行目 . public static void main(String[l a 「 gs){ ◎まること覚えよう : プログラムは main メソッドから開始する ◎ちょっと一言 . アプレットは init メソッドから開始する 3 行目 . System. out. println("HeIlo!"); ◎ちょっと一 System. out. println 4 行目 : } 5 行目 : } ・全体をもう一度つかんでみよう ◎ちょっと一言 : 字下げ ・例題 2 : こんにちは。を表示する Java プログラム ◎ List(Aisatsu. java) 画面にあいさつを表示して終了するプログラム 似下省略 ) ◆◆◆◆◆ 私がよく使うのは , ■・◆◎などの記号 List 15 $file 'yourfile. txt' 1 : 2 : open(FILE, $file) 0 て d 土 3 : while (defined($line = <FILE>)) { print 引土 n } elsif ($line = ~ 6 : 7 : print 引土 n } e lsif ( 引 ine = 8 : print ' 9 : , 引土 n } elsif ($line = ~ ◎ / ) ( 10 : print 11 : , 引 i れ 12 : 13 : } 14 : cIose(FILE); $file = 'yourfile. txt' ・ 1 : 2 : open(FILE, $file) 0 て d 土 3 : while (<FILE>) 4 : print ー ) elsif ( だ・ 6 : print 7 : } 引 sif ( 广◆ / ) { 8 : print 9 : } elsif ( だ◎ / ) { 10 : 11 : print 12 : 13 : } 14 : close(FILE); 96 C MAGAZINE 2000 4
ロの List ハッシュを使う ( out ⅱ ne2. pl) List 同じ動作をする謎のプログラム ( out ⅱ ne3. pl) $file = yourfile. txt' 1 : 2 : 3 : 4 : 5 : 6 : 8 : open(FILE, $file) 0 て die; 9 : while ( く FILE>) { foreach $regex (keys %prefix) { 10 : if ( /$regex/) ( 11 : print $prefix{$regex) , $ 12 : 13 : last ー 14 : 15 : 16 : ) 17 : close(FlLE); $file = yourfile. txt' 1 : 2 : 8prefix = ( 3 : ' ◆ 5 : 6 : . join( ' ) Ⅱ ' , keys(%prefix)) 8 : $pattern = ( ( ' 9 : open(FILE, $file) or die; 10 : while (<FILE>) { print($prefix{$ 十 ), (-) if ( /*$pattern/); 11 : 12 : ) 13 : close(FILE); ハッシュの添え字のことを「キー」と呼び , 短く書けばよい , というものではないです ・シンプルに それに対応する要素を「値」と呼びます。 ね。 List 14(outline0. (l) は正しく動作するプ List 16(outline2. (l) では , ハッシュ %pre 同じ動作をするもっとよいプログラムが ログラムですが , 特殊な変数 $ ーを使うと f ⅸのキーは「 ^ ◆」のような文字列で値は「」 ありましたら , ぜひ結城浩くhyuki@hyuki.c もっとシンプルに書くことができます。 Li のような空白文字の列です。ハッシュ % om > までご連絡ください。 st 15 ( outl ⅲ el. (l) はいちいち $ ⅱ ne に代入せ prefix を初期化するときにはコンマ区切り 次回は「ネットワーキング」 ず , 暗黙のうちに仮定される変数 $ ーを活 の代わりに = > が使え , 対応関係をわかり 用しています。これだとムダな記述がない やすく書くことができます。またこれだと , ぶん , どういうパターンにマッチさせてい インデントを空白ではなく「 > 」にしたり 今回はテキスト処理のいくつかの例を示 るかが読みやすくなりますが , その反面 「→」にしたりするときでも修正が楽になり しました。いかがでしたか。次回は「ネッ Perl に慣れていない人には何をやっている ます。 トワーキングの楽しみ」と題して , Perl で List 16 (outline2. (l) では foreach を使って かわかりにくいと思われる危険性もありま ネットワークプログラミングを行ってみま しよう。どうぞご期待ください。 す。 ハッシュ %prefix のキ—$regex に関するル ープを作り , 現在対象になっている行 $ ー もしも , ご意見やご質問がありましたら , ・ハッシュ ( 連想配列 ) を使う が $ regex にマッチするかどうかを調べて 本誌綴じ込みの編集部へのハガキでお知ら せくだされば幸いです。また , ご遠慮なく List 15(outline1. (l) は慣れてくればわか います。マッチした場合には , $prefixl$r egex Ⅱすなわちその正規表現に対応した 結城浩くhyuki@hyuki.com/ へメールをお送 りやすいプログラムですが , 記号とインデ りください。本連載に関するメールには表 ントの関係をさらにはっきりと表すために インデント ) を現在行の前に置いて表示し 書き換えてみましよう。 perl のハッシュ 題に [MP] という文字を含めてくださると ます。 last というのは C 言語の break に似て ( 連想配列 ) と呼ばれるデータ構造を使いま こでは foreach を中断する 助かります。本連載に関する U 糺は , いるもので , す。 のに使います。 http://www hyuki.com/mp/ List 16 (outline2. (l) は , 「 ^ ◆」のような正 foreach をなくして List 17 (outline3. (l) の です。 規表現と , インデントの対応を % pre ⅱ x と ようなプログラムを書くこともできます。 参考文献等 いうハッシュで表現したものです。 これも不思議なことに List 16(outIine2. pl) ハッシュというデータ構造は , ひとこと と同じ動作をします。 [ 1 ] 『 Effective Perl 』 , Joseph N. HaII , RandaI でいえば「文字列が添え字になっているよ 変数 $ pa れ ern は「 ^ ( ( ◎月 ( ・月 ( ◆月 ( ◎ ) ) 」 L. Schwarts 著 , 吉川邦夫訳 , アスキー うな配列」です。通常の配列は , 数字が添 という正規表現になり , これとマッチさせ 出版局 ると特殊な変数 $ + に「最後にマッチしたカ え字になっており , 配列@array の 0 番目の http://www effectiveperl.com/ 要素は $ array [ 0 ] で表されます。一方ハッ ッコの内容」が格納されます。そのため , [ 2 ] 『詳説正規表現』 , Jeffrey E. F. Friedl 著 , $prefix 月で目的のインデントが取り出 シュは文字列が添え字の役目を果たし , ハ 歌代和正監訳 , オライリー・ジャパン ッシュ %hash の 'key' という文字列に対応 [ 3 ] メールマガジン「 perl クイズ』 せるのです。 こまでやると読みにくく感 する要素は $ hash ド key Ⅱで表されます。 じる人は多くなるでしよう。プログラムは http://www.hyuki.com/pq/ Pe 日プログラミングの楽しみ 97
= 編 の ン グラムの保守や改造の段階で「あれ ? 」とな ターン ) として , のように答えます。ところが「 " ABC " の代 「 NULL 」と「数値のゼロ」と「 ' ¥ 0 ' 」と「””」 るパターンです。筆者の経験では , あるひ わりに空つばの文字列をセットするには ? 」 とりのプログラマが勘違いしている場合 と質問を変えると , 経験不足だったり勉強 の違いがわからない 同じ会社のほかのメンバも , やはり同じよ というのもあります。 不足なプログラマはとたんにポロを出しま うに誤解をし , 一種の「文化」となっている たとえば List 1 のようなプログラムでは , す。 場合があります。 fl ~ f4 のうちどれが正しい処理かわかりま 答えとして意味的に正しいのは「 f4 」だけ [ 原因 ] すか ? で , ほかはみんな間違いです。おそらくプ C 言語の仕様に対する勉強不足 , あるい s 仕 cpy という関数は文字列をセットする ログラムが停止したり , 意味不明な文字列 は K & R を始めとする参考書の説明不足です。 ための関数だということは , 初心者プログ がセットされたり , 暴走するでしよう。簡 [ 対策 / 予防 ] 単にいえば「 NU 比は無効なポインタ」「数 ラマでもよく知っていますし , わりあいに 有名な関数です。だから「 e 対に ABC" と 値のゼロは単なるゼロ」「 ' \ 0 ' は文字列の文 勉強するしか , しようがありません。し 末コード ( つまり単なるゼロ ) 」「 " " は空っ , こういう症状を呈する人たちって , いう文字列をセットするにはどうしたらい たいてい不勉強なんですよね ( 苦笑 ) 。 いか ? 」という質問をしたら , 誰もが List 2 ばな文字列」です。 [ 例外 ] Fig. 1 空っぽの文字列をセット なし。「事情がわかっていて , わざとや る場合はいいじゃないか」と反論したい人 もいるだろうけど , あなた以外のプログラ マが , あなた並みに優秀である保証などな いことをどうかお忘れなく。 [ 備考 ] この変形パターン ( というよりも同種パ 空っぽの文字列をセットするつもり 0 で、日 128 vo れ ( ) ー 鴕て 0 ( も = リ void ぼ 2 い て 0 ( 0 レ ~ void モ 3 ( ) 日 t て 0 ( gT 、 0 ' ) い void f4() て 0 ( ex ”わ アドレス 00000000 00000001 00000002 gText ー NULL 領域→ strcpy(gText, NULL): を実行すると XXXXXXX 1 ◆◆◆◆◆◆・ gText ー 凵 st アドレス NULL 領域のデータ (XX,YY,ZZ など ) を そのままコピーするか , あるいは 例外でプログラムが落とされる gText ー XX YY XXXXXXXO XXXXXXX 1 アドレス 00000000 00000001 00000002 NULL 領域→ XX ZZ strcpy(gText, " ) : を実行すると ◆◆◆◆◆◆・ ◆◆◆◆ LISt strc py の使用例 アドレス きちんと空っぽの文字列がコピーされる void f0( ) て c ( ex らな BC を gText - XXXXXXXO XXXXXXX 1 プログラミングの禁じ手 25 特集 1
真紀俊男の ローテク講座 れば , 常識が非常識に , 非常識が常識に P IntN Buf いとも簡単にすり替わるのが現実だという ことを忘れないでほしい。困るのは , プロ P_Char_Buf は単に 1 文字をバッフアに加 下請け関数 P-IntN_Buf は " 数値→文字列 " グラムを趣味的にやってきて , こういう現 変換の関数である。単純に考えれば , n 進 えるだけでよいので比較的 , 簡単に実現で 実を認めたがらない者たちの反論である。 きる (List 1) 。ただし文字として読めるか 数の各桁の分解になるので , n で割ってい こういう反論は , た おもしろいことに った剰余から 1 文字ずつを取り出せばよい いていダメなプログラムと同様 , 「長文」に どうかの判断が必要になるので isp 日 nt を使 が , 実は上の桁から文字が決定するのでは って判断をする。 isprint のような , ある文 なっていて , どれが焦点なのかハッキリせ なく , 下の桁から決定するプログラムのほ 字の特性を判断するマクロは c . h にいく ずポヤけていて説得力がない。加えて , た うが楽である。ということは逆さまに文字 つか定義されている [ 2 ] 。 いていの人間にとって , 自分にとって当面 が決定するので , ある種のスタック構造 役に立ちそうもないもの , 興味を引かない ( つまり最初に入れたものがあとから出て ものが「長文」だと , それだけでひいてしま くる構造 ) を利用すると , すっきりしたプ うので , せつかく努力して長文を書いたと ログラムになる。というわけで逆さまに文 P-Text-Buf は文字列をコピーするだけ しても最初から読んでもらえないというこ なので , これも簡単に実現できる ( List2 ) 。 字列を決定する下請け関数 P IntN-Buf-Sub とをこの人たちは計算に入れていない。 を別途に用意し , P-IntN Buf は文字列の逆 P_Int Buf と P Hex_Buf 取り出しを行うことにする。 List 5 の P_Int N_Buf は最初に inNum がマイナスであるか どうか判断し , マイナスならリ記号をバ P Int_Buf と P_Hex_Buf は数値を文字列化 ッフアに置く。次に下請け関数 P IntN-Bu するだけである。ただし片方は 10 進数 , 片 f_Sub で逆さの文字列変換を行い , その次 方は 16 進数という違いがある。似たような の行で文字列の逆取り出しをする (List6)0 処理になると思われるので , ともに共通の 下請け関数 P 」 n ー Buf を使うようにコーデ 下請け関数 P_IntN_Buf_Sub では inNum を inRadix( つまり n 進数の n の値 ) でつぎっ イングする (List 3 , 4 ) 。 P_Char_Buf P—Text_Buf 前回の続き 下請け関数として ・ P_Char Buf(1 文字を処理 ) ・ P Text Buf( 文字列を処理 ) ・ P 」 nt ー Buf ( 10 進数整数を処理 ) ・ P ー Hex ー Buf ( 16 進数整数を処理 ) が残っていたので , これらを片付ける。 P 」 nt_Buf lSt P 」 ntN_Buf_Sub static char *P—IntN—Buf-Sub(char *i0Buf,int inNum,int inRadix) static char theN[ ] = ” 0123456789ABCDEF ″ while(inNum >= inRadix) { * 土 oBuf 十十 = theN[inNum 宅 inRadixl; inNum / = inRadix; *ioBuf 十十 = theN[inNum]; return ioBuf; static char *P—Int—Buf(char *ioBuf,int inl ) return P-IntN-Buf(i0Buf,inI,10); P_Hex_Buf static char *P—Hex—Buf(char *ioBuf,int inH) return P—IntN—Buf(ioBuf,inH,16); P 」 ntN_Buf 固定配列を使わない P 」 ntN_Buf-Sub static char *P—IntN-Buf—Sub(char *ioBuf,int inNum,int inRadix) if(inNum く 10 ) { thec = ' 0 ' 十 inNum ・ )else{ theC = 'A' 十 (inNum - 10 *ioBuf 十十 = theC; return ioBuf static char *P—IntN—Buf(char *i0Buf,int inNum,int inRadix) char theBuf[16]; char *thePtr; if(inNum くの { *ioBuf 十十 = inNum * = - thePtr = P—IntN—Buf-Sub(theBuf,inNum,inRadix); while(--theptr > = theBuf) { * 土 OBuf 十十 = *thePtr; return ioBuf; 真紀俊男のローテク講座 135
0 の標準規格の改訂版 Revised [ 血 機能のほとんどは数値計算プログラムで利用するためのものだ。 実際には 1990 年に ISO が C89 を国際標準として承認した直後から おそらくそれは , C89 が承認されたあとのもっとも活動的なグ 始まった。それは国際委員会のメンバが , C89 のなかで適切に ループが Numerical C Extensions Group (NCEG) という組織で 扱われていないと感じた問題点を処理するために計画されたも あったためである。彼らはすぐれた標準を言語の形にまとめる のだ。結局 , Amendment 1 は標準の C ライプラリへの大きな追 ために必要な技術を開発し , 広く公開した。彼らは C99 のため 加という形になり , 言語そのものへの本質的な変更を伴わない の作業に役立つように予定どおりにそれを行ったのだ。 ものになった。 しかしまた , 数値計算のプログラミングは C というプログラ nendmentl では次の三つのヘッダが追加された。 ミング言語にとって重要な , 成長しつつある分野であるという ・く iS0646. h > のも事実である。 Fo 市 an から C へ移行中のプログラマは数値計 算処理においていくつかの機能の欠落を痛切に感じた。 NCEG ある特定の文字について伝統的な ASCII 文字を使わないよう はこれらの機能を補充するためにけんめいに働いた。だから C な実装において , ある演算子をより読みやすくするために設計 99 が数値演算プログラミングにとって大幅に好都合になってい されたほんの一握りのマクロ定義から構成される。たとえば , ても , それはおそらくまったく妥当で常識的な感覚だといえる 縦棒冂」はそのような文字のひとつだ。 だろう。 このヘッダをインクルードすることで演算子「ト」の代わりに C99 を作る際に C89 から除外されたふたつの大きな事柄につい 「 bit-or 」と書くことができる。これらのマクロ名はすべて , 標 てはすでに話した。残りのほとんどは機能の追加である。最低 準 C + + で同じ意味のキーワードとなっているものだ。 1990 年代 限 , 何らかの構造を提供するために こでそれらを五つに分 初頭に存在していた , このヘッダのわずかな使い道はどんどん 類して示そう。 消滅しつつある。 ・ 1995 年までに行われた正式な変更 ・ <wchar.h> ・おもにコードを読みやすくするための , 言語そのものへの 細かい変更 ( 少なくとも私の意見としては ) これは非常に大きいへッダだ。これは C89 内の実質すべての 1 ・新しい言語機能を追加するための比較的大きな変更 バイト文字操作関数と等価なワイド文字版の関数を提供する。 ・既存のライブラリへッダへの細かい変更 すなわち , 「 s 国 en 」がヌル終端の「 ch 記の要素列の長さを調 ・まったく新しいライブラリへッダという形をとった比較的 べるのと同様に , 「 wcslen 」関数はヌル終端の「 wchar ー t 」要素列 大きな変更 の長さを調べるものだ。 おそらくもっとも大がかりな変更は「ワイド入出力ストリー 初期の変更点 ム」の追加であろう。たとえば , 「 p ⅱ n 田関数の振る舞いは「 f p ⅱ n 田とたいへんよく似ているが , ワイド文字の書式文字列を 正規の C の標準規格は , 実は 1990 年代の初期に数回変更され 受け取って , 出力としてワイド文字の列を生成する。ワイド文 た。それらの変更のうちふたつが Technical corrigenda( 技術正 字出力ストリームをファイルに書き込むのに適したバイト列に 誤表 ) の形式をとった。 変換する処理はライプラリに任されている。同様に , ワイド入 それらは最初の C の標準規格への「バグ修正」をまとめたドキ カストリームからデータを読んでそれらを入力でのワイド文字 ュメントだ。 Technical Corrigendum は何らかの新しい機能を取 列に変換する処理もライプラリに任されている。たとえば , す り入れたり , 機能を取り除いたりするためのものではない。単 べてのファイルが UTF ー 8 形式のマルチバイト文字の列で格納さ に C の委員会がそれによって C の標準規格の表現を明確にした れていた場合でも , すっかり UNICODE 文字に置き替えてプロ り , あいまいな点をなくしたりするためためのものだ。重要な グラムできるような実装も可能だ。 問題はすべてこのふたつの Technical Co ⅲ genda だけで処理でき ・ <wctype. h> た。委員会はそれ以降の変更をすべて C99 まで保留することで 合意した。 く c pe. h > で宣言されている 1 バイト文字を類別する関数と等 三つ目の変更は 1995 年の nendment 1 の採択で , これは最初 価なワイド文字版の関数を提供する。く wch . h > とともに の C の標準規格への唯一の改訂だった。 Amendment 1 の作業は れはワイド文字版の関数の一式を提供する。 特別記事 C の標準規格の改訂版 17