第7回のレポートより

参考として、良かったレポートを示す。

氏名: fx
学籍番号: c111126
クラス: 中国語1

1.作成したプログラム
#!/usr/bin/koeki/ruby
# coding:euc-jp

name = []
kin = []
i = n = sum = 0
open("receipt.txt","r") do |hoge|
  while line = hoge.gets
    if /^#/ =~ line
      next
    elsif /^"(.+)"\s+(\d+)\s+(\d+)\s+(\d+)/ =~ line
      name[i] = $1
      kin[i] = $4.to_i
      sum += $4.to_i
      i += 1
    end
  end
end
open("result.txt","w") do |hoge|
  hoge.print"+-----------------------------+\nSHOP HOGEHOGE\n           --------\n           |領収書|\n           --------\n+-----------------------------+\n"
  while n < i
    hoge.printf("  %-20s%8d円\n",name[n],kin[n])
    n += 1
  end
  hoge.printf("+-----------------------------+\n  合計%20d円\n+-----------------------------+\n",sum)
end

 5番のreceipt.txt にあるデータを入力として 購入したものや合計金額などを
 本物のレシートのような 書式で result.txt ファイルに出力するプログラム
 open5.rbを作成した。

2.プログラムを動かした結果画面と、その結果ファイルの内容
roy{c111126}% ruby open5.rb                       [~/Ruby]
roy{c111126}% cat result.txt                      [~/Ruby]
+-----------------------------+
SHOP HOGEHOGE
           --------
           |領収書|
           --------
+-----------------------------+
  モコモコスパゲッティ               880円
  suidou ざ・movie          3980円
  SDHC 4GB                 980円
  5フィンガー靴下                 120円
+-----------------------------+
  合計                5960円
+-----------------------------+


3.プログラムの説明
最初の2行はおまじない

4,5行目の
name = []
kin = []
でnameという配列とkinという配列を作っている

また、6行目の
i = n = sum = 0
で、数える用のiとn、合計を入れるためのsumという変数に0を入れている

7行目の
open("receipt.txt","r") do |hoge|
では、receipt.txtというファイルを読み込みモードで開いている

8行目の
while line = hoge.gets
では、7行目に読み込んだデータを一行ずつlineという変数の中に読み込み、デー
タが読めなくなったらループを終わるという条件を設定している。

9,10行目の
if /^#/ =~ line
   next
では、読み込んだデータの先頭が#だった場合は、その行はメモでデータではな
いので次のデータを読みなおすようにしている。

11行目の
elsif /^"(.+)"\s+(\d+)\s+(\d+)\s+(\d+)/ =~ line
では、読み込んだデータの形が
  ^          先頭に
  "(.+)"     ""で囲まれた文字が一つ以上続き、(商品名)
  \s+        空白が一つ以上続き、(商品名と分類コードの間の空白)
  (\d+)      数字が一つ以上続き、(分類コード)
  \s+        空白が一つ以上続き、(分類コードと商品コードの間の空白)
  (\d+)      数字が一つ以上続き、(商品コード)
  \s+        空白が一つ以上続き、(商品コードと価格の間の空白)
  (\d+)      数字が一つ以上続いている(価格)
時に、

/^"(.+)"\s+(\d+)\s+(\d+)\s+(\d+)/
     $1      $2      $3      $4

の順にデータを取るというif文にしている

12,13行目の
name[i] = $1
kin[i] = $4.to_i
では、nameという配列のi番目に読み込んだデータの$1の位置にある名前を入れ
て、kinという配列のi番目に読み込んだデータの$4の位置にある価格を入れ、数
字として出すために.to_iを付けている。

14行目の
sum += $4.to_i
では、合計用の変数sumに$4に入っている価格を.to_iを付けて数字として持って
来て足していくようにしている。

15行目の
i += 1
では、配列の入れる位置をずらす為に1ずつ足している。また、ここでデータの
件数も数えている。

16,17,18行目の
end
は、それぞれ9行目のif文、8行目のwhile文、7行目のopenを閉じるためのもので
ある。

19行目の
open("result.txt","w") do |hoge|
では、result.txtというファイルを書き込み形式で開き、無ければ新規作成して、
既にあれば中身を何も無くしてから書き込むようにしている。

20行目の
hoge.print"+---...---+\n"
では、外部に出力するために19行目で設定した変数をpirntの前に付けて、レシー
トの飾りになる部分を表示している。

21行目の
while n < i
では、件数を数えていたiよりもnが小さい間ループを続けるという条件で設定し
ている。

22行目の
hoge.printf("  %-20s%8d円\n",name[n],kin[n])
では、printfの前に外部に出力するための変数を付け、実際に表示する商品名が
入っている配列nameのn番目と、価格が入っている配列kinのn番目を、それぞれ
%-20s,%8dで表示している。

23行目の
n += 1
では、22行目で表示するn番目をずらすためと、件数を数えているiと比べるため
にnに1ずつ足している。

24行目の
end
は、23行目のwhile文を閉じる為のものである。

25行目の
hoge.printf("+----...--+\n 合計 %20d円\n+---...---+\n,sum)
では、レシートを横線で閉じ、金額の合計を入れていたsumを表示して、レシー
トをまた横線で閉じているように表示している。

26行目の
end
は、19行目のopenを閉じる為のものである。


4.考察
データを読み込む正規表現を書く時に、ただ
/^(\S+)\s+(\d+)\s+(\d+)\s+(\d+)/
とやると、suidou ざ・movieなど、商品名の間に空白があるものに上手く当ては
まらなくなる。なので、データの中の商品名が""で囲まれている事を利用し、
/^"(.+)"\s+(\d+)\s+(\d+)\s+(\d+)/
とすることで、""に囲まれている文字というように選択でき、上手く正規表現に
当てはめる事が出来る。


5.参考文献
広瀬雄二."ファイル入出力".東北公益文化.
http://roy/~yuuji/2012/pf1/07/file-io.html,(参照2012-5-8)


6.感想
openコマンドはこれからよく使う事になると思うので、しっかり使いこなせるよ
うにしたいと思う。
メールを送るコマンド等も復習して、これから先グループ課題等を作る事になっ
た時に活用出来るようにしていけるようにしたい。

本日の目次