Rev.01 1997/11/24 風つかい ■ Icon > Icon散歩道 はじめに 風つかい 目次 Iconは アリゾナ大学の Ralph E Griswold教授のグループによって開発されてい るテキスト処理言語です。 Iconは テキスト解析に 威力を発揮する 豊富なデータ構造と 強力な制御構造を を備えています。 英語の国で開発されている言語ですが、日本語の処理も不自由 しませんし、もっともっと使われてよい言語と思います。 しかし、未だ 日本語の入門書が ありませんので、 AWKについて、ある程度の 知識を お持ちになっている方を 対象として、入門講座を書きました。 ・テキスト解析言語Icon入門講座 ---AWKerのための Icon入門--- ・Icon日記 ---テキスト解析言語Icon入門講座2--- ・Icon雑記帳 ---テキスト解析言語Icon入門講座3--- この Icon散歩道は その続編として、その後 作ったプログラムや 前の 講座で 書き落とした ものを、まとめたものです。 前の 3編の講座と いっしょに ご覧になって Iconを使って頂けると うれしい です。 Iconのプログラムおよびライブラリーは、次の所から 入手できます。 http://www.cs.arizona.edu/icon/index.html この講座は、主に PCVANのPIGのテキストデータ処理会議室にアップロードした ものに加筆・修正を行ったものです。 Iconは PDSですので、この入門講座も同じ扱いとします。(転載・編集自由) (This textbook is in the public domain.) 目次 はじめに (1) 再び構造体 tree表示(1) (2) suspend...do... (3) 再び5クイーン (4) 再び構造体 tree表示(2) (5) 再び構造体 tree表示(3) (6) 再び wild.icn(1) (7) 再び wild.icn(2) (8) 再び dir2tree (9) 再び x2tree(1) (10) 再び x2tree(2) (11) Icon迷い道 (1)system() (12) Icon迷い道 (2)download数 集計 (13) Icon迷い道 (3)CSV:定義ファイルの読込 (14) Icon迷い道 (4)CSV:定義ファイルの解析 (15) Icon迷い道 (5)CSV:拡張子変更(1) (16) Icon迷い道 (6)CSV:拡張子変更(2) (17) Icon迷い道 (7)CSV:CSV2TB (18) Icon迷い道 (8)CSV:TB2CSV (19) ちょっと Icon(1)data整形(1) (20) ちょっと Icon(2)data整形(2) (21) ちょっと Icon(3)data整形(3) (22) ちょっと Icon(4)data整形(4) (23) Icon回り道 (1)重複しないランダムな10個の数(1) (24) Icon回り道 (2)重複しないランダムな10個の数(2) (25) Icon回り道 (3)重複しないランダムな10個の数(3) (26) Icon回り道 (4)Usageが... (27) Icon回り道 (5)a < b が、値を持つ (28) ちょっと Icon(5)Wicon beta8 (29) ちょっと Icon(6)Icon Newsletter No.53 (30) ちょっと Icon(7)Icon Ver.9.3(Windows95/NT) むすび 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: 愛の言霊/サザン・オールスターズ (iconlec4.txt 1997/11/24) ■ Icon > Icon散歩道(1) 再び 構造体tree表示(1)風つかい 目次 Icon雑記帳 に引き続き、Icon迷い道 じゃなかった Icon散歩道 を始めます。 今回こそは、テキスト解析らしい programを作ってみたいと思います。 テキスト解析といっても、 ・簡単な数式解析 と ・簡単なアセンブラ あたり を目標にしています。 と、思っていたのですが、Icon雑記帳を読み返していたら、う〜む。ミスが 見つかりました。 その修正から始めます。 Icon入門講座をやっていまして、アップロードする原稿や programは、その前 に、チェックしている つもりなのですが、大抵 1つや 2つのミスが 含まれて います。 しかし、気がつくのは、大抵、アップロードした後に、自分のメッセージを 読みだしコマンドで、読んだ時です。 もう手遅れのタイミングです。 アップロードするまでは、若干緊張しています。 それが終わった後に、少し ホッとした気分で、自分のメッセージを読み返す訳なのですが、 そういう時に 自分のミスが見つかります。別の自分にならないと、見つからないみたいです。 書いた後に、1日位 寝かせておいて、その後に もう1回チェックすると良い のですが、こらえ性が無くて。 修行が足りないな〜。 と、言うわけで、Icon雑記帳(19)の x2tree03.icnの修正版です。 内容は、コメントに書き込んでありますので、ご覧下さい。 -----^ X2TREE05.ICN ( date:97-05-06 time:01:17 ) -----------<cut here # 構造体の構成を tree状に見せる generator (recursive) # x2tree05.icn Rev.1.2 1997/05/05 windy comment修正 # x2tree05.icn Rev.1.1 1997/05/04 windy # Icon雑記帳(19)の x2tree03.icn のミス(3つも!(汗))を、修正。 # 1) 再帰構造判定のために、serial Noを使ったが、serial Noは、type毎に # 振られるのを知らなかった。serial No登録用 setを type毎に (list, # set,table)分けた。 # 2) 登録 setからの、serial No 削除処理(delete) の位置が、間違っていた。 # suspend...do...の do...の位置ではまずい。更に構造(list等)があって # 自分自身を呼んだ時、その構造の要素の表示処理の度に、戻って来てその # 度に do...が実行される。よって、期待以外の時に serial Noが削除され # てしまう。 素直に suspendの後ろの行に置く。 # 3) 初期化処理を x2treeで initial {...}でやっていた。 x2t()を 使う # program内で 別の構造体 tree表示のために、再び x2t()を呼んだ 時に # 実行されなくて状態が残る。 initial {...}ではなくて、x2t()からの # フラグで 初期化指示する方式に変えた。 # This file is in the public domain. link jimage procedure x2t(x) # generator # topの処理 suspend "<" || type(x) || " " || string(serial(x)) || ">" #↑listの serial No suspend " " || x2tree(x,"") #↑初期化フラグ end procedure x2tree(x,init) # generator # show the tree structure of x static T # serial No 登録用 set登録用 table static宣言を して # おかないと、再帰したときに、未定義 errorとなる。 if \init then { # Rev.1.2 T := table() T["list"] := set() # ここは、table(set())とすると、全て同じ setが T["set"] := set() # 割り当てられてしまうので、個別に初期化する。 T["table"] := set() if (t := type(x)) == ("list" | "set" | "table") then insert(T[t],serial(x)) # serial Noを T[type(x)]に登録 } n := *x # 枝の末端検出用カウンタ every xx := !x do { # 構造体の要素を1つ づつ取り出す n -:= 1 case t := type(xx) of { # 構造体のタイプにより、 "string" : suspend "+ " || left(t,7) || " " || jimage(xx) #↓list,set,tableなら、typeを書出して、その中身をまた解析する。 "list" | "set" | "table" : { #↓再帰構造で なければ。(T[type(xx)] に既に登録済みなら再帰構造) if not member(T[t],m := serial(xx)) then { insert(T[t],m) # serial Noを T[type(xx)]へ登録 suspend "+ <" || t || " " || string(m) || ">" suspend (if n > 0 then "| " else " ") || x2tree(xx) #↑枝の途中 #↑枝の末端 # 再帰↑ delete(T[t],m) #←serial No 登録を削除 } else { # 再帰構造 ならば、書き出すとキリが無いので打止め return "+ <" || t || " " || string(m) || "> (Recursion)" } } #↓その他なら、typeと値を書き出す。 default : suspend "+ " || left(t,7) || " " || image(xx) } } end # test driver procedure main() #listの test L1 := ["A","B"] L2 := ["C","D"] L3 := ["E","F"] put(L1,L2) put(L2,L3) put(L1,L3) # 別枝 test put(L3,L1) # listの再帰 every write(x2t(L1) \20) # \20は、テストをドジッた時に、20個で止めるため。 write() #tableの test T := table() T["A"] := "G" T["C"] := L2[1] T["E"] := L3 T[L1] := L1[1] put(L3,T) # tableの再帰 every write(x2t(T) \20) write() #setの test L4 := ["H","I"] S1 := set(["L","M"]) S := set(["J","K",L4]) insert(S,S1) insert(S1,S) # setの再帰 every write(x2t(S) \20) end -----$ X2TREE05.ICN ( lines:98 words:380 ) -----------------<cut here ( comment修正のため、差し替え) linkしている jimage.icnは、Icon雑記帳に含まれています。 この jimage.icnは 更に Icon日記に含まれる sjis4.icnを linkしています。 結果は、次のようになります。 テストケースを増やしましたが、まだ漏れ が、あるかもしれません。尚、構造体の recordへの配慮が 抜けていますが、 これは、私が使わないもので、省いてあります。 それは、仕様です。(笑) -----^ X2TREE05 ( date:97-05-04 time:20:59 ) ---------------<cut here <list 1> + string "A" + string "B" + <list 2> | + string "C" | + string "D" | + <list 3> | + string "E" | + string "F" | + <list 1> (Recursion) + <list 3> + string "E" + string "F" + <list 1> (Recursion) <table 2> + string "C" + <list 3> | + string "E" | + string "F" | + <list 1> | | + string "A" | | + string "B" | | + <list 2> | | | + string "C" | | | + string "D" | | | + <list 3> (Recursion) | | + <list 3> (Recursion) | + <table 2> (Recursion) + string "A" + string "G" <set 8> + string "K" + <set 7> | + string "M" | + string "L" | + <set 8> (Recursion) + <list 38> | + string "H" | + string "I" + string "J" -----$ X2TREE05 ( lines:42 words:155 ) ---------------------<cut here 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: Goodbye Day /来生たかお (icon_301.txt 1997/05/05 PCVAN PIG) ■ Icon > Icon散歩道(2) suspend...do... 風つかい 目次 前回、Icon雑記帳(19)で取り上げた x2tree03.icnのミスを 修正しました が、私は、どうも suspend...do...の構文が、理解できていない と思います。 そこで、動作確認の実験 programを作ってみました。 こういう構成の programです。 main() test_a() test_b() ------------------ ------------------ ------------------ | main() | | | | | | every test_a() <--- suspend...test_b() <--- suspend... | | | | do... | | do... | ----------------- ------------------ ------------------ 実験 programです。 -----^ DO_01.ICN ( date:97-05-04 time:23:28 ) --------------<cut here # suspend...do...の動作の確認1 # do_01.icn 1997/05/04 windy # This file is in the public domain. # main()は test_aの出力を書き出すだけ procedure main() write("suspend...do.. の実行順序の確認実験1") write() write("メイン先頭") every s := test_a("MM") do write("メイン出力 ",s) write("メイン末尾") end # teat_aは test_b(s)の先頭に、文字列 "AA "を加えるだけ procedure test_a(s) write(" A先頭") suspend "AA " || test_b(s) do write(" A do") write(" A末尾") end # 2出力の generator # 1つは sに文字列 "B1 "を加え、もう1つは sに文字列 "B2 "を加える procedure test_b(s) write(" B先頭") suspend "B1 " || s do write(" B1 do") write(" B中間") suspend "B2 " || s do write(" B2 do") write(" B末尾") end -----$ DO_01.ICN ( lines:29 words:91 ) ---------------------<cut here 動作結果は、次のように なります。 test_a() ,test_b() の do...の部分 の 実行タイミングと 回数に着目して下さい。 -----^ DO_01 ( date:97-05-04 time:23:28 ) ------------------<cut here suspend...do.. の実行順序の確認実験1 メイン先頭 A先頭 B先頭 メイン出力 AA B1 MM A do B1 do B中間 メイン出力 AA B2 MM A do B2 do B末尾 A末尾 メイン末尾 -----$ DO_01 ( lines:15 words:25 ) -------------------------<cut here 私は、動作タイミングを 全く誤解していました。 つい、generatorではない procedureを 呼んだ時と 同じ順番と 思っていました。 実際に 実験してみるもんですね。 ついでに、test_a()で 2つ suspendする 場合の 実験 programも あげておき ます。 -----^ DO_02.ICN ( date:97-05-05 time:22:43 ) --------------<cut here # suspend...do...の動作の確認2 # do_02.icn Rev.1.2 1997/05/04 windy comment修正 # do_02.icn Rev.1.1 1997/05/05 windy # This file is in the public domain. # main()は test_aの出力を書き出すだけ procedure main() write("suspend...do.. の実行順序の確認実験2") write() write("メイン先頭") every s := test_a("MM") do write("メイン出力 ",s) write("メイン末尾") end # teat_aは test_b(s)の先頭に、文字列 "A1 "か "A2 "を 加えるだけ procedure test_a(s) write(" A先頭") suspend "A1 " || test_b(s) do write(" A1 do") write(" A中間") suspend "A2 " || test_b(s) do write(" A2 do") write(" A末尾") end # 2出力の generator # 1つは sに文字列 "B1 "を加え、もう1つは sに文字列 "B2 "を加える procedure test_b(s) write(" B先頭") suspend "B1 " || s do write(" B1 do") write(" B中間") suspend "B2 " || s do write(" B2 do") write(" B末尾") end -----$ DO_02.ICN ( lines:32 words:112 ) --------------------<cut here (コメント修正のため、差し替え) 結果です。 -----^ DO_02 ( date:97-05-04 time:23:29 ) ------------------<cut here suspend...do.. の実行順序の確認実験2 メイン先頭 A先頭 B先頭 メイン出力 A1 B1 MM A1 do B1 do B中間 メイン出力 A1 B2 MM A1 do B2 do B末尾 A中間 B先頭 メイン出力 A2 B1 MM A2 do B1 do B中間 メイン出力 A2 B2 MM A2 do B2 do B末尾 A末尾 メイン末尾 -----$ DO_02 ( lines:25 words:45 ) -------------------------<cut here イケイケ評価(Goal-directed evaluation) を 行うために test_a(), test_b() の 全組み合わせ を試している のが 分かります。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: いとおしいグレイ/篠原美也子 (icon_302.txt 1997/05/05 PCVAN PIG) ■ Icon > Icon散歩道(3) 再び 5クイーン 風つかい 目次 前回 suspend...do...の構文 の動作確認を 行いましたが、他の programでも 誤解して 使っているところが 無いかと、探しました。 Icon日記の 5-Queensの programでも、Queenの置き直しのところで、使ってい ます。 ここは、特に do...を使う必要は、ありませんね。 -----^ 5QUEEN1D.ICN ( date:97-05-04 time:20:02 ) -----------<cut here # 5-Queensの解の書き出し # 5x5のチェス盤に 5個の Queenを互い取られない位置に置く。 # 5queen1d.icn Rev.1.1 1997/05/04 windy # This file is in the public domain. # Icon教典(The Icon Programming Language)の 8-Queens program # に、手を加えたもの。 # 動作は、Icon日記(24)〜(26)を参照して下さい。 # Queenの 置き直しは、suspend ... do ...の do...を 使わなくて # も良いことに 気付いて 修正したもの。 # # 行・列の番号 右上がり対角線 右下がり対角線 # 列→(column) 番号→ ←番号 # 1 2 3 4 5 1 2 3 4 5 5 4 3 2 1 # 行 1Q・・・・ Q//// 6 6 Q\\\\ # ↓ 2・・Q・・ //Q// 7 7 \\Q\\ # (row) 3・・・・Q ////Q 8 8 \\\\Q # 4・Q・・・ /Q/// 9 9 \Q\\\ # 5・・・Q・ ///Q/ \\\Q\ # # 上の図のように置き終わった状態では、 # 行 右上がり対角線 右下がり対角線 # row 12345 up 123456789 down 123456789 # col "13524" col "1..32.54." col "..53142.." # procedure main() # Queenが1行から5行まで全て置けたら、列位置を順に書き出す。 # q(1),...,q(5)が全て成功しなければ writeの引数は成功しない。 every write(q(1)," ",q(2)," ",q(3)," ",q(4)," ",q(5)) #↑Queenを順に1行ずつ置いていって、全部置けたら成功 # 置けないときは、順に1行ずつ戻って別の置き方を試す。 # とにかく、【イケイケ】で、答えが出るまで試す。 # 答えのある限り試す。 write() end procedure q(r) # r番目の行の Queenを、1〜5列に置いて試すための generator # 戻り値は、置けた列の No suspend place(r,1 to 5) # ↑ 1列〜5列迄試す。 end procedure place(r,c) # Queenを r行 c列に置いてみる。置けないと失敗。置けると列 Noを返す。 static up,down,col # 既に置かれた Queenを記憶。 # 列位置と影響する対角線2方向の位置を記憶する。 initial{ # 初期値( Queenを何処にも置いていない状態) up := repl(".",9) # 右上がり対角線管理 down := repl(".",9) # 右下がり対角線管理 col := repl(".",5) # 列番号管理 } if col[c] == up[r + c -1] == down[5 - c + r] == "." # ↑r行 c列に置けるかの check(全部 "."ならあいている。) then { suspend col[c] := up[r + c -1] := down[5 - c + r] := c # ↑ c番目の列に Queenを置く。 # 置いた列・右上がり対角線・右下がり対角線に cを代入している。 # 置いたことを示すだけなら "."以外の文字ならなんでも良いが、 # 戻り値を列番号にするために cを代入。 # 続行時の処理 col[c] := up[r + c -1] := down[5 - c + r] := "." # ↑ c番目から Queenを取り去る。 # 続行は、次の行の Queenが置けなかった時、または全部の Queenが # 置けて、別の置き方を 試す時に起こる。 } end -----$ 5QUEEN1D.ICN ( lines:69 words:272 ) -----------------<cut here 結果です。 修正前と、同じ結果になります。 -----^ 5QUEEN1D ( date:97-05-04 time:20:02 ) ---------------<cut here 1 3 5 2 4 1 4 2 5 3 2 4 1 3 5 2 5 3 1 4 3 1 4 2 5 3 5 2 4 1 4 1 3 5 2 4 2 5 3 1 5 2 4 1 3 5 3 1 4 2 -----$ 5QUEEN1D ( lines:11 words:50 ) ----------------------<cut here 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: いとおしいグレイ/篠原美也子 (icon_303.txt 1997/05/05 PCVAN PIG) ■ Icon > Icon散歩道(4) 再び 構造体tree表示(2)風つかい 目次 Icon散歩道(1)で、x2tree03.icnの ミス修正版を 説明しましたが、どうし て ミスに気がついたか というと、実は、Version Upをしようと、思いまして、 テスト・ケースを増やしてみて、気がつきました。 今回は、その Version Upです。 Iconの tableは、AWKでいう 連想配列です。 tableは、key と valueを持っています。 前の programでは、valueしか表示し ません。 x2treeは、programの動作確認 のための toolとして作りましたが、 tableでは、value表示だけでなく、key表示も欲しい! ということで、key表示を追加します。 尚、Iconでは、keyにも 構造体(list,set,table)が、使えます。 しかし、keyに 構造体を使っても、そちらは tree表示はしません。 (そんな 複雑 tree表示は、思いつかないよ〜。) -----^ X2TREE06.ICN ( date:97-05-05 time:03:26 ) -----------<cut here # 構造体の構成を tree状に見せる generator (recursive) # x2tree06.icn Rev.1.1 1997/05/05 windy # x2tree05.icn にて、tableの場合は key表示を追加したもの。 # This file is in the public domain. link jimage procedure x2t(x) # generator # topの処理 suspend "<" || type(x) || " " || string(serial(x)) || ">" #↑listの serial No suspend " " || x2tree(x,"") #↑初期化フラグ end procedure x2tree(x,init) # generator # show the tree structure of x static T # serial No 登録用 set登録用 table static宣言を して # おかないと、再帰したときに、未定義 errorとなる。 if \init then { # 初期化を initialでやると、同じ program内で別の # 構造体 tree表示のために、再び x2tを 呼んだ時に # 実行されなくて状態が残るので、フラグで初期化指示 T := table() T["list"] := set() # ここは、table(set())とすると、全て同じ setが T["set"] := set() # 割り当てられてしまうので、個別に初期化する。 T["table"] := set() if (t := type(x)) == ("list" | "set" | "table") then insert(T[t],serial(x)) # serial Noを T[type(x)]に登録 } n := *x # 枝の末端検出用カウンタ if (tt := type(x)) ~== "table" then { # not table every xx := !x do { # 構造体の要素を1つ づつ取り出す n -:= 1 t := type(xx) val_disp := if t == ("list" | "set" | "table") then "+ <" || t || " " || string(m := serial(xx)) || ">" else "+ " || left(t,7) || jimage(xx) case t of { # 構造体のタイプにより、 "string" : suspend val_disp #↓list,set,tableなら、typeを書出して、その中身をまた解析する。 "list" | "set" | "table" : { #↓再帰構造で なければ。(T[type(xx)] に既に登録済みなら再帰構造) if not member(T[t],m) then { insert(T[t],m) # serial Noを T[type(xx)]へ登録 suspend val_disp suspend (if n > 0 then "| " else " ") || x2tree(xx) #↑枝の途中 #↑枝の末端 # 再帰↑ delete(T[t],m) #←serial No 登録を削除 } else { # 再帰構造 ならば、書き出すとキリが無いので打止め return val_disp || " (Recursion)" } } #↓その他なら、typeと値を書き出す。 default : suspend val_disp } } } else { # table every xkey := key(x) do { # tableの keyを1つ づつ取り出す n -:= 1 tk := type(xkey) xx := x[xkey] t := type(xx) val_disp := if t == ("list" | "set" | "table") then "+ <" || t || " " || string(m := serial(xx)) || ">" else "+ " || left(t,7) || jimage(xx) key_disp := if tk == ("list" | "set" | "table") then " <- <" || tk || " " || string(serial(xkey)) || ">" else " <- " || left(tk,7) || jimage(xkey) case t of { # 構造体のタイプにより、 "string" : suspend val_disp || key_disp #↓list,set,tableなら、typeを書出して、その中身をまた解析する。 "list" | "set" | "table" : { #↓再帰構造で なければ。(T[type(xx)] に既に登録済みなら再帰構造) if not member(T[t],m) then { insert(T[t],m) # serial Noを T[type(xx)]へ登録 suspend val_disp || key_disp suspend (if n > 0 then "| " else " ") || x2tree(xx) #↑枝の途中 #↑枝の末端 # 再帰↑ delete(T[t],m) #←serial No 登録を削除 } else { # 再帰構造 ならば、書き出すとキリが無いので打止め return val_disp || key_disp || " (Recursion)" } } #↓その他なら、typeと値を書き出す。 default : suspend val_disp || key_disp } } } end # test driver procedure main() #listの test L1 := ["A","B"] L2 := ["C","D"] L3 := ["E","F"] put(L1,L2) put(L2,L3) put(L1,L3) # 別枝 test put(L3,L1) # listの再帰 every write(x2t(L1) \20) # \20は、テストをドジッた時に、20個で止めるため。 write() #tableの test T := table() T["A"] := "G" T["C"] := L2[1] T["E"] := L3 T[L1] := L1[1] put(L3,T) # tableの再帰 every write(x2t(T) \20) write() #setの test L4 := ["H","I"] S1 := set(["L","M"]) S := set(["J","K",L4]) insert(S,S1) insert(S1,S) # setの再帰 every write(x2t(S) \20) end -----$ X2TREE06.ICN ( lines:133 words:507 ) ----------------<cut here 行数制限が ありますので、結果は次回に。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: いとおしいグレイ/篠原美也子 (icon_304.txt 1997/05/05 PCVAN PIG) ■ Icon > Icon散歩道(5) 再び 構造体tree表示(3)風つかい 目次 x2treeに、tableの key表示を追加した programの動作結果です。 tableの部分が、若干、混みあった表示になりますが、test toolですので、 まあ、いんじゃない。 と、納得しましょう。 -----^ X2TREE06 ( date:97-05-05 time:03:26 ) ---------------<cut here <list 1> + string "A" + string "B" + <list 2> | + string "C" | + string "D" | + <list 3> | + string "E" | + string "F" | + <list 1> (Recursion) + <list 3> + string "E" + string "F" + <list 1> (Recursion) <table 2> + string "C" <- string "C" + <list 3> <- string "E" | + string "E" | + string "F" | + <list 1> | | + string "A" | | + string "B" | | + <list 2> | | | + string "C" | | | + string "D" | | | + <list 3> (Recursion) | | + <list 3> (Recursion) | + <table 2> (Recursion) + string "A" <- <list 1> + string "G" <- string "A" <set 8> + string "K" + <list 44> | + string "H" | + string "I" + <set 7> | + string "M" | + string "L" | + <set 8> (Recursion) + string "J" -----$ X2TREE06 ( lines:42 words:167 ) ---------------------<cut here keyに、構造体を 使った場合でも keyの type表示の下に、treeを作れば良い ような気がします。 とりあえず、気がつかなかったことにしよう。(笑) (tableの要素に また tableが出てくるケースなんか、ツライだろうし。) 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: そのままの君でいて/岡本真夜 (icon_305.txt 1997/05/05 PCVAN PIG) ■ Icon > Icon散歩道(6) 再び wild.icn(1) 風つかい 目次 近ごろ、"再び" というタイトルが多いですね〜。う〜む。以前の講座のミス が、みつかるのが多いな〜。 ということで、今回は Icon入門講座(16)で 作った wild.icnの修正版で す。 Iconの Program 例えば、abcd.icnを compileして、動かした結果のfile名を 以前は、abcd.txtとしていたんですが、txtの拡張子をつけるのも面倒というこ とで、近ごろは、ただ abcdとしています。 これを、YAB形式にしようと、IYAB(Icon入門講座(18))を動かすとどうも 結果がオカシくなります。 調べてみますと、IYABは、拡張子無しの file名を指定するとおかしくなりま す。 更に調べると、iyab.icnは、wild.icnを linkしていますが、wild.icnで既に オカシイ。 あれれ、wild.icnは、拡張子なしの file名の手当をしていたはず だか??? と、思って、良くみると、あれま、ミスコーディング をしていま す。 if not upto('.',line) then line ||= "." というミスをやらかしていました。 つう、ことで、修正版です。 -----^ WILD.ICN ( date:97-05-10 time:00:42 ) ---------------<cut here # wild cards file指定 の fileの情報を "dir" を発行して 調べて # listにして 返す。 # response fileも指定可。(@file_list) # Icon入門講座(16)を参照して下さい。 # This file is in the public domain. # # wild.icn Ver.1.5 1997/05/10 windy comment修正(引数は list) # wild.icn Ver.1.4 1997/05/05 windy 拡張子無し手当修正 "||=" → "||:=" # wild.icn Ver.1.1 1996/10/26 windy # # Usage: wild([file(s) or @file_list_file]) # sortf(wild([file(s) or @file_list]),1) file名で sortする時 # 注意:引き数は listなので、間違えないこと。 # value: [i][1] full path付き file名、[i][2] file size # [i][3] 日付、[i][4] 時刻 i : 1 〜 fileの数 # 該当 fileが無ければ失敗(fail) link dir2lst # ← Icon入門講座 に含まれています。 procedure wild(args) ################### # file指定 command行処理 ################### tmp := "$$$tmp.$$$" # temporary file名設定 if s := getenv("TMP") then tmp := s || "\\" || tmp #↑環境変数に temporary directoryが設定してあれば # file名 の前 に追加 fn_list := [] # file名等 格納 list # command lineの file指定 をもとに、"dir" commandを発行し、tmpへ。 if *args = 0 then fail # file指定なし else { every arg := !args do { # command line引数 listから順に取り出し。 case arg[1] of { # caseを使ってみたかったのだ。 "@" : { # response file指定 dir := open(arg[2:0]) | stop("cannot open " || arg[2:0]) while line := read(dir) do { if not upto('.',line) then line ||:= "." # Rev.1.4 #↑ 拡張子が無い時には、 "."を追加。 system("dir " || line || " >>" || tmp) # "dir"発行 } close(dir) } default : { # file指定 if not upto('.',arg) then arg ||:= "." # Rev.1.4 system("dir " || arg || " >>" || tmp) # "dir"発行 } } # end of case } # end of every } # end of else dir := open(tmp) | stop("cannot open " || tmp) # fileオープン # "dir" の結果格納 fileから、file指定部分を 抜き出して listへ。 while line := read(dir) do # tmp fileから1行づつ読込。 put(fn_list,dir2lst(line)) # file情報を抜き出して、 # listへ格納 close(dir) remove(tmp) # 証拠隠滅 #################### # command解析終了 #################### if *fn_list = 0 then fail # 該当 file無し else return fn_list end -----$ WILD.ICN ( lines:65 words:298 ) ---------------------<cut here test programでも、test caseを 落としていますので、追加しました。 -----^ WILD~.ICN ( date:97-05-08 time:23:07 ) --------------<cut here # a test driver and a stub for wild.icn # Usage: wild~ > wild.rst # Rev.1.2 1997/05/05 windy 拡張子無しのテストケース追加 # Rev.1.1 1996/12/01 windy # This file is in the public domain. link wild, show_l procedure main() write("test for wild.icn\n") # "abc" という名前のファイルは存在しないこと。 write((L := ["abc"])[1]) show_wl(wild(L)) | write(L[1],"は見つからない。\n") # wild card write((L := ["*.*"])[1]) show_wl(wild(L)) write((L := ["*.icn"])[1]) show_wl(wild(L)) write((L := ["wi*.*"])[1]) show_wl(wild(L)) # response file write((L := ["@WILD_FL.DAT"])[1]) show_wl(wild(L)) # 複数指定 every writes(" ",!(L := ["*.icn","*.dat"])) ; write() show_wl(wild(L)) # "AAA", "AAA.TXT" の 2つの fileを用意しておくこと。 every writes(" ",!(L := ["AAA"])) ; write() # 追加 Rev.1.2 show_wl(wild(L)) write((L := ["wild~.*"])[1]) show_wl(wild(L)) end -----$ WILD~.ICN ( lines:39 words:102 ) --------------------<cut here というだけでは、シャクなので、次回は、wildの応用 programを。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: 河よりも長くゆるやかに/篠原美也子 (icon_306.txt 1997/05/10 PCVAN PIG) ■ Icon > Icon散歩道(7) 再び wild.icn(2) 風つかい 目次 PIG広場の方で、fileの名前と拡張子を 入れ換える 話題が 出ています。 そのネタをいただいて、Iconでやったらということで、programを 作ってみま した。 Iconには、fileの rename関数があります。 wild.icnで、該当 fileを 探して rename関数で、renameするという programです。 この programでは、log.* ファイルの拡張子とファイル名を入れ換え、その後 もう1度、入れ換えて、元に戻しています。 -----^ REN01.ICN ( date:97-05-10 time:00:37 ) --------------<cut here # log.* fileの file名と拡張子 の交換 # ren01.icn 1997/05/10 windy # This file is in the public domain. link wild, split, top # ←Icon入門講座にある procedure procedure main() L := wild(["log.*"]) # log.* の file list入手 name_ex(L) # file名と 拡張子名を 交換 L := wild(["*.log"]) # *.log の file list入手 name_ex(L) # file名と 拡張子名を 再び交換 # (元に戻す。) end # file名と拡張子 の交換 procedure name_ex(L) if /L then return # 該当 file無し write("\nfile名<->拡張子") every LL := !L do { s := top_cut("\\",LL[1]) # 現file名から directory部を 削除 # ↑file名 LLL := split(s,".") # file名を "."で分割して listへ write(s," -> ",s2 := LLL[2] || "." || LLL[1]) # 動作モニター #↑拡張子 ↑file名 rename(s,s2) # rename } return end -----$ REN01.ICN ( lines:28 words:109 ) --------------------<cut here この programを 作っている最中に 動かな〜い。!? と 悩んでいましたが wild.icnの引数は listなのに、stringと勘違いしていました。 今後は、間違えないようにと、wild.icnに、commentを追加しました。 動作モニター用出力を fileに 落としたものです。 -----^ REN01 ( date:97-05-10 time:00:40 ) ------------------<cut here file名<->拡張子 LOG.97 -> 97.LOG LOG.95 -> 95.LOG LOG.96 -> 96.LOG file名<->拡張子 95.LOG -> LOG.95 96.LOG -> LOG.96 97.LOG -> LOG.97 -----$ REN01 ( lines:10 words:20 ) -------------------------<cut here test用に用意した、ファイルです。 -----^ LOG.95 ( date:97-05-10 time:00:39 ) -----------------<cut here 95 -----$ LOG.95 ( lines:1 words:1 ) --------------------------<cut here -----^ LOG.96 ( date:97-05-10 time:00:39 ) -----------------<cut here 96 -----$ LOG.96 ( lines:1 words:1 ) --------------------------<cut here -----^ LOG.97 ( date:97-05-10 time:00:39 ) -----------------<cut here 97 -----$ LOG.97 ( lines:1 words:1 ) --------------------------<cut here まだ、"再び" の話題は 続きます。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: 河よりも長くゆるやかに/篠原美也子 (icon_307.txt 1997/05/10 PCVAN PIG) ■ Icon > Icon散歩道(8) 再び dir2tree 風つかい 目次 ミスが多い と言いつつ、相変わらず、やっていますね〜。 再び wild.icn(7)-> 再び wild.icn(2) ですね。 (このテキストでは直っています。) ところで、Icon入門講座シリーズを、アリゾナ大学の Icon-WEBに 置いて頂く ように、Icon入門講座 (ICON_LEC.LZH)と Icon日記 (ICONLEC2.LZH) の fileを Icon Projectに、送ってお願いしていたんですが、置いて頂けました。場所は、 ftp://ftp.cs.arizona.edu/icon/contrib/Japanese/ です。 /icon/contrib/ は 寄贈 program (contribution)の directoryです。 ここに、Japaneseという directoryを作っていただきました。 英文なら E-mailか FTPで、送ればいいんですが、日本語の SHIFT-JISの file ですので、printしたものと、FDを送ってみました。 とても、全文を英訳する力は、ありませんので、 「 printed materialの programの部分で 内容は 想像して下さい。」 と お願いした文章を、四苦八苦して 書きました。(汗) 近ごろ、カタカナ部分を なるべく 英語で書いていますが それは Icon Project で、内容を 想像しやすいように ということで、やっています。(あはは) 内容は、こちらにアップしたものと 殆ど同じです。(その後 みつかった文章 や綴り(特に英語)の誤記を多少 修正しています。program自体は同じです。) さて、今回は、Icon雑記帳(20)〜(22)で、やりました dir2tree の修 正です。 dir2treeは、私のHDDの Icon関係 directoryの中の sub-directoryで test しました。 で 先日、Icon雑記帳の fileを、Icon-Projectの送ろうと そのFD の directory treeを、表示しようとしましたら、programが、コケました。 root directoryじゃ、動かなひ〜。 dir /s の command を 実行したときに、 ・root directoryでは A:\とか directory名称の後ろに、\ が、つきますが ・sub-directoryでは、つきません。 \ がつく caseの手当を忘れていました。つうことで、その点を修正しました。 -----^ D2TREE.ICN ( date:97-05-10 time:00:48 ) -------------<cut here # ディレクトリーを tree表示する。 # d2tree.icn Ver.1.1 1997/05/10 windy # This file is in the public domain. # Icon雑記帳(20)〜(22)の dir2tree.icn の root directoryの対応 # 漏れを修正した。(root directoryだけは directory名称に "\\"が付く。) # Usage : d2tree directory_name # "dir /s" を発行して 得た ディレクトリー情報を tree 表示する。 link x2tree07 # test用 procedure main(args) ####################### # directory情報を得る。 ####################### dir_name := if *args > 0 then args[1] else "" tmp := "$$$tmp.$$$" # テンポラリファイル名設定 # ↓環境変数に、テンポラリーディレクトリ名が、設定してあればファイル名 # の前に追加 if s := getenv("TMP") then tmp := s || "\\" || tmp # コマンドラインの ディレクトリー名指定 をもとに、"dir /s" コマンド を # 発行して tmpへ出力 system("dir /s " || dir_name || " >" || tmp) # directory data sample ↓こんなデータが tmpに格納されます。 #1 16 #ディレクトリは D:\ICON\LEC24\TEST_A # #. <DIR> 97-04-29 21:51 . #.. <DIR> 97-04-29 21:51 .. #TEST_B <DIR> 97-04-29 21:52 TEST_B #BBB TXT 10 97-04-29 21:56 BBB.TXT #TEST_CCC TXT 15 97-04-29 21:57 TEST_CCC.TXT #TEST_C <DIR> 97-04-29 21:55 TEST_C #AAA 6 97-04-29 21:56 AAA # 3 個 31 バイトのファイルがあります # #一覧のファイル総数: ###################### # dir /s (dir_name)結果から、directory毎の情報を listへ 登録 ###################### dir := open(tmp) | stop("cannot open " || tmp) # tmpファイルオープン L_dir := [] # directory情報登録用 list T_dir := table() # sub-directory list参照 table while line := read(dir) do { # directory情報を directory毎に、一旦 list(LL)にまとめて、登録する。 line ? { #↓listにまとめた directory情報を登録 if find("個") then put(\T_dir[c_dir] | L_dir,LL) #↑tableに c_dirが存在すれば if match(" ") then next # ごみ行を無視 if match("一") then break # "一覧の..."が来たら終わり L := p_split() # lineを " "で分割→[1]:開始位置 # [2]:要素 #↓lineの1番目の要素 case L[1][2] of { "ディレクトリは" : { LL := [] # directory data buffer # ↓lineの2番目の要素の開始位置 if line[-1] == "\\" then c_dir := line[L[2][1] : -1] # root対応 else c_dir := line[L[2][1] : 0] # put(LL,[c_dir]) #↑listにして LLに追加 } "." : next # 無視 ".." : put(LL[1],line) # その directory自身の情報。 # トップの directory以外では必要 # ないが、全てにつき格納 default : { if find("<DIR>") # sub-directoryだったら then { put(LL,LLL := [line]) # 内容を bufferに追加 insert(T_dir,c_dir || "\\" || L[1][2] ,LLL) # ↑sub-directory名称を keyにして tableへ登録 } else put(LL,line) # 通常 fileならそのまま追加 } } # end of case } # end of line ? } # end of while close(dir) remove(tmp) # delete tmp ####################### # directory情報の表示 ####################### # every write(x2t(L_dir) \25) # list 内容確認用表示 # every write(x2t(T_dir) \25) # table内容確認用表示 # stop() every write(d2t(L_dir)) end ######################## # directory tree表示 ######################## procedure d2t(L) # top directoryの名前/time_stamp処理 L1 := get(L) # Lには1個しか要素が無い。それを取り出す。 L2 := get(L1) # そのまた top (directory_name,time_stamp)を取り出す。 dir_top := L2[2][14:-3] | "\\ <DIR>" # top directoryの名前と time stamp ↓root directory対応 suspend L2[1] || dir_top suspend " " || d2tree(L1) # tree化処理 # ↑tree書出し初期位置 end procedure d2tree(L) # directoryの処理 # show the tree structure of directory n := *L # Lの size(末尾要素検出用) every LL := !L do { # listの要素を1つづつ取り出す n -:= 1 # 要素カウンタ−1 case t := type(LL) of { # 要素の typeにより、 "string" : suspend "+ " || LL # file "list" : { # sub-directory suspend "+ " || get(LL) # sub-directory自体表示 LLL := get(LL) # sub-directoryの中身を取り出し get(LLL) # 先頭要素を読み飛ばし #↓最後の要素でないなら suspend (if n > 0 then "| " else " ") || d2tree(LLL) } default : stop("error") } } end ######################## # stringを cを区切りにして分割して、開始位置と要素を返す。 ######################## # 動作は、Icon入門講座(7) Iconの特徴(5)スキャンを参考にして下さい。 procedure p_split(line,c) /c := ' \t' # default /line := &subject # default list := [] # 戻り値用 list line ? { while tab(ps := upto(~c)) do put(list,[ps,tab(pe := many(~c))]) } return list end -----$ D2TREE.ICN ( lines:141 words:544 ) ------------------<cut here 結果と x2tree07.icnの説明は、次回に。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: 河よりも長くゆるやかに/篠原美也子 (icon_308.txt 1997/05/11 PCVAN PIG) ■ Icon > Icon散歩道(9) 再び x2tree(1) 風つかい 目次 まず、前回の 「再び dir2tree」の続きです。 FDの root directoryからの treeを 表示してみました。 -----^ ICON_FD2.DIR ( date:97-05-10 time:23:55 ) -----------<cut here A:\ <DIR> + NOT_ARCH <DIR> 97-05-03 21:00 NOT_ARCH | + ICON_LEC DOC 3,038 97-04-23 23:17 ICON_LEC.DOC | + ICON_LEC TXT 116,916 97-04-23 23:15 ICON_LEC.TXT | + ICONLEC2 DOC 2,686 97-04-23 23:19 ICONLEC2.DOC | + ICONLEC2 TXT 125,700 97-04-23 23:20 ICONLEC2.TXT | + ICONLEC3 DOC 2,746 97-05-08 12:47 ICONLEC3.DOC | + ICONLEC3 TXT 105,141 97-05-08 12:47 ICONLEC3.TXT + OTHER <DIR> 97-05-03 21:00 OTHER | + ICON_LEC ENG 3,109 97-04-23 23:30 ICON_LEC.ENG | + ICONLEC2 ENG 2,869 97-04-23 23:32 ICONLEC2.ENG | + ICONLEC3 ENG 2,924 97-05-09 20:00 ICONLEC3.ENG | + CONTRIB TXT 2,309 97-04-26 13:57 CONTRIB.TXT | + CONTRIB2 TXT 752 97-05-09 19:39 CONTRIB2.TXT + ICON_LEC LZH 42,239 97-04-26 10:07 ICON_LEC.LZH + ICONLEC2 LZH 44,737 97-04-26 10:07 ICONLEC2.LZH + ICONLEC3 LZH 33,723 97-05-08 12:48 ICONLEC3.LZH -----$ ICON_FD2.DIR ( lines:17 words:123 ) -----------------<cut here さて、今回は、「再び x2tree」というタイトルですが、これは ミスではなく 機能アップです。(汗) x2treeは、構造体を使った programの testの際に便利なのですが、 treeの列 の進みを指定できる ように して置かなかったので、階層が多い 構造体の tree 表示では、列の端が、画面から外れてしまします。 そこで、treeの列の進みを指定できるように修正しました。 -----^ X2TREE07.ICN ( date:97-05-08 time:21:54 ) -----------<cut here # 構造体の構成を tree状に見せる generator (recursive) # x2tree07.icn Rev.1.1 1997/05/08 windy # x2tree06.icn にて、列の進みを設定可にしたもの # This file is in the public domain. link jimage procedure x2t(x,step) # generator # topの処理 suspend "<" || type(x) || " " || string(serial(x)) || ">" #↑listの serial No ss := repl(" ", \step | 0) suspend " " || ss || x2tree(x,ss,"") #↑初期化フラグ end procedure x2tree(x,ss,init) # generator # show the tree structure of x static T # serial No 登録用 set登録用 table static宣言をして # おかないと、再帰したときに、未定義 errorとなる。 if \init then { # 初期化を initialでやると、同じ program内で別の # 構造体 tree表示のために、再び x2tを 呼んだ時に # 実行されなくて状態が残るので、フラグで初期化指示 T := table() T["list"] := set() # ここは、table(set())とすると、全て同じ setが T["set"] := set() # 割り当てられてしまうので、個別に初期化する。 T["table"] := set() if (t := type(x)) == ("list" | "set" | "table") then insert(T[t],serial(x)) # serial Noを T[type(x)]に登録 } n := *x # 枝の末端検出用カウンタ if (tt := type(x)) ~== "table" then { # not table every xx := !x do { # 構造体の要素を1つ づつ取り出す n -:= 1 t := type(xx) val_disp := if t == ("list" | "set" | "table") then "+ <" || t || " " || string(m := serial(xx)) || ">" else "+ " || left(t,7) || jimage(xx) case t of { # 構造体のタイプにより、 "string" : suspend val_disp #↓list,set,tableなら、typeを書出して、その中身をまた解析する。 "list" | "set" | "table" : { #↓再帰構造で なければ。(T[type(xx)] に既に登録済みなら再帰構造) if not member(T[t],m) then { insert(T[t],m) # serial Noを T[type(xx)]へ登録 suspend val_disp suspend (if n > 0 then "| " else " ") || ss || ss || x2tree(xx,ss) #↑枝の途中 #↑枝の末端 # 再帰↑ delete(T[t],m) #←serial No 登録を削除 } else { # 再帰構造 ならば、書き出すとキリが無いので打止め return val_disp || " (Recursion)" } } #↓その他なら、typeと値を書き出す。 default : suspend val_disp } } } else { # table every xkey := key(x) do { # tableの keyを1つ づつ取り出す n -:= 1 tk := type(xkey) xx := x[xkey] t := type(xx) val_disp := if t == ("list" | "set" | "table") then "+ <" || t || " " || string(m := serial(xx)) || ">" else "+ " || left(t,7) || jimage(xx) key_disp := if tk == ("list" | "set" | "table") then " <- <" || tk || " " || string(serial(xkey)) || ">" else " <- " || left(tk,7) || jimage(xkey) case t of { # 構造体のタイプにより、 "string" : suspend val_disp || key_disp #↓list,set,tableなら、typeを書出して、その中身をまた解析する。 "list" | "set" | "table" : { #↓再帰構造で なければ。(T[type(xx)] に既に登録済みなら再帰構造) if not member(T[t],m) then { insert(T[t],m) # serial Noを T[type(xx)]へ登録 suspend val_disp || key_disp suspend (if n > 0 then "| " else " ") || ss || ss || x2tree(xx,ss) #↑枝の途中 #↑枝の末端 # 再帰↑ delete(T[t],m) #←serial No 登録を削除 } else { # 再帰構造 ならば、書き出すとキリが無いので打止め return val_disp || key_disp || " (Recursion)" } } #↓その他なら、typeと値を書き出す。 default : suspend val_disp || key_disp } } } end -----$ X2TREE07.ICN ( lines:101 words:448 ) ----------------<cut here test programと その結果は、次回に。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: 河よりも長くゆるやかに/篠原美也子 (icon_309.txt 1997/05/11 PCVAN PIG) ■ Icon > Icon散歩道(10) 再び x2tree(2) 風つかい 目次 前回の 「再び x2tree」の続きです。test programとその結果です。 test programが長くなりましたので、分けました。 -----^ X2TREE7~.ICN ( date:97-05-08 time:21:54 ) -----------<cut here # test driver for x2tree07.icn # x2tree7~.icn 1997/05/08 windy # This file is in the public domain. link x2tree07 procedure main() # #listの test L1 := ["A","B"] L2 := ["C","D"] L3 := ["E","F"] put(L1,L2) put(L2,L3) put(L1,L3) # 別枝 test put(L3,L1) # listの再帰 every write(x2t(L1) \20) # \20は、テストをドジッた時に、20個で止めるため。 write() #tableの test T := table() T["A"] := "G" T["C"] := L2[1] T["E"] := L3 T[L1] := L1[1] put(L3,T) # tableの再帰 every write(x2t(T) \20) write() #setの test L4 := ["H","I"] S1 := set(["L","M"]) S := set(["J","K",L4]) insert(S,S1) insert(S1,S) # setの再帰 every write(x2t(S) \20) write() every write(x2t(L1,1) \20) every write(x2t(S,1) \20) every write(x2t(T,1) \20) write() every write(x2t(L1,2) \20) every write(x2t(S,2) \20) every write(x2t(T,2) \20) end -----$ X2TREE7~.ICN ( lines:46 words:111 ) -----------------<cut here 同じデータで、順番に、列の進みを増やしています。 -----^ X2TREE07 ( date:97-05-11 time:00:43 ) ---------------<cut here <list 1> + string "A" + string "B" + <list 2> | + string "C" | + string "D" | + <list 3> | + string "E" | + string "F" | + <list 1> (Recursion) + <list 3> + string "E" + string "F" + <list 1> (Recursion) <table 2> + string "C" <- string "C" + <list 3> <- string "E" | + string "E" | + string "F" | + <list 1> | | + string "A" | | + string "B" | | + <list 2> | | | + string "C" | | | + string "D" | | | + <list 3> (Recursion) | | + <list 3> (Recursion) | + <table 2> (Recursion) + string "A" <- <list 1> + string "G" <- string "A" <set 8> + string "K" + <list 44> | + string "H" | + string "I" + <set 7> | + string "M" | + string "L" | + <set 8> (Recursion) + string "J" <list 1> + string "A" + string "B" + <list 2> | + string "C" | + string "D" | + <list 3> | + string "E" | + string "F" | + <list 1> (Recursion) + <list 3> + string "E" + string "F" + <list 1> (Recursion) <set 8> + string "K" + <list 44> | + string "H" | + string "I" + <set 7> | + string "M" | + string "L" | + <set 8> (Recursion) + string "J" <table 2> + string "C" <- string "C" + <list 3> <- string "E" | + string "E" | + string "F" | + <list 1> | | + string "A" | | + string "B" | | + <list 2> | | | + string "C" | | | + string "D" | | | + <list 3> (Recursion) | | + <list 3> (Recursion) | + <table 2> (Recursion) + string "A" <- <list 1> + string "G" <- string "A" <list 1> + string "A" + string "B" + <list 2> | + string "C" | + string "D" | + <list 3> | + string "E" | + string "F" | + <list 1> (Recursion) + <list 3> + string "E" + string "F" + <list 1> (Recursion) <set 8> + string "K" + <list 44> | + string "H" | + string "I" + <set 7> | + string "M" | + string "L" | + <set 8> (Recursion) + string "J" <table 2> + string "C" <- string "C" + <list 3> <- string "E" | + string "E" | + string "F" | + <list 1> | | + string "A" | | + string "B" | | + <list 2> | | | + string "C" | | | + string "D" | | | + <list 3> (Recursion) | | + <list 3> (Recursion) | + <table 2> (Recursion) + string "A" <- <list 1> + string "G" <- string "A" -----$ X2TREE07 ( lines:124 words:501 ) --------------------<cut here 当分は、ミスに気がつきませんように。(笑) 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: 河よりも長くゆるやかに/篠原美也子 (icon_310.txt 1997/05/11 PCVAN PIG) ■ Icon > Icon迷い道(1) system() 風つかい 目次 Icon散歩道の方では、次は 多項式の展開 をやってみるつもりなんですが、 結構 道が険しくて、次のお話しが書けません。 (a+b+c)^2 を a^2+b^2+c^2+2ab+2ac+2bcに、変換する程度の処理を、考えて いるのですが、どうやって programを 組めば良いのか 思いつきません。 そちらは、しばらく考えてみるとして、何にも書かないのもさみしいので、 近ごろ書いた programを紹介します。 niftyと PCVANの log fileから OSL/Libraryの Icon関係 fileタイトルの部分 を抜き出すものです。 YOTさんの ygrepを使わさせて頂いています。 ygrepの引数になる文字列を作って、system()関数に与えるだけです。 MS-DOSの batch programで書ける内容ですが、re-directが できないとかの 制限がありますので、Iconから呼んでいます。 command line引数に、日付(月日)を与えると その日付の log fileを、 与えなければ、その日の log fileを検索します。 map関数を使って、 keywordの &dateから日付を 抜き出しています。 &dateは、1997/06/04という形式をしています。これから 0604の部分を 抜き出すものです。 すると、使っている式は map("679A","123456789A","1997/06/04") となります。 map関数は、本来は文字変換の関数です。 その解釈ですと、前の式は 文字列 "679A"を 次の 規則で変換することになります。 1 -> 1 すると、ご覧のように "679A"は、ちょうど月日の部分 2 -> 9 の数字に変換されます。 3 -> 9 ちょっと、パズルみたいですが、このやり方を 覚えて 4 -> 7 おくと便利です。 5 -> / 部分文字列指定の 6 -> 0 &date[[6:8] || &date[9:0] 7 -> 6 と同じ結果になります。 8 -> / 9 -> 0 A -> 4 さて、 programです。 -----^ IDLG.ICN ( date:97-06-04 time:23:49 ) ---------------<cut here # niftyと PCVANの logから Icon関係 download数 の部分を切り出し # idlg.icn Rev.1.3 1997/06/04 windy file-name変更 idl.icn -> idlg.icn # comment追加 # idl.icn Rev.1.2 1997/06/01 windy 不正 date検出強化 # idl.icn Rev.1.1 1997/05/23 windy Kazetuskai H.S. # YOTさんの ygrep(超高速・多機能 grep)を使用。 # Usage: idlg または idlg MMDD procedure main(args) # 日付指定が あればその日付 無ければその日 の log fileを対象にする。 # ↓format変換(月日抜き出し) date := right(numeric(args[1]),4,"0") | map("679A","123456789A",&date) # 1997/06/04の形式↑ # ygrepの呼び出しパラメータ生成 # nifty用 ↓ OR検索 s1 := "ygrep \"{icon,bipl,de386}.*lzh\"" || " nif" || date || ".log " # PCVAN用 ↓一致行の前の行も出力 s2 := "ygrep -B1 \"{icon,bipl,de386}.*lzh\"" || " van" || date || ".log " write(&errout,s1) system(s1) # nifty log検索 write(&errout,s2) system(s2) # PCVAN log検索 end -----$ IDLG.ICN ( lines:26 words:105 ) ---------------------<cut here 結果は、こんなものです。(単なる grepの結果です。汗) -----^ DL970605.G ( date:97-06-05 time:00:18 ) -------------<cut here 82 PFF01531 97/05/03 33393 2 B ICONLEC3.LZH テキスト処理言語Icon入門講座3 (中略) 17 PFF01531 96/12/08 41893 133 B ICON_LEC.LZH テキスト処理言語Icon入門講座 89.ICONLEC3.DOC TRA11936 97/ 5/ 3 0002747 0000005 ICONLEC3.LZH TRA11936 97/ 5/ 3 0033385 0000003 (中略) 413.DE386_93.DOC TRA11936 97/ 5/11 0003329 0000029 DE386_93.LZH TRA11936 97/ 5/11 0206581 0000012 -----$ DL970605.G ( lines:24 words:165 ) -------------------<cut here 迷い道から、抜け出せるかな〜。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: 河よりも長くゆるやかに/篠原美也子 (icon_351.txt 1997/06/06 PCVAN PIG) ■ Icon > Icon迷い道(2)download数 集計 風つかい 目次 前回、Iconから ygrepを呼んで、log fileから Icon関係 fileのタイトル行を 切り出す programをご覧にいれました。 更に 集計表まで 出してくれるといい ということで、Iconだけで集計 programを書いてみました。 -----^ DL970607 ( date:97-06-07 time:00:35 ) ---------------<cut here <1997/06/07> PIG SLABO PFL FGALTS file計 BIPL.LZH - 11 - 19 30 DE386.LZH - 12 - 40 52 ICONLEC3.LZH 3 11 3 46 63 ICONLEC2.LZH 3 16 41 67 127 ICON_LEC.LZH 6 32 91 134 263 ------------------------------------------------ SIG/forum計 12 82 135 306 535 -----$ DL970607 ( lines:8 words:43 ) -----------------------<cut here listで 集計表を 作っておきます。 logを1行づつ 読みながら fileの titleの 行から download数を 切り出して 表を更新します。 log fileが 終わると、 集計表を出力しています。 -----^ IDL.ICN ( date:97-06-05 time:00:21 ) ----------------<cut here # niftyとPCVANの logファイルから Icon関係 fileの download数抽出 # idl.icn Rev.1.2 1997/06/05 windy file-name変更 idl2.icn -> idl.icn # comment追加 # idl2.icn Rev.1.1 1997/06/04 windy Kazetsukai H.S. # This file is in the public domain. # Usage: idl または idl MMDD procedure main(args) # download数 格納 list(2重 list) #↓ [1]:PIG [2]:SLABO [3]:FPL [4]:FGALTS L := [ [ 0 ,0, 0 ,0], # L[1] ICON_LEC.LZH [ 0 ,0, 0 ,0], # L[2] ICONLEC2.LZH [ 0 ,0, 0 ,0], # L[3] ICONLEC3.LZH ["-",0,"-",0], # L[4] DE386.LZH PIG,FPLには uploadしていない。 ["-",0,"-",0] ] # L[5] BIPL.LZH PIG,FPLには uploadしていない。 # file名称 作成 # command line引数が数字に変換できれば、file日付に使う。できなければ、 # その日の日付を file日付に使う。 f_date := right(numeric(args[1]),4,"0") | map("679A","123456789A",&date) #↑ &dateの 6,7,9,10番目の文字を抜き出す。(map関数の応用) # &dateは 1997/06/04の形式 f_nif := "nif" || f_date || ".log " # nifty log file名生成 f_van := "van" || f_date || ".log " # PCVAN log file名生成 #################### # nifty 処理 #################### # nifty log file例 #1 16 33 37 # 17 PFF01531 96/12/08 41893 130 B ICON_LEC.LZH テキスト処理言語Icon入門講座 dir_nif := open(f_nif) | stop("cannot open ",f_nif) write(&errout,f_nif) size_nif := 15 # Icon関係 file検出のための照合字数 while line := read(dir_nif) do { # log fileを1行づつ読み込んで nn := numeric(line[33:37]) # download数 切り出し case line[1:size_nif+1] of { # download数を listに登録 " 17 PFF01531 " : L[1][4] := nn # FGALTS ICON_LEC.LZH " 20 PFF01531 " : L[2][4] := nn # FGALTS ICONLEC2.LZH " 21 PFF01531 " : L[3][4] := nn # FGALTS ICONLEC3.LZH " 163 PFF01531 " : L[4][4] := nn # FGALTS DE386_93.LZH " 124 PFF01531 " : L[5][4] := nn # FGALTS BIPL93.LZH " 78 PFF01531 " : L[1][3] := nn # FPL ICONLEC1.LZH " 81 PFF01531 " : L[2][3] := nn # FPL ICONLEC2.LZH " 82 PFF01531 " : L[3][3] := nn # FPL ICONLEC3.LZH } } close(dir_nif) #################### # PCVAN処理 #################### # PCVAN log file 例 #1 19 52 59 # 219.ICON_LEC.DOC TRA11936 96/12/ 8 0002421 0000032 # ICON_LEC.LZH TRA11936 96/12/ 8 0041893 0000032 dir_van := open(f_van) | stop("cannot open ",f_van) write(&errout,f_van) size_van := 18 # Icon関係 file検出のための照合字数 while line := read(dir_van) do { # log fileを1行づつ読み込んで nn := numeric(line[52:59]) # download数 切り出し case line[1:size_van+1] of { # SIG検出 (" 219.ICON_LEC.DOC " | " 243.ICONLEC2.DOC " | " 256.ICONLEC3.DOC " ) : mode := "LAB" # SLABO処理中 (" 79.ICON_LEC.DOC " | " 84.ICONLEC2.DOC " | " 89.ICONLEC3.DOC ") : mode := "PIG" # PIG処理中 # download数を listに登録 " ICON_LEC.LZH " : if mode == "LAB" then L[1][2] := nn # SLABO else L[1][1] := (nn-1) # PIG # download test分 ↑ " ICONLEC2.LZH " : if mode == "LAB" then L[2][2] := nn # SLABO else L[2][1] := nn # PIG " ICONLEC3.LZH " : if mode == "LAB" then L[3][2] := nn # SLABO else L[3][1] := nn # PIG " DE386_93.LZH " : L[4][2] := nn # SLABO " BIPL93.LZH " : L[5][2] := nn # SLABO } } close(dir_van) #################### # 表にして出力 #################### f_name := [ "ICON_LEC.LZH ", # file名称 list "ICONLEC2.LZH ", "ICONLEC3.LZH ", "DE386.LZH ", "BIPL.LZH ", "SIG/forum計 " ] size_f_name := *f_name[1] sig := [ " PIG", # SIG/forum名称 list " SLABO", " PFL", " FGALTS", " file計" ] size_sig := *sig[1] # 日付生成 ↓fdateに"/"を挿入。(map関数の応用) writes(left("<" || &date[1:6] || map("12/34",1234,f_date) || ">",size_f_name)) every writes(!sig) # SIG/forum名出力 write() L_sum_col := [0,0,0,0,0] # SIG/forum毎の download数 集計用 list every i := *L to 1 by -1 do { # listの末尾から(逆順出力のため) writes(f_name[i]) # file名出力 sum_line := 0 # file毎の download数 集計 every j := 1 to *L[i] do { writes(right((nnn := L[i][j]),size_sig)) # file毎 download数 sum_line +:= (nnnn := numeric(nnn) | 0) # 数字なら足し込む L_sum_col[j] +:= nnnn # 数字なら足し込む } write(right(sum_line,size_sig)) # file毎 daownload数 出力 L_sum_col[-1] +:= sum_line # 総計に足し込む } write(repl("-",*L_sum_col * size_sig +size_f_name)) # 仕切り線 writes(f_name[-1]) # "SIG/forum計 "の文字を出力 # (f_nameの最後の要素) every writes(right(!L_sum_col,size_sig)) # SIG/forum毎の計 write() end -----$ IDL.ICN ( lines:131 words:617 ) ---------------------<cut here (追記 97/11/24現在では次の download数になっています。) -----^ DL971124 ( date:97-11-24 time:10:16 ) ---------------<cut here <1997/11/24> PIG SLABO FPL FGALTS file計 BIPL.LZH - 14 - 33 47 DE386.LZH - 17 - 89 106 ICONLEC3.LZH 3 12 18 95 128 ICONLEC2.LZH 5 16 56 111 188 ICON_LEC.LZH 7 34 109 196 346 ------------------------------------------------ SIG/forum計 15 93 183 524 815 -----$ DL971124 ( lines:8 words:43 ) -----------------------<cut here 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: 河よりも長くゆるやかに/篠原美也子 (icon_352.txt 1997/06/07 PCVAN PIG) ■ Icon > Icon迷い道(3)CSV:定義ファイルの読込 風つかい 目次 夏の盛りから、担当している 某 projectの関係で、某所に拉致されており ましたが、一区切りつきましたので娑婆に戻って、気がつけばもう秋深し。 Icon講座は、どこまで書いたか記憶の彼方です。 確か、CSVデータ(コンマ区切りデータ)を、 表形式の テキストデータに 変換するprogram を作って upload しようとしていた ような 気がします。 リハビリと兼ねて、思い出しながら 続きをやってみたい と思います。 しかし、某 projectは未だ続いていますので、Icon講座が 途絶えましたら、 また 某所に拉致されたな と思って下さい。(笑) さて、CSVデータというのは、こんなデータです。 "なかやまみほ","中山美穂",1970,3,1,"O",158,80,60,84,45,"東京都小金井市" コンマ区切りのデータで、文字列は " で くくってあります。 文字列中に " が 現れる場合は、"" で表わすものとします。 CSVといっても、細かい点で仕様が違うものが、いくつかあるようですが、ここ ではこの仕様とします。 例のようなデータが並んでいる データファイルを、表形式のデータへ 変換した り、表形式のデータを逆に CSVデータへ変換するものを作ってみます。 例のデータを表形式にするためには、各欄を何文字の表にするかの情報をどこか で定義しないといけません。 たとえばこんな感じです。各欄の文字数を定義する ついでに、文字か数字かの情報もまとめて定義しています。 -----^ CSV2TB.CFG ( date:97-10-27 time:00:02 ) -------------<cut here #################### # csv -> 表データ 変換指定ファイル #################### # 行頭が "#"あるいは行に "="が含まれ無いなら、無視。(コメント) # 処理対象ファイル名の先頭の文字にて、処理指定を識別する。 # ファイル識別文字("="の手前の文字)は、英字大文字。 # 変換指示は、","区切りのデータを何桁のデータとして扱うかを、指示。 # 変換指定例 # s14 : 14桁の文字列、n4 : 4桁の数字、s0 : その欄は無視(n0でも良い) # csvデータより、指定桁が大きい場合は、後ろに " "が追加される。 # 変換指定が無い部分の csvデータは無視される。 #################### # テスト用サンプルデータ # "なかやまみほ","中山美穂",1970,3,1,"O",158,80,60,84,45,"東京都小金井市",10 SAM= s13 s9 n4 n2n2 s0 n3 n3 n3 n3 n3 s12 n2 -----$ CSV2TB.CFG ( lines:17 words:52 ) --------------------<cut here ということで、こんな定義ファイルを読みこむための procedureを 先ず 作って みることにします。 早速、programです。定義ファイルを読み込んで listへ格納する programと その listに格納されている keyと stringをチェックする2つの procedureが 含まれています。 -----^ GET_INL.ICN ( date:97-10-27 time:23:59 ) ------------<cut here #################### # 初期化ファイル・定義ファイルの読み込み(文字列ダブリ対応) #################### # args : string(拡張子名) # value: list (初期設定値の [key1,value1,key2,value2,...]) # Usage: L_INI := get_inil("INI") # 実行ファイル名の拡張子を INIに変えたものを初期化ファイルとみなす。 # 初期化ファイルの形式は、下記の形式 # Nantara=Kantara Dotara # ["Nantara","Kantara Dotara"]が valueとなる。 # "="が、含まれ無い行は無視される。(コメント行に使える) # 備考 : ある keyの文字列が他の keyの文字列に含まれる場合は、 # keyは降順に書き込むこと。(長い順にチェックしないと無視されるので) # ABC=D:\icon\ # AB=D:\icon\my_procs\ # This file is in the public domain. link file_e # f_name() procedure get_inil(ext) L := [] # list生成 /ext := "INI" # 拡張子 default dir := open(f_name() || "." || ext) | # 初期化ファイルを fail # while line := read(dir) do { # 1行ずつ読み込み line ? { # lineを走査対象として #↓2番目の式を値とする put(L,tab(upto('=')),2(move(1),tab(0))) } # ↑'='迄の文字列 ↑ ↑残りの文字列 } # ↑を keyとして "="文字スキップ return L end #################### # 文字列の先頭が Lの keyにあれば、valueを返す #################### # args : [1]:list [key1,value1,key2,value2,...]の形式 # [2]:string # value: keyが文字列の先頭と一致すれば、keyに対応した value # 備考 : Lは再使用不可。 # This file is in the public domain. procedure key_check(L,s) /s := &subject while ss := get(L) do { # keyを取り出して、 # keyが文字列の先頭に一致すれば、valueを返す。不一致なら読み飛ばし。 if match(ss,s) then return get(L) else get(L) } fail # 一致しなければ、fail end -----$ GET_INL.ICN ( lines:50 words:165 ) ------------------<cut here (差し替え) f_name()は以前 exe_name()という名前で紹介しました procedureです。 実行ファイル名を取り出す procedureです。 私は f_name()を、現在は file_e.icn という procedureのファイルの中に入れていますので、file_eを linkしています。 get_inilの test programを次に。 定義ファイルを読み込んで読み込んだ結果 の listの表示を行う部分と key_checkを行った結果の表示を 行う部分が含まれ ています。 -----^ GET_INL~.ICN ( date:97-10-27 time:23:55 ) -----------<cut here # test procedure for get_inil # This file is in the public domain. link view_e, # x2t() file_e # get_inil(), key_check() procedure main() every write(x2t(get_inil())) every write(x2t(get_inil("CFG"))) write(key_check(get_inil("CFG"),"lmnopqr") | "error") write(key_check(get_inil("CFG"),"lmno") | "error") write(key_check(get_inil("CFG"),"lmn") | "error") write(key_check(get_inil("CFG"),"abcd") | "error") end -----$ GET_INL~.ICN ( lines:12 words:40 ) ------------------<cut here tree表示 の x2t()は、view_eに、get_inil(),key_checkは、file_eに入れている ため 各々を linkしています。 定義ファイルのサンプルです。 -----^ GET_INL~.INI ( date:97-10-27 time:23:57 ) -----------<cut here # test data for get_inl~ ABC=abc_ini DEFG=デーイーエフジー hijk=123,456 -----$ GET_INL~.INI ( lines:5 words:8 ) --------------------<cut here もう1つの定義ファイルサンプルです。 -----^ GET_INL~.CFG ( date:97-10-27 time:23:56 ) -----------<cut here # test data for get_inl~ hijk=123,456,789 lmno=lmnoだ pqrs= lmn=lmnだ -----$ GET_INL~.CFG ( lines:6 words:9 ) --------------------<cut here 結果はこうなります。 -----^ GET_INIL ( date:97-10-27 time:00:30 ) ---------------<cut here <list 1> + string "ABC" + string "abc_ini" + string "DEFG" + string "デーイーエフジー" + string "hijk" + string "123,456" <list 84> + string "hijk" + string "123,456,789" + string "lmno" + string "lmnoだ" + string "pqrs" + string "" + string "lmn" + string "lmnだ" lmnoだ lmnoだ lmnだ error -----$ GET_INIL ( lines:20 words:50 ) ----------------------<cut here というところで、今日はこのくらいにします。 次回は、定義ファイルを 解析するあたりをやってみます。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: Smile/岡本真夜 (icon_353.txt 1997/10/27 PCVAN PIG) ■ Icon > Icon迷い道(4)CSV:定義ファイルの解析 風つかい 目次 今日は、定義ファイルの解析の部分をやります。定義ファイルは、CSVデータと 並べて次のように指定したいのです。 SAM= s4 s1 n1n2 n3 s16 # "地球","E",1,15,256,"ちきゅうはまるい" 順に、地球 -> s4 E -> s1 1 -> n1 15 -> n2 256 -> n3 ちきゅうはまるい -> s16 と指定している訳です。 programでは、CSVデータの欄に対応した指定を listに格納しておくことに します。 前回の定義ファイルの読込みでは、 SAM= s4 s1 n1n2 n3 s16 という stirngを ["SAM"," s4 s1 n1n2 n3 s16"] と 変換して、"SAM"で listデータを サーチして、" s4 s1 n1n2 n3 s16" という文字列を 取り出すところまで 済んでいます。 今回は、この指定文字列を、欄毎の指定が順に詰まった listへ変換する部分 を作ります。 指定が全てスペース区切りなら、以前紹介しました splitとかで listに変換 できるのですが、今回のデータは スペースが無い部分もあります ので、 別の 方法が必要です。 指定が、アルファベット1文字と数字の組み合わせですので、その組み合わせ を検索して、listに順に格納する procedureを作ります。 こういう データ変換 procedureを 簡単に作れるところが、Iconの良いところ です。 というところで、programです。 Test programも一緒に入れています。 -----^ CN_SPLIT.ICN ( date:97-10-29 time:00:42 ) -----------<cut here #################### # 文字列処理指定の文字列を解析 #################### # cn_split.icn 1997/10/29 windy comment追加 # cn_split.icn 1997/08/20 windy 風つかい H.S. # This file is in the public domain. # Test program procedure main() s := "s4 s1 n1n2 n3 s16" s ? every write(!cn_split()) end #################### # 文字列処理指定の文字列を解析 #################### # 処理指定(英文字1文字を想定)+処理文字数 # args : c1 : cset(処理指定1バイト文字セット) # c2 : cset(処理文字数、数字n桁) # s : 指定文字列 # value: list(処理指定を順に詰めたもの) # 例 : "s4 s1 n1n2 n3 s16" -> [s4,s1,n1,n2,n3,s16] と変換 # "地球","E",1,15,256,"ちきゅうはまるい" # 備考 : csvデータを表データに変換するプログラムのために作成 # 上の例の用に、データ例と並べて指定が可能なプログラムにするため procedure cn_split(s,c1,c2) /s := &subject # default /c1 := &letters # 英文字の大文字・小文字のセット /c2 := &digits # 数字のセット '0123456789' L := [] # 戻り値用 list s ? { while tab(upto(c1)) do { # c1迄スキップ ss := "" # ss := tab(many(c1)) # c1以外の文字迄スキップし、その間の文字 # を ssへ put(L,ss ||:= tab(many(c2))) # c2以外の文字迄スキップし、その間の文字 # を ssへ足しこむ } } return L end -----$ CN_SPLIT.ICN ( lines:42 words:140 ) -----------------<cut here cn_split.exeを実行した結果です。 -----^ CN_SPLIT ( date:97-10-29 time:00:42 ) ---------------<cut here s4 s1 n1 n2 n3 s16 -----$ CN_SPLIT ( lines:6 words:6 ) ------------------------<cut here あと、もう一つ procedureを準備しますが、それは次回に。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: Smile/岡本真夜 (icon_354.txt 1997/10/29 PCVAN PIG) ■ Icon > Icon迷い道(5)CSV:拡張子変更(1) 風つかい 目次 さて、今日は 拡張子を変更する procedureについて説明します。この procedure は、CSVデータのファイル名を foo.csvとしますと、CSVデータを表形式データに変換 したデータのファイルは拡張子を変えて、foo.txtという名称にするためのものです。 まず ファイル名の '.' の前の部分と 後ろの部分を分ける procedureを作ります。 早速、programです。 -----^ DOT.ICN ( date:97-10-30 time:00:33 ) ----------------<cut here #################### # 文字列 sの 文字 cより手前と後ろの部分を得る。 #################### # 文字列 sの 文字 cより手前と後ろの部分を得る。 # 尚、文字 cは、1個か もしくは無い場合を想定、複数の場合は top_get()や # top_cut() を使う。 # ファイル名の拡張子を除いた部分や拡張子を得る場合とか、数字の小数点以下や # 以上の値を得る場合に使用。 # dot.icn 1997/10/30 windy comment修正 # dot.icn 1997/08/15 windy 風つかい H.S. # This file is in the public domain. #################### # cより手前の部分を得る。 #################### # args : (1):文字列, (2):文字(セット) # value: 文字列 # cが含まれ無い場合は、引数文字列 procedure pre_char(s,c) /c := '.' # default s ? return tab(upto(c) | 0) end #################### # cより後ろの部分を得る。 #################### # args : (1):文字列, (2):文字(セット) # value: 文字列 # cが含まれ無い場合は、""(空文字列) procedure post_char(s,c) /c := '.' # default s ? return if tab(upto(c)) then 2(move(1),tab(0)) else "" end -----$ DOT.ICN ( lines:36 words:102 ) ----------------------<cut here この部分の Test programです。 -----^ DOT~.ICN ( date:97-10-30 time:00:43 ) ---------------<cut here # test procedure for dot.icn # dot~.icn 1997/10/30 windy comment修正 # dot~.icn 1997/08/15 windy 風つかい H.S. # This file is in the public domain. link dot procedure main() write(s := "abcd.efg"," ",pre_char(s)," ",post_char(s)) write(s := "abcd"," ",pre_char(s)," ",post_char(s)) write(s := ".efg"," ",pre_char(s)," ",post_char(s)) write(s := "abcd."," ",pre_char(s)," ",post_char(s)) write(s := "123.45"," ",pre_char(s)," ",post_char(s)) write(s := "123"," ",pre_char(s)," ",post_char(s)) write(s := ".45"," ",pre_char(s)," ",post_char(s)) write(s := "123."," ",pre_char(s)," ",post_char(s)) end -----$ DOT~.ICN ( lines:16 words:69 ) ----------------------<cut here dot~.exeの結果です。 -----^ DOT~ ( date:97-10-30 time:00:36 ) -------------------<cut here abcd.efg abcd efg abcd abcd .efg efg abcd. abcd 123.45 123 45 123 123 .45 45 123. 123 -----$ DOT~ ( lines:8 words:18 ) ---------------------------<cut here ちょっと、長くなりましたので、続きは次回に。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: Blow by Blow / Jeff Beck (icon_355.txt 1997/10/30 PCVAN PIG) ■ Icon > Icon迷い道(6)CSV:拡張子変更(2) 風つかい 目次 さて、拡張子を変更する procedureのつづきです。 前回 作りました '.' の前の 部分と 後ろの部分を分ける procedureを使って、拡張子を変更したりチェックした りする procedureを作ります。 -----^ EXT.ICN ( date:97-10-30 time:00:48 ) ----------------<cut here #################### # 拡張子名変更・チェック #################### # ext.icn 1997/10/30 windy comment修正 # ext.icn 1997/08/25 windy 風つかい H.S. link dot #################### # 拡張子名変更ファイル名生成 #################### # 拡張子名が ext1ならば、拡張子を ext2に変更したファイル名を生成 # args : (1):許容チェック拡張子名, (2):新拡張子, (3):ファイル名,(4):反転 # value: string: 新ファイル名 # 拡張子が ext1で無ければ、失敗 # 備考 : negに、何か値をセットすると条件を反転(拡張子が、ext1で無ければ # ...という動作となる。 procedure change_ext(ext1,ext2,f_name,neg) return if /neg # ↓'.'以前の文字列 then 2(map(ext1) == map(post_char(f_name)),pre_char(f_name) || "." || ext2) # ↑'.'以降の文字列(=拡張子) # ↓↑比較式は、成功すれば右辺値になる。 else 2(map(ext1) ~== map(post_char(f_name)),pre_char(f_name) || "." || ext2) end #################### # 拡張子名チェック #################### # 拡張子名が extかどうかチェック # args : (1):許容拡張子名, (2):ファイル名 ,(3):反転 # value: string: ファイル名 # 拡張子が extでなければ、失敗 # 拡張子無しのチェックは、extに ""(空文字列)をセット # 備考 : negに、何か値をセットすると条件を反転(拡張子が、extなら失敗) procedure check_ext(ext,f_name,neg) return if /neg then 2(map(ext) == map(post_char(f_name)),f_name) else 2(map(ext) ~== map(post_char(f_name)),f_name) end -----$ EXT.ICN ( lines:41 words:113 ) ----------------------<cut here Test programです。 -----^ EXT~.ICN ( date:97-10-30 time:01:08 ) ---------------<cut here #################### # 拡張子名変更・チェック Test program #################### # ext~.icn 1997/10/30 windy comment修正 # ext~.icn 1997/08/25 windy 風つかい H.S. link ext procedure main() write("拡張子チェック:check_ext test") write(s1 := "def"," ",s2 := "abc.def"," ",check_ext(s1,s2) | "error") write(s1 := "DEF"," ",s2 := "abc.def"," ",check_ext(s1,s2) | "error") write(s1 := "def"," ",s2 := "abc.DEF"," ",check_ext(s1,s2) | "error") write(s1 := "def"," ",s2 := "abc"," ",check_ext(s1,s2) | "error") write(s1 := ""," ",s2 := "abc.def"," ",check_ext(s1,s2) | "error") write(s1 := ""," ",s2 := "abc"," ",check_ext(s1,s2) | "error") write("拡張子変更:change_ext test") write(s1 := "def"," ",s2 := "xyz"," ",s3 := "abc.def"," ", change_ext(s1,s2,s3) | "error") write(s1 := "DEF"," ",s2 := "xyz"," ",s3 := "abc.def"," ", change_ext(s1,s2,s3) | "error") write(s1 := "def"," ",s2 := "xyz"," ",s3 := "abc.DEF"," ", change_ext(s1,s2,s3) | "error") write(s1 := "def"," ",s2 := "xyz"," ",s3 := "abc.txt"," ", change_ext(s1,s2,s3) | "error") write(s1 := ""," ",s2 := "xyz"," ",s3 := "abc.def"," ", change_ext(s1,s2,s3) | "error") write(s1 := ""," ",s2 := "xyz"," ",s3 := "abc"," ", change_ext(s1,s2,s3) | "error") write("拡張子チェック:check_ext 条件反転 test") write(s1 := "def"," ",s2 := "abc.def"," ",check_ext(s1,s2,"") | "error") write(s1 := "DEF"," ",s2 := "abc.def"," ",check_ext(s1,s2,"") | "error") write(s1 := "def"," ",s2 := "abc.DEF"," ",check_ext(s1,s2,"") | "error") write(s1 := "def"," ",s2 := "abc"," ",check_ext(s1,s2,"") | "error") write(s1 := ""," ",s2 := "abc.def"," ",check_ext(s1,s2,"") | "error") write(s1 := ""," ",s2 := "abc"," ",check_ext(s1,s2,"") | "error") write("拡張子変更:change_ext 条件反転 test") write(s1 := "def"," ",s2 := "xyz"," ",s3 := "abc.def"," ", change_ext(s1,s2,s3,"") | "error") write(s1 := "DEF"," ",s2 := "xyz"," ",s3 := "abc.def"," ", change_ext(s1,s2,s3,"") | "error") write(s1 := "def"," ",s2 := "xyz"," ",s3 := "abc.DEF"," ", change_ext(s1,s2,s3,"") | "error") write(s1 := "def"," ",s2 := "xyz"," ",s3 := "abc.txt"," ", change_ext(s1,s2,s3,"") | "error") write(s1 := ""," ",s2 := "xyz"," ",s3 := "abc.def"," ", change_ext(s1,s2,s3,"") | "error") write(s1 := ""," ",s2 := "xyz"," ",s3 := "abc"," ", change_ext(s1,s2,s3,"") | "error") end -----$ EXT~.ICN ( lines:52 words:296 ) ---------------------<cut here ext~.exeの結果です。 -----^ EXT~ ( date:97-10-30 time:00:53 ) -------------------<cut here 拡張子チェック:check_ext test def abc.def abc.def DEF abc.def abc.def def abc.DEF abc.DEF def abc error abc.def error abc abc 拡張子変更:change_ext test def xyz abc.def abc.xyz DEF xyz abc.def abc.xyz def xyz abc.DEF abc.xyz def xyz abc.txt error xyz abc.def error xyz abc abc.xyz 拡張子チェック:check_ext 条件反転 test def abc.def error DEF abc.def error def abc.DEF error def abc abc abc.def abc.def abc error 拡張子変更:change_ext 条件反転 test def xyz abc.def error DEF xyz abc.def error def xyz abc.DEF error def xyz abc.txt abc.xyz xyz abc.def abc.xyz xyz abc error -----$ EXT~ ( lines:28 words:86 ) --------------------------<cut here ということで、やっと次回 CSVデータを 表形式データに 変更する programが まとまります。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: Blow by Blow / Jeff Beck (icon_356.txt 1997/10/30 PCVAN PIG) ■ Icon > Icon迷い道(7)CSV:CSV2TB 風つかい 目次 さて、CSVデータを表形式データへ変換する programのまとめです。 CSVデータのファイルから、1行ずつデータを読込んで、CSVデータを表形式データ に変換して、書き出していきます。 -----^ CSV2TB.ICN ( date:97-10-26 time:21:08 ) -------------<cut here #################### # CSV(comma区切りデータ)を 表形式に変換 #################### # csv2tb.icn Rev.1.2 1997/10/26 windy .cfg変換指定をtableからlistへ変更 # csv2tb.icn Rev.1.1 1997/08/26 windy .cfg変換指定方式へ変更、名称変更 # csv2tbl.icn Rev.1.1 1994/11/03 windy 風つかい H.S. # Usage : csv2tb [format] input.csv # format例 : "s14 s0 n4" # command lineの format指定が無い場合は current directoryの # csv2tb.cfgにて format指定されているものと見なす。 # SA=s14 s0 n4 # 指定のやり方 : s14 :文字列 12桁、n4 :数字 4桁。 s0 :その欄は無視 # 変換後のデータは、input.txtというファイルへ出力される。 # This file is in the public domain. link string_e, # cn_split file_e # get_inil, change_ext, key_check procedure main(args) # argsは command line引数(list)。 # 名前は args以外でも良い。 Usage := (map(f_name()) || " s14 s0 n4 input.csv") #↑map()は、デフォルトでは、大文字→小文字変換 new_ext := "txt" # 表形式へ変換したデータのファイルの拡張子指定 # 引数チェック case *args of { # *argsは、argsのサイズを示す。ここでは引数の数。 0 : stop(Usage)# 引数エラー 1 : { # 変換指定が command lineに無いので、.cfgを読み込む。 f_csv := map(args[-1],&lcase,&ucase) # [-1]は最後の要素を指定 # ↑英大文字へ変換 L_cfg := get_inil("CFG") | stop("cannot open .CFG file") # ↑定義 file読込み form := cn_split(key_check(L_cfg,f_name(f_csv))) # テキスト変換指定 # ↑ #↑ csvファイルの名前の先頭で、cfgファイルのどの指定を # | # 使うか判断する。 # |data変換指定を listへ変換 } default : { # ファイル指定以外の引数を formにセット。 f_csv := args[-1] form := args[1:-1] } # ↑[1:-1]は、最初の要素から最後の要素までの範囲指定 } # open files intext := open(f_csv) | stop("cannot open ",f_csv) # 拡張子が "csv" ならば、new_txtへ変換したものを、出力ファイル名とする。 outtext := open(f_new := change_ext("csv",new_ext,f_csv),"a") | stop("file error") write(&errout,f_csv," -> ",f_new) # 動作モニター # display form data # every writes(&errout," ",!form) ; write(&errout) # main no := 0 # モニター用表示の行番号初期値 while line := read(intext) do { # ファイルを1行ずつ読み込み、 write(outtext,csv2tb(line,form)) # form指定に従い変換 writes(&errout," ",right(no +:= 1,4)) # モニター用表示 } write(&errout,"") # カーサー復帰 # close files (無くても動く) close(intext) close(outtext) end #################### # csvデータ1行変換 procedure #################### # args : [1]: string csvデータ(1行)、[2]: list 変換指定文字+桁の list、 # [3]: 桁揃え追加文字 # value: string 表形式に変換された文字列(1行) procedure csv2tb(line,form,s_fill) /s_fill := " " # 指定が無ければ、spaceと見なす。 # 原データ中の spaceと桁揃えのために付加する spaceを区別を # する時使用。例えば、データ中の " "を "_"とかに変換する。 if line[1] == "#" then { # 行の先頭が "#"ならコメント行 return line } l_list := split_csv(line) # 行データを、","区切りで、listに変換。 ################## # 指定桁合わせ ################## i := 1 # 欄番号 s_line := "" # 文字列足し込み用の空文字列 while i <= *form do { # 変換指定の数分、ループ if not (form[i][2:0] == "0") then { # 0桁指定でなければ if form[i][1] == "s" # 文字列指定だったら、左詰め then s_line ||:= (left(map(string(l_list[i])," ",s_fill), form[i][2:0]) || " ") # 数字指定だったら、右詰め else s_line ||:= (right(l_list[i],form[i][2:0]) || " ") } i +:= 1 } return s_line[1:-1] # 末尾の spaceの つけ過ぎを削除。 end #################### # csvデータを listに変換 #################### # args : string csvデータ(1行) # 文字列データは 両端を \" で囲まれているものとする。 # 文字列中の \"は、\"\"で表わされているものとする。 # value: list 欄データを順に listに詰めたもの # 備考 : 3状態の状態遷移マシン state : "init": 初期状態, # "string":文字列処理状態, "number":数字処理状態 procedure split_csv(line) state := "init" # 動作状態管理変数に、初期状態をセット # "string":文字列処理状態, "number":数字処理状態 L := [] # 戻り値用 空 list line ? { repeat { # write(&errout,&pos," ",state) case state of { "init" : { # 初期状態 buf := "" # 文字列足し込み用バッファー初期化 s := move(1) | fail # 次の1文字を get if s == "\"" # stringデータの始め記号なら then state := "string" # 状態 -> 文字列処理 else { state := "number" # 状態 -> 数字処理 move(-1) # &pos戻し } } "number" : { # 数字データ処理状態 put(L,tab(upto(',') | 0)) # 次の ","迄の文字列を list Lに追加 move(1) | break # skip "," または行末でループを抜ける。 state := "init" # 状態 -> 初期状態 } "string" : { # 文字列データ処理状態 buf ||:= tab(upto("\"")) # 次の "\""迄の文字列を bufに追加 move(1) # skip \"(必ずあるはず。) if (s := move(1)) # 行末チェック then { # 行末でなければ if s == "," # データ区切り記号 then { # 前の \"は、stringの終わりだった。 put(L,buf) # bufの内容を listへ追加 state := "init" # 状態 -> 初期状態 } else { # 前の \"は、escapeだった。 buf ||:= s # bufに足し込み state := "string" # 状態 -> 文字列処理 } } else { # 行末なのでループを抜ける。 put(L,buf) # bufの内容を listへ追加 break } } default : stop("state error") # ここへは、来ないハズ。 } } } return L end -----$ CSV2TB.ICN ( lines:162 words:594 ) ------------------<cut here 動作は、コメントでお分かりいただけるかと思います。 link指定は、これまで作った procedureを指定しているのですが、 私の libraryに合わせた指定となっています。 お試しの時は、適当に修正をお願い します。(手抜きだな〜。汗) 次回は、表形式データを、CSV形式データに変換する programを作ります。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: Sun & Moon/岡本真夜 (icon_357.txt 1997/10/31 PCVAN PIG) ■ Icon > Icon迷い道(8)CSV:CSV2TB 風つかい 目次 さて、今回は、表形式データを CSVデータへ変換する programです。この program でも、定義ファイルを使いますが、次のような形式です。 -----^ TB2CSV.CFG ( date:97-10-26 time:21:20 ) -------------<cut here #################### # 表データ -> csvファイル変換指定ファイル #################### # 行頭が "#"あるいは行に "="が含まれ無いなら、無視。(コメント) # 処理対象ファイル名の先頭文字にて、処理指定を識別する。 # ファイル識別文字("="の手前の文字)は、英字大文字。 # 変換指示は、 # s: 文字データ先頭指示、n: 数字データ先頭指示、d: 削除データ先頭指示 #################### # テスト用サンプルデータ #なかやまみほ 中山美穂 1970 3 1 O 158 80 60 84 45 東京都小金井 SAM=s ds dn dn dn dsdn dn dn dn dn ds -----$ TB2CSV.CFG ( lines:13 words:47 ) --------------------<cut here 上の定義ファイルの場合に、変換指示の文字の位置を検出する必要があります。 ということで、早速その procedureです。 1行の表データ CSVデータへ変換する programも Test programとして含んでいます。 show_wlは、以前紹介しました 2重 list表示 procedure、replaceは BIPLに含まれる procedureです。 -----^ CP_SPLIT.ICN ( date:97-10-31 time:00:09 ) -----------<cut here #################### # 表形式データ→CSVデータ変換 programの習作 #################### # cp_split.icn 1997/10/31 windy comment修正 # cp_split.icn 1997/08/25 windy 風つかい H.S. link view_e, # show_wl strings # replace procedure main() #0 0 0 00 1 1 2 2 2 3 #1 5 7 89 1 5 3 5 9 1 s1 := "地球 E 115256ちきゅうはまるい" s2 := "s d sdnn n s d s d " write(s1,"\n",s2) write(right("",*s1,"1234567890")) L := cp_split(s2) show_wl(L) # 2重 list 表示 # csv変換の例 ss := "" every i := 1 to *L do { ss ||:= case (LL := L[i])[1] of { "s" : { "\"" || replace(s1[LL[2]:LL[3]],"\"","\"\"") || "\"\," } "n" : { s1[LL[2]:LL[3]] || "\," } # "d" の部分は無視する。 } } write(ss[1:-1]) end #################### # 文字列処理指定の文字列を解析 #################### # 処理指定 英文字1文字 # args : c : cset(処理指定1バイト文字セット) # s : 指定文字列 # value: 2重 list(処理指定を順に詰めたもの) # [1]:指定文字, [2]:開始位置, [3]:次の指定文字の開始位置 # 指定例 0 0 0 00 1 1 2 2 2 3 # 1 5 7 89 1 5 3 5 9 1 # s1 := "地球 E 115256ちきゅうはまるい" # s2 := "s d sdnn n s d s d " # s2を [["s",1,5],["d",5,7], ... ,["d",29,31]] と変換する。 # 備考 : 表データの整形( csv変換、等)のプログラムのために作成 # 上の例の用に、データ例と並べて指定が可能なプログラムにするため procedure cp_split(s,c) /s := &subject # default /c := &letters # 英文字の大文字・小文字のセット L := [] # 戻り値用 list s ? { tab(ps := upto(c)) # c迄スキップ move(1) # その文字をスキップ while tab(upto(c)) do { # 次の c迄スキップし、 put(L,[s[ps],ps,&pos]) # 文字、開始位置、次の文字の開始位置 # を list に追加 ps := &pos # ps更新 move(1) # その文字をスキップ } put(L,[s[ps],ps,*s+1]) # 残りの部分を処理 } return L end -----$ CP_SPLIT.ICN ( lines:63 words:253 ) -----------------<cut here cp_split.exeの実行結果です。 -----^ CP_SPLIT ( date:97-10-31 time:00:11 ) ---------------<cut here 地球 E 115256ちきゅうはまるい s d sdnn n s d s d 123456789012345678901234567890 s 1 5 d 5 7 s 7 8 d 8 9 n 9 10 n 10 12 n 12 15 s 15 23 d 23 25 s 25 29 d 29 31 "地球","E",1,15,256,"ちきゅう","まる" -----$ CP_SPLIT ( lines:16 words:46 ) ----------------------<cut here というところで、まとめです。 -----^ TB2CSV.ICN ( date:97-10-26 time:21:16 ) -------------<cut here #################### # 表形式データを CSV(comma区切りデータ)に変換 #################### # tb2csv.icn Rev.1.2 1997/10/26 windy .cfg変換指定をtableからlistへ変更 # tb2csv.icn Rev.1.1 1997/08/26 windy .cfg変換指定方式へ変更、名称変更 # tbl2csv.icn Rev.1.1 1994/10/30 windy 風つかい H.S. # Usage : tb2csv input.txt # tb2csv.cfgにて format指定を行う。 #なかやまみほ 中山美穂 1970 3 1 O 158 80 60 84 45 東京都小金井 #SA=s ds dn dn dn dsdn dn dn dn dn s # 変換後のデータは、input.csvというファイルへ出力される。 # This file is in the public domain. link string_e, # cp_split file_e # get_inil, change_ext, key_check procedure main(args) # argsは command line引数(list)。 # 名前は args以外でも良い。 Usage := (map(f_name()) || " input.txt") #↑map()は、デフォルトでは、大文字→小文字変換 new_ext := "csv" # 表形式へ変換したデータのファイルの拡張子指定 # 引数チェック if *args ~= 1 then stop(Usage) # 引数エラー f_txt := map(args[1],&lcase,&ucase) # ↑英大文字へ変換 # config file読み込み L_cfg := get_inil("CFG") | stop("cannot open .CFG file") # テキスト変換指定 form := cp_split(key_check(L_cfg,f_name(f_txt))) # ↑ #↑ csvファイルの名前の先頭で、cfgファイルのどの指定を # | # 使うか判断する。 # |data変換指定を listへ変換 # open files intext := open(f_txt) | stop("cannot open ",f_csv) # 拡張子が、"csv"で無ければ、"csv"を変換後のファイル名とする。 outtext := open(f_new := change_ext("csv",new_ext,f_txt,""),"a") | stop("file ext error") #↑反転条件 write(&errout,f_txt," -> ",f_new) # 動作モニター # display form data # every writes(&errout," ",!form) ; write(&errout) # main no := 0 # モニター用表示の行番号初期値 while line := read(intext) do { # ファイルを1行ずつ読み込み、 write(outtext,tb2csv(line,form)) # form指定に従い変換 writes(&errout," ",right(no +:= 1,4)) # モニター用表示 } write(&errout,"") # カーサー復帰 # close files (無くても動く) close(intext) close(outtext) end #################### # 表データ -> csvデータ1行変換 procedure #################### # args : [1]: string 表データ(1行)、[2]: list 変換指定(2重 list) # value: string csv形式に変換された文字列(1行) procedure tb2csv(s,L) ss := "" every i := 1 to *L do { ss ||:= case (LL := L[i])[1] of { "s" : { "\"" || replace(s[LL[2]:LL[3]],"\"","\"\"") || "\"\," } "n" : { s[LL[2]:LL[3]] || "\,"} # "d" の部分は無視する。 } } return ss[1:-1] end #↑最後の余分な "\,"を削除 -----$ TB2CSV.ICN ( lines:73 words:275 ) -------------------<cut here 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: Sun & Moon/岡本真夜 (icon_358.txt 1997/10/31 PCVAN PIG) ■ Icon > ちょっと Icon(1)data整形 風つかい 目次 (niftyserveの FGALTSに「AWK天国/なんだ簡単じゃねえか!」という会議室が ありますが、そこで data整形の話題が でました。 それをネタに FGALTSの「スクリプト天国/何でもかんでも」の会議室で、 Iconの紹介を したものです。) 次のような dataを -----^ TEST03.DAT ( date:97-05-17 time:13:32 ) -------------<cut here 1,相川 七瀬 1,安室 奈美恵 3,大黒 摩季 3,岡本 真夜 3,尾崎 亜美 3,辛島 美登里 7,篠原 ともえ 7,篠原 美也子 7,篠原 涼子 10,竹内 まりあ 10,中島 みゆき 10,中山 美穂 10,中村 あゆみ 10,久松 史奈 10,松任谷 由美 10,森川 美穂 10,山下 久美子 18,遊佐 未森 -----$ TEST03.DAT ( lines:18 words:36 ) --------------------<cut here 次のように、整形します。 先頭の数字が変わったら改行、1行の dataは、 3つまで、オリジナル dataの先頭の数字は、整形後は先頭にだけ。 -----^ SHAPE01 ( date:97-05-17 time:16:08 ) ----------------<cut here 1,相川 七瀬,安室 奈美恵 3,大黒 摩季,岡本 真夜,尾崎 亜美 3,辛島 美登里 7,篠原 ともえ,篠原 美也子,篠原 涼子 10,竹内 まりあ,中島 みゆき,中山 美穂 10,中村 あゆみ,久松 史奈,松任谷 由美 10,森川 美穂,山下 久美子 18,遊佐 未森 -----$ SHAPE01 ( lines:8 words:26 ) ------------------------<cut here という風に、整形するというのが、仕様です。) AWK部屋で、1行データを 3個づつまとめる データ整形の話題が、出ました が、Iconでやったらどんな風になるか、ちょっと、ご覧にいれようと思います。 まず、AWKのスクリプトは、大体こんな風になります。 -----^ SHAPE01.AWK ( date:97-05-16 time:19:52 ) ------------<cut here # N個 区切りスクリプト # shape01.awk Rev.1.2 1997/05/16 windy printf 引数修正 # shape01.awk Rev.1.1 1997/05/14 windy # Usage: jgawk -f shape01.awk data_file >kekka # data sample(/line) : 1,"A" # This file is in the public domain. BEGIN{ FS = "," # 行内の data区切りを ","に変更 No = 0 # データ種別番号 n = 1 # (同一データ種別番号の)データ個数カウンタ N = 3 # 区切り数 } { if($1 != No){ # data種別 Noが変わったら No = $1 # data種別 No更新 if(n % N != 1 ){ print ""} # top dataで無ければ、改行出力 n = 1 # data個数 reset } if(n % N == 1) { # N個 区切りの先頭ならデータ種別 No出力 # printf($1) # printf($1 FS $2) # Rev1.2 } # printf(FS $2) # printf(FS $3 FS $4) # Rev1.2 if(n % N == 0) { print ""} # N個 区切り数最後なら、改行出力 n++ # data数カウントアップ } END{ if(n % N != 1) { print ""} # 最後の行が N個でなければ、改行出力 } -----$ SHAPE01.AWK ( lines:33 words:147 ) ------------------<cut here これを、Iconで書くと、次のようになります。 関数名・演算子記号以外は 殆ど、変わりません。 (programの後ろの方に関数・演算子記号の解説をつけました。) 尚、AWKでは、command line 引数に file名を 指定すると、自動的に その fileを オープンして、data fileとして、読み込んでくれます。 Iconは、自動的には、やりません。 programで fileをオープンします。 また、AWKでは、行を 自動的に FSで分割して、配列に してくれますが、 Iconは やりませんので、必要なら その処理を行う procedureを作成して linkする必要が、あります。 逆に言えば、Iconでは、行をどう料理しようが、programする人の自由です。 -----^ SHAPE01.ICN ( date:97-05-17 time:13:11 ) ------------<cut here # N個 区切りプログラム # shape01.icn 1997/05/16 windy # Usage: shape01 data_file >kekka # data sample(/line) : 1,"A" # shape01.awk を、そのまま、Iconに移し変えたもの。 # This file is in the public domain. link split6 procedure main(args) # ↑command line 引数 (list) Usage := "shape01 data_file >kekka" # command line 引数チェック(引数が無ければ使用方法表示) if *args = 0 then stop(Usage) # data fileオープン(エラーならエラー表示) dir := open(args[1]) | stop("cannot open ",args[1]) # ↑command line引数の1番目 fs := '\,' # 行内の data区切り No := 0 # データ種別番号 n := 1 # (同一データ種別番号の)データ個数カウンタ N := 3 # 区切り数 while line := read(dir) do { # 1行づつ順次読み込んで、 L := split(line,fs) # fsにて dataを分割して、listへ if numeric(L[1]) ~= No then { # データ種別 Noが変わったら if (n % N) ~= 1 then write() # top dataで無ければ、改行出力 No := numeric(L[1]) # データ種別 No更新 n := 1 # data個数 reset } if (n % N) = 1 then writes(No) # N個 区切りの先頭ならデータ種別 No出力 # if (n % N) = 1 then writes(No,fs,L[2]) # writes(fs,L[2]) # データ出力 # writes(fs,L[3],fs,L[4]) # データ出力 if (n % N) = 0 then write() # N個 区切り数最後なら、改行出力 n +:= 1 # data数カウントアップ } if (n % N) ~= 1 then write() # 最後の行が N個でなければ、改行出力 end # 解説 # *args : argsの size(この場合は、引数の個数) # stop(s) : 文字列 sを出力して、programを stopする関数 # read() : text-mode file 読み込み関数 # numeric : 文字→数字変換関数 # = : 数字の比較 # := : 代入 # +:= : n +:= m は、 n := n +m の略記 # ~ : 否定 # writes : printf 相当(改行無し出力) # write : print 相当(改行付き出力) # "abc" : 文字列 abc # 'xyz' : 'x' 'y' 'z' を要素とする集合 # L[3] : L (list)の 3番目の要素 # link : 他の fileの procedureを linkする指定 -----$ SHAPE01.ICN ( lines:57 words:273 ) ------------------<cut here linkする xplit06.icnがあふれましたので、続きは、次回に。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: Vivien/篠原美也子 (nif0516a.txt 1997/05/16 niftyserve fgalts, 1997/05/17 PCVAN SLABO) ■ Icon > ちょっと Icon(2)data整形 風つかい 目次 1行データを 3個づつまとめる データ整形 の お話しの続きです。 前回の programで使っている 文字列分割の procedureです。 -----^ SPLIT6.ICN ( date:97-05-17 time:13:09 ) -------------<cut here # 文字列分割→list格納 procedure # split6.icn Rev.1.3 1997/05/17 windy comment修正 # split6.icn Rev.1.1 1997/05/14 windy # icont -c split6.icn とすると、split6.u1,split6.u2という中間言語 fileが # できる。この形にしておくと、他の procedureから linkできる。 # Usage: L := split(line,c) # This file is in the public domain. # Icon入門講座(5)あたりに詳しい説明があります。 # arg : [1]:文字列, [2]:文字(集合) # value : list procedure split(line,c) /c := ' \t' # 引数に cがセットして無ければ、spaceか tab list := [] # 出力 data足しこみ用 空 list line ? { # lineを、走査対象として # ↓くり返し while tab(upto(~c)) do # c以外の文字へ 走査位置を移動 put(list,tab(many(~c))) # c以外の文字以外の文字(すなわち c)まで } # 走査位置を移動。 移動した間の文字列を # listへ格納 return list end # 解説 # /c : c が null(未定義)ならば # 'ab' : 文字 aと、文字 b を要素とする集合 # while ... do : ...を繰り返す。 # tab(n) : nの位置まで、走査位置を移動。この関数の値は、移動した部分の # 文字列となる。 # upto(c) : 走査対象の文字列 の中で、現在の走査位置以降で、文字集合 cの # 中の いずれかの文字が 現れる位置。 位置が複数ある場合は、順 # 次その位置を見つける。(すなわち、generator) # many(c) : 現在の走査位置以降で、文字集合 cに含まれる文字 以外の文字が # 現れる位置 # put(L,x): L(list)の末尾に xを追加する。 -----$ SPLIT6.ICN ( lines:36 words:144 ) -------------------<cut here 細かく解説しますと、Icon入門講座に書いた内容を、全部説明しないと、 いけなくなります。 program中の commentで、ご想像を お願いします。 しかし AWKと同じ機能だけでは、面白く無いので、次回は、少しいじって みましょう。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: Vivien/篠原美也子 (nif0516b.txt 1997/05/16 niftyserve fgalts, 1997/05/17 PCVAN SLABO) ■ Icon > ちょっと Icon(3)data整形 風つかい 目次 1行データを 3個づつまとめる データ整形 の お話しの続きです。 前の programに Iconの機能を、多少ちりばめてみます。 でも、同じ機能の programですから、動いた結果は同じです。(汗) ・読み込んだ dataの各行の分割のところで、最初の ","で、行データを分割す るプログラムにします。 ・行データを、table(AWKの連想配列)に格納します。 (格納する必要は 無いのですが、tableのサンプルとして。) そうしますと、AWKの連想配列と同じく、取り出すときに、格納した順番とは なりません。 そこで、tableに格納した dataを keyで sortして出力します。 tableは sortすると、listになります。( dataに順番を与えるには、listに しないといけないので、Iconの言語仕様が そうなっています。) ・出力処理で、Iconでは、せっかく case構文が、サポートされています ので、使ってみます。 多少、動作が分かりやすくなると思います。 ・整形結果を 出力した後に、使った tableと listの構造が どうなってい るかを、x2tという procedureを使って書き出します。(これは、参考用 です。本来の動作とは関係ありません。) x2tを説明しますと、 Icon入門講座1〜3全部を、説明しないといけなく なりますので、まあ そういう機能の procedureだと、 ここでは、考えて 下さい。(Icon入門講座3(19)の x2tree03 にミス修正(汗)と機能 アップ(tableの場合 valueだけでなく keyも出力するように) したもの です。) -----^ SHAPE02.ICN ( date:97-05-17 time:10:17 ) ------------<cut here # N個 区切り program # shape02.icn Rev.1.2 1997/05/17 windy comment修正 # shape02.icn Rev.1.1 1997/05/16 windy # Usage: shape02 data_file >kekka # data sample(/line) : 1,"A" # This file is in the public domain. link x2tree06 procedure main(args) Usage := "shape02 data_file >kekka" if *args = 0 then stop(Usage) dir := open(args[1]) | stop("cannot open ",args[1]) fs := '\,' # 行内の data区切り N := 3 # 区切り数 T1 := table() # tableを生成(初期値 無し) while line := read(dir) do { # 1行づつ順次読み込んで、 line ? { # lineを走査対象として ps := upto(fs) # ps : lineの中で、最初に fsが見つかった位置 n := numeric(line[1:ps]) # lineの psより前の部分を数字変換 s := line[ps+1:0] # lineの psより後の部分 /T1[n] := [] # table T1の keyに、nが無ければ、nを key # として valueに [] (空 list)を 登録 put(T1[n],s) # tableの key n の value (list)に sを追加 } } L1 := sort(T1,1) # T1 を keyで sortし、 listへ変換 write("整形結果") every L2 := !L1 do { # L1から、要素(list) を順次取り出して No := L2[1] # 1番目の要素(数字)を Noに代入 n := 0 # 同じ Noの要素のカウンタ every s := !L2[2] do { # 2番目の要素(list) から要素(文字列)を # 順次取り出して n +:= 1 # 同じ Noの要素のカウンタ +1 case (n % N) of { # nを Nで割った余りによって 1 : { writes(No) # No出力 writes(fs,s) } # データ出力 2 : writes(fs,s) 0 : { writes(fs,s) write() } # 改行出力 default : stop("case error") # それ以外だったら } } if (n % N) ~= 0 then write() # 最後の出力行の要素数が、N以外だったら } # 改行出力 # 動作参考用 write("\nT1 (table) 構\造") # "構" は "\x8d5c" なので、"\x5c"を補う。 every write(x2t(T1)) # x2tは 構造体の内容を tree表示する procedure # x2tree06.icnに含まれる。 write("\nL1 (list) 構\造") every write(x2t(L1)) end # 解説 # /T1[n] : T1[n]の null (未定義) check # table : table(AWKの連想配列)を生成 ()内には、初期値を指定できる # every ... !L : 構造体 Lの要素を順次取り出して -----$ SHAPE02.ICN ( lines:61 words:277 ) ------------------<cut here 動かした時の結果です。 -----^ SHAPE02 ( date:97-05-17 time:18:12 ) ----------------<cut here 整形結果 1,相川 七瀬,安室 奈美恵 3,大黒 摩季,岡本 真夜,尾崎 亜美 3,辛島 美登里 7,篠原 ともえ,篠原 美也子,篠原 涼子 10,竹内 まりあ,中島 みゆき,中山 美穂 10,中村 あゆみ,久松 史奈,松任谷 由美 10,森川 美穂,山下 久美子 18,遊佐 未森 T1 (table) 構造 <table 1> + <list 6> <- integer18 | + string "遊佐 未森" + <list 5> <- integer10 | + string "竹内 まりあ" | + string "中島 みゆき" | + string "中山 美穂" | + string "中村 あゆみ" | + string "久松 史奈" | + string "松任谷 由美" | + string "森川 美穂" | + string "山下 久美子" + <list 4> <- integer7 | + string "篠原 ともえ" | + string "篠原 美也子" | + string "篠原 涼子" + <list 2> <- integer1 | + string "相川 七瀬" | + string "安室 奈美恵" + <list 3> <- integer3 + string "大黒 摩季" + string "岡本 真夜" + string "尾崎 亜美" + string "辛島 美登里" L1 (list) 構造 <list 7> + <list 9> | + integer1 | + <list 2> | + string "相川 七瀬" | + string "安室 奈美恵" + <list 8> | + integer3 | + <list 3> | + string "大黒 摩季" | + string "岡本 真夜" | + string "尾崎 亜美" | + string "辛島 美登里" + <list 10> | + integer7 | + <list 4> | + string "篠原 ともえ" | + string "篠原 美也子" | + string "篠原 涼子" + <list 11> | + integer10 | + <list 5> | + string "竹内 まりあ" | + string "中島 みゆき" | + string "中山 美穂" | + string "中村 あゆみ" | + string "久松 史奈" | + string "松任谷 由美" | + string "森川 美穂" | + string "山下 久美子" + <list 12> + integer18 + <list 6> + string "遊佐 未森" -----$ SHAPE02 ( lines:71 words:285 ) ----------------------<cut here 次回、もう少し、いじってみます。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: Vivien/篠原美也子 (nif0516b.txt 1997/05/16 niftyserve fgalts, 1997/05/17 PCVAN SLABO) ■ Icon > ちょっと Icon(4)data整形 風つかい 目次 相変わらず、1行データを 3個づつまとめる データ整形 の お話しの 続きです。 前回の programの出力部分に generatorを使ってみます。 generatorと いうのは、procedureで、複数の結果を、順次返す機能 を、持っている ものを言います。 でも、全体は、同じ 機能の programですから、 動いた結果も、相変わ らず 同じです。(笑) -----^ SHAPE03.ICN ( date:97-05-17 time:10:46 ) ------------<cut here # N個 区切り program # shape03.icn Rev.1.3 1997/05/17 windy comment修正 # shape03.icn Rev.1.1 1997/05/15 windy # Usage: shape03 data_file >kekka # data sample(/line) : "1","A" # This file is in the public domain. link retrieve procedure main(args) Usage := "shape03 data_file >kekka" if *args = 0 then stop(Usage) # command line 引数 check dir := open(args[1]) | stop("cannot open ",args[1]) # file open # 初期設定 fs := '\,' # 行内の data区切り N := 3 # 区切り数 T1 := table() # 空の tableを生成 # data fileを読み込み tableに格納 (tableは AWKの連想配列と同じ) while line := read(dir) do { # 1行づつ順次読み込んで、 line ? { # 読み込んだ 行を 走査対象として ps := upto(fs) # 最初の fsの位置を得る n := numeric(line[1:ps]) # fsより前が n (numeric :文字→数字変換) s := line[ps+1:0] # fsより後が s /T1[n] := [] # T1に nが keyとして存在しないなら # T1に nを keyとして、空 listを登録 put(T1[n],s) # tableの key n の value (list)に sを追加 } } L1 := sort(T1,1) # T1を keyで sort(結果は listの list) write("整形結果") every L2 := !L1 do { # L1の要素を 順次取り出して No := L2[1] # data種別 No every L3 := retrieve(L2[2],3) do { # L2[2]の要素を 3個づつ取り出す。 writes(No) # data種別 No を出力 every writes(fs,!L3) # L3の要素を 順次出力 write() } } end -----$ SHAPE03.ICN ( lines:43 words:194 ) ------------------<cut here generatorです。 shape03.icnから、3個区切りでデータを返す指定で 呼ばれています。 -----^ RETRIEVE.ICN ( date:97-05-17 time:10:48 ) -----------<cut here # x(list または string)の要素を n個区切りにして、部分 list(またはstring) # を、順次返す generator # 元の listは保存 # Usage: every XX := retrieve(X) do {...} # retrieve.icn Rev.1.2 1997/05/17 windy comment修正 # retrieve.icn Rev.1.1 1997/05/16 windy # This file is in the public domain. # link retr # test用 procedure retrieve(X,n) /n := 1 # default every m := 1 to *X by n do { # mを 1から n飛びで 順次増加させて suspend \X[m+:n] # listの m番目の要素から n個要素が # 存在すれば それを値として返す。 } suspend X[(*X -n+1) < \m :0] # n個区切りで、余った要素を返す。 end # 解説 # *X : Xの size(要素数または長さ) # /n : /は nが null(指定が無い時)の check。 存在すればその値を持つ。 # X[m+:n] : list(または string)の mの位置から n個分の部分。 # \X[m+:n] : \は X[m+:n]が、存在すればという check。存在すればその値を持つ。 # \mも同様に mの値が存在すれば、その値を持つ。 # suspend : 複数の値を返す return # a < b : 数字比較 a < b が成立すれば、bを値として持つ。 -----$ RETRIEVE.ICN ( lines:27 words:131 ) -----------------<cut here programだけで、余り説明の無い 書きこみでしたが、 ・なかなか 変わった programだから、一度動かしてみよう。 とか ・機能が 色々ありそうだから、試してみよう。 とか お考えの方が いらっしゃると うれしいです。 おまけに、retrieve.icnの test programを付けておきます。 -----^ RETR.ICN ( date:97-05-17 time:19:23 ) ---------------<cut here # retrieve.icnの test procedure # retr.icn Rev.1.3 1997/05/17 windy comment修正, test case 追加 # retr.icn Rev.1.2 1997/05/16 windy stringの testc ase追加 # retr.icn Rev.1.1 1997/05/16 windy # test時は、retrieve.icnが、この procedureを linkする。 # This file is in the public domain. link show_l procedure main() # test data L0 := [] L1 := ["A1"] L2 := ["A2","B2"] L3 := ["A3","B3","C3"] L4 := ["A4","B4","C4","D4"] L5 := ["A5","B5","C5","D5","E5"] L6 := ["A6","B6","C6","D6","E6","F6"] # test every L := retrieve(L0,2) do show_sl(L) ; write() every L := retrieve(L1,2) do show_sl(L) ; write() every L := retrieve(L2,2) do show_sl(L) ; write() every L := retrieve(L3,2) do show_sl(L) ; write() every L := retrieve(L4,2) do show_sl(L) ; write() every L := retrieve(L5,2) do show_sl(L) ; write() every L := retrieve(L6,2) do show_sl(L) ; write() # test case 追加 Rev.1.2 s0 := "" s1 := "A" s2 := "AB" s3 := "ABC" s4 := "ABCD" s5 := "ABCDE" s6 := "ABCDEF" every writes(" ",retrieve(s0,2)) ; write() every writes(" ",retrieve(s1,2)) ; write() every writes(" ",retrieve(s2,2)) ; write() every writes(" ",retrieve(s3,2)) ; write() every writes(" ",retrieve(s4,2)) ; write() every writes(" ",retrieve(s5,2)) ; write() every writes(" ",retrieve(s6,2)) ; write() # Rev.1.3 追加 end -----$ RETR.ICN ( lines:45 words:189 ) ---------------------<cut here 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: Vivien/篠原美也子 (nif0516c.txt 1997/05/16 niftyserve fgalts, 1997/05/17 PCVAN SLABO) ■ Icon > Icon回り道(1)重複しないランダムな 10個の数 風つかい 目次 (PCVANの SLABOで、乱数の話題がでていました。Iconで乱数をつかったこと がありませんでしたので、話題に相乗りして Iconでもやってみました。 テーマは、3桁の重複しない乱数を得る、というものです。) ということで、私も Iconの乱数機能を 使ったことが、ありませんでした ので、どういう programになるか やってみました。。 Iconでは、?10 と書きますと、1〜10迄の乱数を発生できます。 正確には 乱数列の最初の数字を得ることができます。 同じ program内で、次にこの式 (?10) を 実行すると、乱数列の2番目の 数字が得られます。 ちなみ、文字列では、?"ABCDEFG" と書くと "ABCDEFG"から randomに1文 字(1-byte character)取り出せます。 Iconでは、この乱数列は programを何度実行しても同じ乱数列となります。 違う乱数列を得るためには、keywordの &randomを変えると可能だそうです。 1 〜 n までの randomな数 を m個 発生させる programは次のようになり ます。 -----^ RANDOM01.ICN ( date:97-05-30 time:23:22 ) -----------<cut here # Iconで 1 〜 n までの randomな数 を m個 発生させるテスト # random01.icn 1997/05/30 windy Kazetsukai H.S. # This file is in the public domain. procedure main(args) Usage := "random01 最大値 発生数" # command line引数を 数字に変換して、n(最大値),m(生成数)にセット。 # 数字に変換できなければ、Usageを表示して stop {(n := numeric(args[1])) & (m := numeric(args[2]))} | stop(Usage) #↑前の 2項のどちらか # 失敗したとき every writes(" ",rand(n) \m) # ↑generatorの生成数限定 write() end # 1 〜 n迄の数を生成する generator(順次、値を発生する procedure) procedure rand(n) repeat { suspend ?n } #↑くり返し #↑ #↑ ?nは、1 〜 nの random数を生成 end #suspendは、generatorの場合に使う return -----$ RANDOM01.ICN ( lines:22 words:82 ) ------------------<cut here random01 999 10 とした時の結果です。 何度実行しても同じ数列が出てきます。 (そういう仕様です。) -----^ RANDOM01 ( date:97-05-31 time:13:07 ) ---------------<cut here 212 413 316 510 422 306 80 737 51 717 -----$ RANDOM01 ( lines:1 words:10 ) -----------------------<cut here 生成される数に最少数を設ける には、生成した数がその最少制限数より小さ ければ無視する というやり方が あります。 そのやり方でやりますと、 -----^ RANDOM02.ICN ( date:97-05-31 time:13:12 ) -----------<cut here # Iconで 1 〜 n までの randomな数 を m個 発生させるテスト # ★ l 以上の値のものだけという制限付き # random02.icn 1997/05/31 windy Kazetsukai H.S. # This file is in the public domain. procedure main(args) Usage := "random01 最大値 発生数 最小値" {(n := numeric(args[1])) & (m := numeric(args[2])) & (l := numeric(args[3])) } | stop(Usage) #↑前の 3項の いずれかが 失敗したとき every writes(" ",(l <= rand(n)) \m) #↑ a < b は、b が aより大きければ bの値、さもなくば失敗 write() end procedure rand(n) repeat { suspend ?n } end -----$ RANDOM02.ICN ( lines:20 words:78 ) ------------------<cut here random02 999 10 100とした時の結果です。 random01 999 10 100の結果 から、100未満の数字を除いた数列になっています。 -----^ RANDOM02 ( date:97-05-31 time:13:13 ) ---------------<cut here 212 413 316 510 422 306 737 717 138 336 -----$ RANDOM02 ( lines:1 words:10 ) -----------------------<cut here 生成する数の最少値制限の別のやり方です。 制限の値だけ最大値を小さい 範囲で生成しておいて、後で制限の値を足すやり方です。 -----^ RANDOM03.ICN ( date:97-05-31 time:13:14 ) -----------<cut here # Iconで 1 〜 n までの randomな数 を m個 発生させるテスト # ★ 最小値 l の制限の仕方を、ちょっと変更 # random03.icn 1997/05/31 windy Kazetsukai H.S. # This file is in the public domain. procedure main(args) Usage := "random01 最大値 発生数 最小値" {(n := numeric(args[1])) & (m := numeric(args[2])) & (l := numeric(args[3])) } | stop(Usage) every writes(" ", rand(n,l) \m) write() end # 最少値の値だけ、小さな範囲の乱数列を発生させて、後で最小値を足す。 procedure rand(n,l) repeat { suspend ?(n-l+1) +l-1 } end -----$ RANDOM03.ICN ( lines:19 words:69 ) ------------------<cut here random03 999 10 100とした時の結果です。 -----^ RANDOM03 ( date:97-05-31 time:13:14 ) ---------------<cut here 290 471 384 559 479 375 171 763 145 745 -----$ RANDOM03 ( lines:1 words:10 ) -----------------------<cut here ちょっと、長くなりましたので、続きは次へ。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: 河よりも長くゆるやかに/篠原美也子 (pcv0531a.txt 1997/05/31 PCVAN SLABO) ■ Icon > Icon回り道(2)重複しないランダムな 10個の数 風つかい 目次 続きです。 乱数列 program実行の度に、同じ乱数列が出てくるのでは、まずい ときには、乱数の種を 乱数にする procedureが BIPL(Icon基本 library)に 有り ますので、それを linkして、乱数列発生の前に実行します。 -----^ RANDOM04.ICN ( date:97-05-31 time:14:41 ) -----------<cut here # Iconで 1 〜 n までの randomな数 を m個 発生させるテスト # ☆ l 以上の値のものだけ という制限付き。 # ★ 発生する数を 実行する度に 変える。 # random04.icn 1997/05/31 windy Kazetsukai H.S. # This file is in the public domain. link random # BIPLの random.icnを link。randomizeを使用 procedure main(args) Usage := "random01 最大値 発生数 最小値" {(n := numeric(args[1])) & (m := numeric(args[2])) & (l := numeric(args[3])) } | stop(Usage) randomize() # ←乱数の種を変える。 every writes(" ",(l <= rand(n)) \m) write() end procedure rand(n) repeat { suspend ?n } end -----$ RANDOM04.ICN ( lines:22 words:81 ) ------------------<cut here random04 999 10 100 >> random04 を3回実行した時の結果です。 -----^ RANDOM04 ( date:97-05-31 time:14:42 ) ---------------<cut here 915 779 671 354 132 841 951 141 188 431 991 377 762 412 594 935 972 385 197 257 719 544 516 449 344 185 504 279 790 634 -----$ RANDOM04 ( lines:3 words:30 ) -----------------------<cut here おっと、重複しない数という条件もありましたね。 すると 生成した数を覚えておいて、同じ数が出てきたら無視するという処理が 必要になります。 構造体の set (集合)に、生成した順に登録していくやり方を使いますと 次のようになります。 -----^ RANDOM05.ICN ( date:97-05-31 time:13:19 ) -----------<cut here # Iconで 1 〜 n までの randomな数 を m個 発生させるテスト # ☆ l 以上の値のものだけ という制限付き。 # ☆ 発生する数を 実行する度に 変える。 # ★ 重複を避ける。 # random05.icn 1997/05/31 windy Kazetsukai H.S. # This file is in the public domain. link random # BIPLの random.icnを link。randomizeを使用 procedure main(args) Usage := "random01 最大値 発生数 最小値" {(n := numeric(args[1])) & (m := numeric(args[2])) & (l := numeric(args[3])) } | stop(Usage) randomize() # ←乱数の種を変える。 every writes(" ", uniq_rand(n,l) \m) write() end # 重複を避ける procedure procedure uniq_rand(n,l) static S S := set() every nn := rand(n,l) do { if not member(S,nn) then { insert(S,nn) suspend nn } } end procedure rand(n,l) suspend |(?(n-l+1) +l-1) #↑ |は、式の前に付くと、くり返し generatorとなる。 end -----$ RANDOM05.ICN ( lines:36 words:111 ) -----------------<cut here 乱数列の発生のためのくり返し実行の部分も気分で変えています。 repeatの代わりに | という表現を使ってみました。 これは数列・文字列のくり返し発生を指定する式になります。| と数列・文字列 を指定する式の間は空けてはいけません。 | と次の式の間を空けると、 programの前の方の | stop(Usage) のように alternation(左側の式が失敗すると右側の式を実行)になってしまいます。 random05 999 10 100 としたときの結果です。 -----^ RANDOM05 ( date:97-05-31 time:13:18 ) ---------------<cut here 439 469 993 330 931 528 935 653 196 586 -----$ RANDOM05 ( lines:1 words:10 ) -----------------------<cut here あっ、数字を小さい順に出さないといけないんでしたね。 すると sortが必要になります。 前の programで setに数字を登録しましたので、 それを sortして出力します。 setへの登録は、既に前に setに登録されていて も無視されます(上書きなのか、登録されないのか分かりません)ので、その チェックは外しました。 -----^ RANDOM06.ICN ( date:97-05-31 time:01:28 ) -----------<cut here # Iconで 1 〜 n までの randomな数 を m個 発生させるテスト # ☆ l 以上の値のものだけ という制限付き。 # ☆ 発生する数を 実行する度に 変える。 # ☆ 重複を避ける。 # ★ sortして出力 # random06.icn 1997/05/31 windy Kazetsukai H.S. # This file is in the public domain. link random # BIPLの random.icnを link。randomizeを使用 procedure main(args) Usage := "random01 最大値 発生数 最小値" {(n := numeric(args[1])) & (m := numeric(args[2])) & (l := numeric(args[3])) } | stop(Usage) randomize() # ←乱数の種を変える。 every writes(" ", uniq_rand(n,m,l)) write() end # 重複を避ける procedure procedure uniq_rand(n,m,l) static S S := set() while *S < m do insert(S,rand(n,l)) every suspend !sort(S) end procedure rand(n,l) suspend |(?(n-l+1) +l-1) end -----$ RANDOM06.ICN ( lines:32 words:103 ) -----------------<cut here random06 999 10 100 としたときの結果です。 -----^ RANDOM06 ( date:97-05-31 time:13:20 ) ---------------<cut here 241 292 388 400 495 711 896 904 937 969 -----$ RANDOM06 ( lines:1 words:10 ) -----------------------<cut here 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: 河よりも長くゆるやかに/篠原美也子 (pcv0531b.txt 1997/05/31 PCVAN SLABO) ■ Icon > Icon回り道(3)重複しないランダムな 10個の数 風つかい 目次 3桁の数字という条件で、そのものズバリ 文字数が3桁 というやり方を書き落と しました。そういう条件の場合は、次のようになります。 -----^ RANDOM07.ICN ( date:97-06-01 time:23:49 ) -----------<cut here # Iconで 1 〜 n までの randomな数 を m個 発生させるテスト # ★ d桁の数だけという制限付き # random07.icn 1997/06/01 windy Kazetsukai H.S. # This file is in the public domain. procedure main(args) Usage := "random01 最大値 発生数 最小値" {(n := numeric(args[1])) & (m := numeric(args[2])) & (d := numeric(args[3])) } | stop(Usage) #↑前の 3項の いずれかが 失敗したとき every writes(" ", 1(nn := rand(n), *nn = d) \m) # ↑ ↑ *は、桁数(文字数)を表わす。 write() # |2つの式のうち1番目の式の値を値とする指定。 end procedure rand(n) repeat { suspend ?n } end -----$ RANDOM07.ICN ( lines:20 words:79 ) ------------------<cut here rndom07 999 10 2 とした場合の結果です。 -----^ RANDOM07.2 ( date:97-06-01 time:23:50 ) -------------<cut here 80 51 12 88 29 33 53 32 75 64 -----$ RANDOM07.2 ( lines:1 words:10 ) ---------------------<cut here rndom07 999 10 3 とすれば、こうなります。 -----^ RANDOM07.3 ( date:97-06-01 time:23:50 ) -------------<cut here 212 413 316 510 422 306 737 717 138 336 -----$ RANDOM07.3 ( lines:1 words:10 ) ---------------------<cut here 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: そのままの君でいて/岡本真夜 (pcv0601a.txt 1997/06/01 PCVAN SLABO) ■ Icon > Icon回り道(4)Usageが... 風つかい 目次 あれれ、random02.icnから random07.icnまで、全部 Usageのファイル名が random01のままですね。あはは。よくやります。 人手で修正するので、漏れがでますので、プログラム自身で作らせようと こんな procedureを作ってみました。 Iconには、プログラム名称を示す keywordがあります。 &prognameです。 &prognameには、ディレクトリー付きのファイル名が入ります。 Usageでは、ディレクトリーと拡張子は、通常 不要ですので、それを削除 して使います。 top_cut()という procedureで、ディレクトリーを削除して、 top_get()という procedureで、拡張子を除いています。 (参考に &prognameそのものも表示するようにしています。) -----^ EXE_NAME.ICN ( date:97-06-02 time:19:06 ) -----------<cut here # Usageの file名訂正漏れを 防ぐための file名生成 procedure # exe_name.icn 1997/06/02 windy Kazetsukai H.S. # This file is in the public domain. procedure exe_name() write(&progname) # test用 return top_get('.',top_cut('\\',&progname)) end #################### # 文字列の 先頭から特定文字までの部分 を取り去る。最長部分を取り去る。 #################### # arg : cset # value : string # Usage : top_cut(c,s) procedure top_cut(c,s) /s := &subject # sの指定がなければ &subject /c := ' \t' # cの指定がなければ spaceか tab s ? { # sを走査対象とする。 while tab(upto(c)) do tab(many(c)) # cが見つかる限り、走査位置を # その文字の後に移動。 return tab(0) # 残りの文字列を返す。 } end #################### # 文字列の 先頭から特定文字までの部分 を得る。最短部分を得る。 #################### # arg : cset # value : string # Usage : top_get(c,s) procedure top_get(c,s) /s := &subject # sの指定がなければ &subject /c := ' \t' # cの指定がなければ spaceか tab s ? { # sを走査対象とする。 return tab(upto(c) | 0) # cまで走査位置を移動しその間の } # 文字列を返す。cがみつからなけ # れば、末尾まで返す。 end -----$ EXE_NAME.ICN ( lines:40 words:132 ) -----------------<cut here 使用サンプルです。 Usageを表示するだけのプログラムです。 -----^ NAME01.ICN ( date:97-06-02 time:01:46 ) -------------<cut here # Usageの file名の訂正漏れを防ぐための file名生成 procedure # name01.icn 1997/06/02 windy Kazetsukai H.S. # This file is in the public domain. link exe_name procedure main(args) Usage := exe_name() || " なんたらかんたら どうたらこうたら" write(Usage) end -----$ NAME01.ICN ( lines:9 words:32 ) ---------------------<cut here 結果はこうなります。1行目は、&prognameを示しています。 -----^ NAME01 ( date:97-06-02 time:19:08 ) -----------------<cut here D:\ICON\LEC35\NAME01.EXE NAME01 なんたらかんたら どうたらこうたら -----$ NAME01 ( lines:2 words:4 ) --------------------------<cut here 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: そのままの君でいて/岡本真夜 (pcv0601b.txt 1997/06/01 PCVAN SLABO) ■ Icon > Icon回り道(5)a < b が値をもつ 風つかい 目次 (Iconでは、比較式は成功すると、右辺の値を取りますが、その説明を PCVANの SLABOの会議室で ちょっと説明しましたので、参考になるかと。) 一般的に、比較式は、成立すれば、右辺の値を持ちます。 例えば、 3 < 5 の値は、 5 です。 "A" << "B" の値は、 "B" です。 ですから、 write(3 < 5) は、"5" を出力しますし、 write("A" << "B") は、"B" を出力します。 ( < は数字の比較。<< は文字列の比較です。 write()は、数字の場合は 文字に変換して出力します。) 実際には、右辺を変数にして、変数が比較条件に一致すれば出力する というような表現に使います。 Iconでは、比較式に限らず、全ての式が値を持ちます。 そこで、 write(if n < m then "NNN" else "MMM") というような表現もできます。これは、 if n < m then write("NNN") else write("MMM") と同じことになります。じゃあ、この式の値はどうなるかというと、 write()は引数と同じ値を持ちますので、出力文字と同じ値になります。 write(if n < m then write("NNN") else write("MMM")) は、同じ文字を2度出力します。 さて、条件が成立しない場合ですが、その場合はその式は【失敗】します。 【失敗する】というのは、その式が無いのと同じということになります。 値としては nullとなります。というか、値が無いという言い方が良いかも しれません。 Iconの関数は、nullが引数ですと、通常は、その関数自体が失敗します。 この仕様のために、表現を非常にコンパクトにできることも多いです。 動作サンプルを次ぎに。 -----^ A_B.ICN ( date:97-06-06 time:20:17 ) ----------------<cut here # This file is public domain. # 式の値のサンプル procedure main() write(3 < 5) wriet(3 > 5) # この式は失敗します。 write("A" << "B") n := 3 m := 5 write(if n < m then "NNN" else "MMM") if n < m then write("NNNN") else write("MMMM") write(if n < m then write("NNNNN") else write("MMMMM")) end -----$ A_B.ICN ( lines:12 words:52 ) -----------------------<cut here command lineから a_b > a_b とした時の結果です。 -----^ A_B ( date:97-06-06 time:20:17 ) --------------------<cut here 5 B NNN NNNN NNNNN NNNNN -----$ A_B ( lines:6 words:6 ) -----------------------------<cut here 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: 河よりも長くゆるやかに/篠原美也子 (pcv0606a.txt 1997/06/06 PCVAN SLABO) ■ Icon > ちょっと Icon(5)Wicon beta8 風つかい 目次 Iconの WindowsNT/95対応版を近ごろいじっています。 日本語は未だ画面に うまく出せないのですが、ちょっとご紹介します。 Iconは、Arizona大学の Griswold教授(のグループ)が開発していますが、 WindowsNT/95対応の Icon(Wicon)は、Arizona大学にいて、その後 Texas大学 San Antonio校(UTSA)に移った Jeffery教授(のグループ)が開発しています。 現在は、beta版で 8版になっています。 次の所から入手できます。 <UTSA> ftp://ringer.cs.utsa.edu/pub/icon/nt/graphics/ Index of /pub/icon/nt/graphics/ Name Last modified Size docs.zip 26-Feb-97 16:47 38K gprocs.zip 26-Feb-97 01:43 501K iconhelp.zip 05-Mar-97 12:53 145K keysyms.icn 08-Feb-96 00:00 3K procs.zip 26-Feb-97 01:43 339K READ.ME 06-Mar-97 00:53 4K vdefns.icn 17-Jun-97 01:53 1K vib.zip 26-Feb-97 02:31 122K vibsrc.zip 26-Feb-97 01:43 261K wi.bat 06-Mar-97 00:50 209K wi.icn 06-Mar-97 00:50 14K wi.zip 06-Mar-97 00:52 54K wicon.zip 06-Mar-97 01:26 339K <Arizona> ftp://ftp.cs.arizona.edu/icon/beta/windows Index of /icon/beta/windows Name Last modified Size docs.zip 06-Mar-97 20:12 38K gprocs.zip 06-Mar-97 20:12 501K iconhelp.zip 06-Mar-97 20:13 145K keysyms.icn 06-Mar-97 20:23 3K procs.zip 06-Mar-97 20:16 339K READ.ME 06-Mar-97 20:21 4K vib.zip 06-Mar-97 20:18 122K vibsrc.zip 06-Mar-97 20:18 261K wi.icn 06-Mar-97 20:23 14K wi.zip 06-Mar-97 20:19 54K wicon.zip 06-Mar-97 20:20 339K UTSAが originalで、後で Arizona大学へも登録されたみたいです。 MS-DOS版の Iconは、特に日本語対応版というのはありませんが、文字列 を 1byte単位で、走査・加工する機能が備わっていますので、日本語対応は 特に、Icon処理系をいじらなくても、Icon Programmer側で処理できます。 Windows版も、日本語文字が画面に出せさえすれば、後は programmer側と しては不便は無いと思って、なんとか日本語が表示できないかと色々試して います。 Windows版の Iconは、起動した状態で、2つの Windowが開きます。 1つは、editor-windowで、もう1つは console-windowです。 ・editor-windowでは、日本語入力は、問題ありません。表示もOKだし 保存して再度読みだしても大丈夫です。 行末のCRLFが、CRCRLFになるようですが、動作は問題ありません。 ・console-windowは、標準出力を表示する windowですが、日本語を出力 すると化けます。 ・programで、windowが開けます。開いた windowには、フォント指定が できます。 日本語のフォント指定も有効なものがあります。 FixedSys と System は指定すると有効みたいです。 しかし、特定コードを含む文字はうまく表示できません。 Shift-JISコードを出力する次のような programを作って試してみました。 -----^ JCHAR02W.ICN ( date:97-07-05 time:21:53 ) -----------<cut here # Show Japapense characters(Shift-JIS, output each character) # This file is in the public domain. # jchar02w.icn 1997/07/05 windy 風つかい H.S. link hexcvt, convert, # BIPL 基本 procedure library wopen # GIPL Window支援 procedure library procedure main(args) Usage := "jchar02w first_byte(hex) of the top char of char blocks. ex: 81" if *args < 1 then stop(Usage) # 引数無し jchar_out(inbase10(args[1],16)) # 引数を数字に変換 end procedure jchar_out(n1) # Shift-JISの文字出力 上位 n1、下位 \x40-\x7E,\x80-\xFC の文字を出力 # arg : [1]:block_no # window open WOpen("size=550,250","bg=pale red", "label=" || (s1 := hexstring(n1,2)) || "40-" || s1 || "FC : each character") | stop("can't open window") Font("FixedSys") # font指定 WWrite("dummy") # 最初の文字がうまく表示されない件の対策 WWrite(s1,"40 -> ",s1,"7E") WWrite("<0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F>") every n2 := 16r40 to 16r7E do { # Shift-JIS文字出力(前半) if ((16r40 < n2) % 32 = 0) then WWrite() # 32文字で改行 WWrites(char(n1) || char(n2)) # otuput each character(2 bytes) } WWrite() WWrite() WWrite(s1 := hexstring(n1,2),"80 -> ",s1,"FC") WWrite("<0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F>") every n2 := 16r80 to 16rFC do { # Shift-JIS文字出力(後半) if ((16r80 < n2) % 32 = 0) then WWrite() WWrites(char(n1) || char(n2)) # output each character(2 bytes) } WWrite() WDone() # q/Qキー入力待ち(Qまたはqを押すと windowを close) return end -----$ JCHAR02W.ICN ( lines:41 words:245 ) -----------------<cut here これを、引数 91で動かしますと、 9140 -> 917E <0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F> 繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙 疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻 9180 -> 91FC <0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F> 操早曹巣槍槽??燥争痩相窓糟総綜聡草荘葬??藻??走送遭鎗????像増憎臓 蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰 詑?チ堕妥惰打柁舵楕陀駄騨体堆対?マ?ミ帯待怠態戴?ヨ泰滞胎腿苔袋貸退?゚ 隊????代台大第醍題鷹滝瀧??啄??托??????濯琢託鐸濁諾????蛸只 という結果で、?の部分の文字がうまく表示できません。 (MS-DOSで動く同じ programの出力に、Windows版の画面で化ける部分の 修正を加えたものです。 ?は画面上は縦長■表示になっています。) 元々英語版の WindowsNT/95用に開発されていますが、MS-DOS版のように、 日本語版の Windows上で動かして、日本語文字表示が、ほぼ支障ないように なるといいなと思っています。 ということで、 Jeffery教授に、日本語版 Windows95で、動かしたときの レポートを 送っています。 日本語表示を検討してみよう言っていただいて いますので、日本語もほぼ支障なく表示できる版ができるかもしれません。 なにか参考書が無いかと聞かれましたので、私も読んでいないのですが、 "Developing International Software for Windows 95 and Windows NT" という本を紹介しました。役に立つと良いのですが。 あちらには、日本語版 Windows95やNTはありませんので、テスト版を作って いただいて、こちらでテストすることになります。 ほぼ日本語表示に支障無い版ができましたら、またお知らせします。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) <IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: 泣けちゃうほどせつないけれど/岡本真夜 (pcv0705a.txt 1997/07/05 PCVAN PIG,SLABO,niftyserve FPL,FGALTS) ■ Icon > ちょっと Icon(6)Icon Newsletter No.53 風つかい 目次 Iconのサポートは、アリゾナ大学の Icon Project で行っていますが、年2回、 Newsletterを発行しています。 以前は、希望者に冊子で配布していましたが、現在は WEBで見ることができ ます。 No.53が公開されていましたので、ご興味のある方は、のぞいて見て下さい。 http://www.cs.arizona.edu/icon/newsletter/inl53/inl53.html No. 53 -- August 1, 1997 Contents Icon in Java Icon Documentation in Japanese Handbook of Programming Languages Icon Analyst Promotional Offer Programming Visualization Course No.50以降は、http://www.cs.arizona.edu/icon/newsletter/inl.html から linkが張ってあります。 目次をご参考に。 No. 52 -- April 1, 1997 Contents Mail-Order Program Material Teaching Icon Web Links Native Interface Components in Windows Icon 9.3 Programming Language Handbook From Our Mail Knowledge Explorer No. 51 -- December 1, 1996 Contents Third Edition of The Icon Programming Language Graphics Programming Book Version 9.3 of Icon Version 9.3 of the Program Library New MS-DOS Implementation Icon in Java Teaching Icon Web Links Chicon No. 50 -- August 1, 1996 Contents Third Edition of the Icon Book New Implementations of Icon Icon for Chinese Computing Teaching Icon Book Sale! Web Links From Our Mail 尚、No.44以降は、次の所に pdf形式で置いてあります。 pdf形式ファイルの表示 には Acrobat Readerが必要ですが、http://www.adobe.co.jp/ から入手できます。 ftp://ftp.cs.arizona.edu/icon/doc inl44.pdf 10-Aug-95 00:00 124K inl45.pdf 10-Aug-95 00:00 187K inl46.pdf 17-Oct-95 00:00 270K inl47.pdf 25-Nov-95 00:00 268K inl48.pdf 25-Nov-95 00:00 378K inl49.pdf 17-Mar-96 00:00 550K inl50.pdf 14-Jul-96 00:00 563K inl51.pdf 05-Dec-96 00:00 508K inl52.pdf 27-Mar-97 22:31 82K <-これはサイズがおかしいですね。 壊れているみたい。 (現在は、正常なものに置換されて います。) おまけに、Icon関係の WEB LINKをあげておきます。 http://www.cs.arizona.edu/icon/index.html http://www.cs.utsa.edu/research/icon/icon.html http://www.nmt.edu/tcc/help/lang/icon/homepage.html http://www.eleves.ens.fr:8080/home/espie/icon/ http://www.crl.com/~spm/unicon/ 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) <IconのWWWは、http://www.cs.arizona.edu/icon/index.html> (pcv0801a.txt 1997/08/01 PCVAN PIG,SLABO,niftyserve FPL,FGALTS) ■ Icon > ちょっと Icon(7)Icon Ver9.3 (Windows95/NT) 風つかい 目次 Iconの Windows95/NT版が、新しい版がリリースされてました。 今度の版は、フォントは限定されますが、日本語も画面に出せます。 Iconは、Arizona大学の Griswold教授(のグループ)が 開発していますが、 WindowsNT/95対応の Icon(Wicon)は、Arizona大学にいて、その後 Texas大学 San Antonio校(UTSA) に移った Jeffery教授(のグループ)が開発しています。 Windows95/NT版ファイルは、次のところから入手できます。 ftp://ringer.cs.utsa.edu/pub/icon/nt/graphics/ README 4 Kb Fri Aug 08 16:13:00 1997 docs.zip 34 Kb Fri Aug 08 05:49:00 1997 Zip Compressed Data iconhelp.zip 605 Kb Fri Aug 08 05:50:00 1997 Zip Compressed Data ipl.zip 866 Kb Fri Aug 08 05:52:00 1997 Zip Compressed Data keysyms.icn 3 Kb Thu Feb 08 00:00:00 1996 vib.zip 119 Kb Fri Aug 08 05:52:00 1997 Zip Compressed Data vibsrc.zip 96 Kb Fri Aug 08 05:52:00 1997 Zip Compressed Data wi.zip 53 Kb Fri Aug 08 05:52:00 1997 Zip Compressed Data wicon.zip 631 Kb Fri Aug 08 05:53:00 1997 Zip Compressed Data 中身は、 README : 説明 docs.zip : Document iconhelp.zip : Help file ipl.zip : BIPL,GIPLの Procedure keysyms.icn : GIPL(基本ライブラリー)に含まれるが修正されているとのこと。 vib.zip : Visual Interface Builder (Iconで書かれたグラフィック インターフェース作成 ツールです。) vibsrc.zip : 同上のソース wi.zip : ランチャー wicon.zip : コンパイラ(ソースから中間言語生成)と(中間言語)の 実行解釈実行 となっています。 実際に動かすには、この他に BIPLが必要です。また、Graphicのサンプルプログラム は、GIPL(グラフィックライブラリー)に入っています。 ipl.zipは、GIPLの内 procedureを取り出したものです。 BIPLと GIPLは次の所にあります。 ftp://ftp.cs.arizona.edu/icon/library/ README 1 Kb Sun Feb 16 13:08:00 1997 VQUEENS.NOTE 197 bytes Sun Jan 05 00:00:00 1997 bipl.lzh 1190 Kb Wed Nov 27 00:00:00 1996 bipl.sea.hqx 1652 Kb Wed Nov 27 00:00:00 1996 Macintosh BinHex Archive bipl.tar.Z 1445 Kb Thu Nov 28 00:00:00 1996 Compressed Data bipl.tar.gz 967 Kb Sun Feb 16 13:05:00 1997 GNU Zip Compressed Data gipl.lzh 1092 Kb Wed Nov 27 00:00:00 1996 gipl.sea.hqx 1486 Kb Wed Nov 27 00:00:00 1996 Macintosh BinHex Archive gipl.tar.Z 1821 Kb Thu Nov 28 00:00:00 1996 Compressed Data gipl.tar.gz 1200 Kb Sun Feb 16 13:05:00 1997 GNU Zip Compressed Data info.lzh 16 Kb Wed Nov 27 00:00:00 1996 info.sea.hqx 40 Kb Wed Nov 27 00:00:00 1996 Macintosh BinHex Archive info.tar.Z 20 Kb Wed Nov 27 00:00:00 1996 Compressed Data info.tar.gz 14 Kb Sun Feb 16 13:05:00 1997 GNU Zip Compressed Data vqueens.icn 7 Kb Sun Jan 05 00:00:00 1997 インストールはこんな感じです。 【ディスクへの格納】 D:\ +wicon | | | +wi.bat <--- wi.zipから | +noop.bat <--- wicon.zipから | +wicont.exe <--- wicon.zipから | +wiconx.exe <--- wicon.zipから | +xxxx.hlp <--- iconhelp.zipから | | | +gipl | +include | | +aaa.icn <--- GIPLの include関係ファイルをそのまま入れる | +procs | | +bbb.u1 <--- GIPLの procedureを 中間言語にして入れておく | | +bbb.u2 | +progs | | +ccc.icn <--- GIPLのプログラム | +my_procs | | +ddd.u1 <--- 自分で作成した procedure | | +ddd.u2 | +my_progs | +fff.icn | +bipl | +include | | +hhh.icn <--- BIPLの include関係ファイルをそのまま入れる | +procs | | +iii.u1 <--- BIPLの procedureを 中間言語にして入れておく | | +iii.u2 | | | +progs | | +jjj.icn <--- BIPLの プログラム | +my_procs | | +kkk.u1 <--- 自分で作成した procedure | | +kkk.u2 | +my_progs | +lll.icn | という風にディスクに格納します。 【環境変数の設定】 次の4つの環境変数をセットしておきます。 IPATH=d:\gipl\procs d:\gipl\my_procs d:\bipl\procs d:\bipl\my_procs LPATH=d:\gipl\include d:\bipl\include ICONFONT=FixedSys WICONLOG=d:\wicon\Wicon.log IPATH は中間言語形式にした Iconの procedureを入れておくと、他のプログラム からの link指定で、その procedureを引用できるディレクトリーの指定です。 LPATH は ソースプログラムの一部として、他のプログラムの $include 指定で その プログラムを引用できるディレクトリーの指定です。 ICONFONT は、使用フォントの指定です。私の環境では、FixedSysと Systemが 有効みたいです。 WICONLOG は、動作ログのファイル指定みたいです。(よく分からないのですが 指定しないと、コンパイルの度に指定しろとメッセージがでるもので。) 【起動】 WI.BATを起動すると、Wiconが起動されて、エディターウィンドウが開きます。 そこから、Iconのソースプログラムを選択するか新しいソースファイル名を入力 して、プログラムを修正/作成して、コンパイル(make)すれば、実行モジュール ができます。 この辺は、実際に動かして見たほうが早いでしょう。 【サンプル】 GIPLにサンプルが入っていますので、動かしてみて下さい。 その中の GPXTEST.ICNは、GIPLのサンプルプログラムで、グラフィック機能の動作 テストのプログラムです。面白い絵がでてきます。 尚、vqueens.icnは修正版があります。GIPLの中のものは、ファイル不足エラーがで ます。修正版が ftp://ftp.cs.arizona.edu/icon/library/vqueens.icn にあります。 【プログラムソース】 プログラムソースは、 ftp://ringer.cs.utsa.edu/pub/icon/nt/src/ にあります。 README 2 Kb Wed Aug 06 01:48:00 1997 c.zip 155 Kb Tue Aug 05 15:32:00 1997 Zip Compressed Data cmn.zip 72 Kb Tue Aug 05 15:32:00 1997 Zip Compressed Data h.zip 83 Kb Tue Aug 05 15:32:00 1997 Zip Compressed Data msvc50.zip 15 Kb Wed Aug 06 00:39:00 1997 Zip Compressed Data p.zip 42 Kb Tue Aug 05 15:32:00 1997 Zip Compressed Data r.zip 364 Kb Tue Aug 05 15:32:00 1997 Zip Compressed Data rtl.zip 100 Kb Tue Aug 05 15:32:00 1997 Zip Compressed Data rtt.exe 275 Kb Fri Jan 26 00:00:00 1996 Binary Executable t.zip 88 Kb Tue Aug 05 15:32:00 1997 Zip Compressed Data wincap.zip 40 Kb Thu Feb 01 00:00:00 1996 Zip Compressed Data 【日本語の扱い】 Iconの文字列処理は、1バイト単位で行います。日本語の文字の区切りを意識し たプログラム以外では、支障は起きません。日本語の文字の区切りを意識するの が必要ならそういう procedureを組めば可能です。 しかし、画面出力はまた別問題です。Windows95/NT環境で、画面の文字を出力す る際には、現バージョンでは 次の制限があります。 ・フォントの制限 フォント指定が、自由にはできない。FixedSysと Systemの指定は有効みた いです。 ・日本語出力のやり方 コンソールウィンドウへの日本語文字出力や、生成したウィンドウへの日本 語文字出力では、バイト単位で出力すると文字が化けます。文字(2バイト) 単位で出力すれば大丈夫でした。 ですから、文字列を表示させるには、支障はありません。 (また、ファイルに出力する分には問題ありません) 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) <IconのWWWは、http://www.cs.arizona.edu/icon/index.html> (pcv0810a.txt 1997/08/10 PCVAN PIG,SLABO,niftyserve FPL,FGALTS) ■ Icon > Icon散歩道 むすび 風つかい 目次 散歩道では、テキスト解析をやろうと思っていたのですが、殆ど 以前の講座 のミス修正と 思いつき programの解説になってしまいました。 散歩道で予定していました 数式解析とかは 全然 手をつけていませんが 秋も 終わりですので、この辺で Icon散歩道 を終わることにします。 お付き合いいただきまして、ありがとうございました。 では、また、お会いする日まで。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> (iconlec4.txt 1997/11/24)