Weitere ähnliche Inhalte Ähnlich wie Usp友の会勉強会、ジャクソン構造図の巻(後編) (20) Usp友の会勉強会、ジャクソン構造図の巻(後編)3. 本日の予定
1. USP友の会の紹介(10分)
2. アイスブレイク(一言自己紹介)(30分)
3. 前回の振り返り(30分)
4. 講義1(先読み技法紹介)(30分)
5. 演習( 60分ぐらい)
6. ライブプログラミング(30分)
7. 次回の予告(20分)
8. まとめ(25分)
10. 例題:整数判定の状態遷移図
0~9
0~9
0~9 EOS
+|-
開始
S0 S1 S2 OK
その他
その他
その他
NG
24. 表現力は状態遷移図と等価
言語階層 機械 文法 備考
タイプ0 チューリングマシン 句構造文法
タイプ1 線形有界オートマトン 文脈依存文法
プッシュダウンオート
タイプ2 文脈自由文法 プログラミング言語の階層
マトン
ジャクソン構造図と等価
タイプ3 有限オートマトン 正規文法
状態遷移図と等価
31. 例:整数判定の状態遷移図
0~9
0~9
0~9 EOS
+|-
開始
S0 S1 S2 OK
その他
その他
その他
NG
32. 先の例を状態遷移表に変換
符号 数字 終端 その他
(+ or -) (0~9) (EOS)
S0 S1 S2 NG NG
S1 NG S2 NG NG
S2 NG S2 OK NG
33. 状態遷移表の縦と横を入れ替える
S0 S1 S2
符号
S1 NG NG
(+ or -)
数字
S2 S2 S2
(0~9)
終端
NG NG OK
(EOS)
その他 NG NG NG
34. プログラムに変換すると
#!/usr/bin/perl } else {
exit 1;
@c = split //, shift; }
}
$s = 0; if ($s == 2) {
for $c (@c) { exit 0;
if ($c eq '+' || $c eq '-') { } else {
if ($s == 0) { exit 1;
$s = 1; }
} else {
exit 1;
}
} elsif ('0' le $c && $c le '9') {
if ($s == 0 || $s1 == 1 || $s == 2) {
$s = 2;
}
36. 先のジャクソン構造図から導かれたプログラム
#!/usr/bin/perl while ('0' le $c && $c le '9') {
$c = shift @c;
@c = split //, shift; }
$c = shift @c; if ($c eq '') {
if ($c eq '+' || $c eq '-') { exit 0;
$c = shift @c; } else {
} exit 1;
}
if ('0' le $c && $c le '9') {
$c = shift @c;
} else {
exit 1;
}
37. 前回の宿題
1. 身の回りのもので位置を利用して情
報を表現しているものを探してみよう
2. 浮動小数点数のジャクソン構造図をプ
ログラムに変換してみよう
3. 浮動小数点数の状態遷移図からgoto
プログラムを書いたのち、発見的手法
でgotoを取り除いてみよう
38. 宿題2のジャクソン構造図
浮動
小数点数
仮数部 指数部
○
符号 絶対値 省略可能
指数部
○ ○ ○
+ or - 整数部付 小数部のみ 指数文字 指数
絶対値 絶対値
整数部 小数部 小数部 E or e 符号 整数部
○ ○
1文字目 2文字目 省略可能 小数点 小数 + or - 1文字目 2文字目
数字 以降数字群 小数部 数字 以降数字群
* *
0~9 0~9 小数点 小数 ・ 1文字目 2文字目 0~9 0~9
数字 以降数字群
* *
・ 0~9 0~9 0~9
39. 宿題2の解答例
#!/usr/bin/perl } elsif ($c eq '.') { if ($c eq 'E' || $c eq 'e') {
$c = shift @c; $c = shift @c;
if ($c eq '+' || $c eq '-') {
@c = split //, shift; if ('0' le $c && $c le '9') {
$c = shift @c;
$c = shift @c; }
$c = shift @c; while ('0' le $c && $c le '9') {
if ($c eq '+' || $c eq '-') { $c = shift @c; if ('0' le $c && $c le '9') {
$c = shift @c; } $c = shift @c;
while ('0' le $c && $c le '9') {
} } else {
$c = shift @c;
exit 1; }
if ('0' le $c && $c le '9') { } } else {
$c = shift @c; } else { exit 1;
while ('0' le $c && $c le '9') { exit 1; }
}
$c = shift @c; }
} if ($c eq '') {
exit 0;
if ($c eq '.') { } else {
$c = shift @c; exit 1;
}
}
43. 例題1:解答例
解答例1 解答例2 解答例3
テキスト テキスト テキスト
ファイル ファイル ファイル
* * *
行 バイト 文字
44. プログラムに変換すると
解答例1 解答例2 解答例3
#!/usr/bin/perl #!/usr/bin/perl #!/usr/bin/perl
$count = 0; $count = 0; binmode STDIN, ":utf8";
while (<STDIN>) { while (defined(getc)) {
$count++; $count++; $count = 0;
} } while (defined(getc)) {
print $count, "¥n"; print $count, "¥n"; $count++;
}
print $count, "¥n";
47. 例題2:解答例
解答例1 解答例2 解答例3
テキスト テキスト テキスト
ファイル ファイル ファイル
* * *
行 文字 行
○ ○
改行以外の 改行文字 行文字列 改行文字
文字
*
改行以外の
文字
48. プログラムに変換すると
解答例1 問題2 問題3
#!/usr/bin/perl #!/usr/bin/perl #!/usr/bin/perl
$count = 0; binmode STDIN, ":utf8"; binmode STDIN, ":utf8";
while (<STDIN>) {
$count++; $count = 0; $count = 0;
} while (defined($char = getc)) { while () {
print $count, "¥n"; if ($char eq "¥n") { while (defined($char = getc)
$count++; && $char ne "¥n") {
} }
} last if (! defined($char));
print $count, "¥n"; $count++;
}
print $count, "¥n";
54. 例題3の拡張状態遷移図による表現
行の取得成功 / カウンタ= 1 行の取得成功 & 保存行と取得行が一致 /
保存行に取得した行を保存 カウンタ++ 行の取得失敗 / print カウンタ, 保存行
S0 S1 S2
行の取得成功 & 保存行と取得行業が不一致 /
print カウンタ, 保存行
カウンタ= 1
保存行に取得した行を保存
行の取得失敗 / -
55. 状態遷移図をプログラムに変換すると
#!/usr/bin/perl
$line = <STDIN>;
if (not $line) {
exit;
}
$count = 1;
$old_line = $line;
while ($line = <STDIN>) {
if ($line ne $old_line) {
print "$count¥t$old_line";
$count = 1;
$old_line = $line;
} else {
$count++;
}
}
print "$count¥t$old_line";
56. プログラムから導かれるデータ構造の
ジャクソン構造図による表現
入力データ 出力データ
テキスト テキスト
ファイル ファイル
○ ○ *
内容なし 内容あり 行
最初の行 間の行 最後の行 同一行の数 同一行
*
行
○ ○
非ブレイク行 ブレイク行
直前の行と 直前の行と
同じ行 異なる行
57. もっと良い構造はないか…
あります。
入力データ 出力データ
テキスト テキスト
ファイル ファイル
* *
同一行 行
グループ
*
同一行 同一行の数 同一行
但し、プログラムで表現するには先読み技法が
必要です。
59. 例:標準入力の行数を求めるプログラム
通常のファイル処理 先読み技法を使ったファイル処理
#!/usr/bin/perl #!/usr/bin/perl
$count = 0; $count = 0;
while (<STDIN>) { $next_line = <STDIN>;
$count++; $line = $next_line;
} while ($line) {
print $count, "¥n"; $next_line = <STDIN>;
$count++;
$line = $next_line;
}
print $count, "¥n";
60. 例題3のプログラムを記述
通常のファイル処理 先読み技法を使ったファイル処理
#!/usr/bin/perl #!/usr/bin/perl
$line = <STDIN>;
if (not $line) { $next_line = <STDIN>;
exit;
} while ($line = $next_line) {
$count = 1; $count = 0;
$old_line = $line;
while ($line = <STDIN>) {
while ($line eq $next_line) {
if ($line ne $old_line) { $count++;
print "$count¥t$old_line"; $next_line = <STDIN>
$count = 1;
$old_line = $line; }
} else { print "$count¥t$line";
$count++;
} }
}
print "$count¥t$old_line";
61. 演習問題
下記のプログラムを先読み技法を使用して書き直せ。
#!/usr/bin/perl print "小計:$count2¥t$old_col1 $old_col2¥n";
$count1 += $count2;
$line = <STDIN>; $count2 = 1;
if (not $line) { $old_col2 = $col2;
exit; if ($col1 ne $old_col1) {
} print "大計:$count1¥t$old_col1¥n";
$count1 = 0;
($col1, $col2) = split(/¥s/, $line); $old_col1 = $col1;
$count1 = 0; }
$count2 = 1; } else {
$old_col1 = $col1; $count2++;
$old_col2 = $col2; }
while ($line = <STDIN>) { }
($col1, $col2) = split(/¥s/, $line); print "小計:$count2¥t$old_col1 $old_col2¥n";
if ($col1 ne $old_col1 || $col2 ne $old_col2) { $count1 += $count2;
print "大計:$count1¥t$old_col1¥n";
65. 演習問題解答例
#!/usr/bin/perl print "小計:$count2¥t$col1 $col2¥n";
$count1 += $count2;
if ($line = <STDIN>) { }
($next_col1, $next_col2) = split(/¥s/, $line); print "大計:$count1¥t$col1¥n";
}
}
while ($line) {
$col1 = $next_col1;
$count1 = 0;
while ($line && $col1 eq $next_col1) {
$col2 = $next_col2;
$count2 = 0;
while ($line && $col1 eq $next_col1
&& $col2 eq $next_col2) {
$count2++;
if ($line = <STDIN>) {
($next_col1, $next_col2)
= split(/¥s/, $line)
}
}
66. 先読み技法ライブプログラミング
Excel互換のCSVパーサーを記述する
入力データ 出力データ
a,b,c abc
1,2,3 123
"""","""""","""""""" " "" """
"""a""","""b","c""" "a" "b c"
"あ あ¥nい¥n う え
い ___
",う,え
,,
~
67. CSVパーサーの拡張状態遷移図
他/バッファ ダブルクォート/エラー
NG
他/バッファ S1 他/バッファ
改行|カンマ 改行|カンマ
/出力 /出力
ダブルクォート
他/バッファ
S3 /何もしない
S0
ダブルクォート ダブルクォート/何もしない
/何もしない
他/エラー
S2 S4
ダブルクォート/バッファ
OK
EOF
改行|カンマ/出力 /何もしない
68. CSVファイルのジャクソン構造図
CSV
ファイル
*
項目
項目本体 区切り文字
○ ○ ○ ○ ○
空項目 通常文字 特殊文字含 カンマ 改行
のみ項目 項目
*
- 通常文字 ダブルクォー 特殊文字含 ダブルクォー
テーション 項目本体 テーション
*
特殊文字
含文字
○ ○ ○ ○
通常文字 ダブルクォー カンマ 改行
テーション
69. 先読み技法を使ったExcel互換の
CSVパーサープログラム
#!/usr/bin/python elif ch == '"' and nch == '"':
buffer += ch
import os, sys nch = chs.next()
elif ch == '"':
def genchs(): sys.exit(1)
for line in sys.stdin: elif ch == ",":
line = line.decode("utf_8") buffer += ","
for ch in line: elif ch == "¥n":
yield ch buffer += "¥¥n"
yield "" else:
buffer += ch
if __name__ == "__main__":
chs = genchs() ch = nch
ch = chs.next() else:
while ch: while ch and ch != "," and ch != "¥n":
buffer = "" if ch == '"':
sys.exit(1)
if ch == "," or ch == "¥n": buffer += ch
buffer += "_" ch = chs.next()
elif ch == '"':
ch = chs.next() if ch == ",":
while ch: print buffer.encode("utf_8"),
nch = chs.next() ch = chs.next()
if ch == '"' and (nch == "," or nch == "¥n"): elif ch == "¥n":
ch = nch print buffer.encode("utf_8")
break ch = chs.next()
71. まとめ1
1. データの解釈の仕方によりプログラミング
は簡単になったり、難しくなったりする。
2. ジャクソン構造図はプログラミングを簡単に
する構造を導き出すのに役立つ。
3. 先読み技法はジャクソン法で導き出した構
造をプログラム上で表現するのに役立つ。
73. ジャクソン法の短所について
1. ジャクソン法は前者の方法を重視している
ため、プログラムから柔軟性は失われる。
2. 実行時に動きを変更するなどの柔軟性を
プログラムに持たせたい場合は、ほかの方
法を採用する必要がある。
75. 例1:整数判定の状態遷移図
0~9
0~9
0~9 EOS
+|-
開始
S0 S1 S2 OK
その他
その他
その他
NG
76. 先の例を状態遷移表に変換
その他 符号 数字 終端
(+ or -) (0~9) (EOS)
S0 NG S1 S2 NG
S1 NG NG S2 NG
S2 NG NG S2 OK
77. 状態遷移表からプログラムを作成
#!/usr/bin/perl
@c = split //, shift;
@state_table = (
[-2, 1, 2, -2],
[-2, -2, 2, -2],
[-2, -2, 2, -1]
);
@char_num{('+', '-', '0'..'9', '')} = ((1)x2, (2)x10, 3);
$s = 0;
while ($s >= 0) {
$s = $state_table[$s][$char_num{shift @c} || 0];
}
exit($s == -2);
78. 例2:浮動小数点数判定の状態遷移図
0~9 E|e 0~9
0~9 0~9 0~9
+|- ・ E|e +|-
0~9 0~9
開始
S0 S1 S2 S4 S5 S6 S7
EOS
・ EOS
・ 0~9
S3 EOS OK
その他
NG
79. 先の例を状態遷移表に変換
その他 符号 数字 小数点 指数記号 終端
(+ or -) (0~9) (.) (E or e) (EOS)
S0 NG S1 S2 S3 NG NG
S1 NG NG S2 S3 NG NG
S2 NG NG S2 S4 S5 OK
S3 NG NG S4 NG NG NG
S4 NG NG S4 NG S5 OK
S5 NG S6 S7 NG NG NG
S6 NG NG S7 NG NG NG
S7 NG NG S7 NG NG OK
80. 状態遷移表からプログラムを作成
#!/usr/bin/perl
@c = split //, shift;
@state_table = (
[-2, 1, 2, 3, -2, -2],
[-2, -2, 2, 3, -2, -2],
[-2, -2, 2, 4, 5, -1],
[-2, -2, 4, -2, -2, -2],
[-2, -2, 4, -2, 5, -1],
[-2, 6, 7, -2, -2, -2],
[-2, -2, 7, -2, -2, -2],
[-2, -2, 7, -2, -2, -1]
);
@char_num{('+', '-', '0'..'9', '.', 'E', 'e', '')} = ((1)x2, (2)x10, 3, (4)x2, 5);
$s = 0;
while ($s >= 0) {
$s = $state_table[$s][$char_num{shift @c} || 0];
}
exit($s == -2);
81. まとめ2
1. 状態遷移図はジャクソン構造図と違い、
コーディングスタイルまで規定しない。
2. 状態遷移図はその分応用範囲が広いと
言える。
82. 参考文献
• M.A.ジャクソン(1985/02) 『構造的プログラム設計の原理』 (日本コン
ピュータ協会)
• 若林糧(2000/03) 『C言語プログラミング演習』 (日経BP社)
• 飯泉 純子、大槻 繁(2011/08) 『ずっと受けたかったソフトウェア設計の授
業』 (翔泳社)
• E.W.ダイクストラ、C.A.R.ホーア、O.J.ダール(1975/05) 『構造化プログラミン
グ』 (サイエンス社)
• 野口健一郎(1990/05) 『ソフトウェアの論理的設計法』 (共立出版)
• 玉井哲雄(2004/03) 『ソフトウェア工学の基礎』 (岩波書店)
• スティーブ マコネル(2005/03) 『Code Complete第2版〈上〉』 (日経BPソフト
プレス)
• きだあきら(1995/05) 「特集 Cプログラム設計技法」 『C MAGAZIN 1993
MAY Vol.5 No.5』 (ソフトバンク )