More Related Content Similar to Usp友の会勉強会、ジャクソン構造図の巻(後編) Similar to 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』 (ソフトバンク )