読者です 読者をやめる 読者になる 読者になる

感謝のプログラミング 10000時間

たどり着いた結果(さき)は、感謝でした。

【プログラミング 46時間目】Rubyの例外処理

Ruby
<スポンサーリンク>

たのしいRuby 第3版

たのしいRuby 第3版

たのしいRubyでたのしくRubyを勉強。この本も素晴らしくわかりやすい素敵な本だ。

プログラムの実行中にエラーが起こると例外が発生する。例外が発生すると、プログラムの実行は一時中断し、例外処理を探す。
例外処理が記述されていればそれを実行する。

例外処理の仕組みがない言語では、処理が完全に終わったかどうかを一つ一つ確認しながらプログラムを書く必要がある。

Rubyの例外処理の書き方

begin
	例外を発生させる可能性がある処理
rescue
	例外が起こった場合の処理
end

あるいは、

begin
	例外が起こる可能性のある処理
rescue => 例外オブジェクトが代入される変数
	例外が起こった場合の処理
end


今日、これまで書いたブログの文字数や単語数、行数を調べるため、以下のプログラムを実行してみた。

lineTotal = 0
wordTotal = 0
charTotal = 0

ARGV.each do |file|
	begin 
		input = open(file)
		line = 0
		word = 0
		char = 0
		while line = input.gets
			line += 1			#1行ごとに足していく
			char += line.size	#文字数を加えていく
			line.sub!(/^\s/,"") #行頭の空白を削除
			ary = line.split(/\s+/) #空白文字で分解して配列につっこむ
			word += ary.size    #単語数の変数に上で分解した配列の箱の数(=単語数)を代入する
		end
		input.close
		printf("%8d %8d %8d %s\n",line,word,char,file)  #整形して出力する
		lineTotal += line
		wordTotal += word
		charTotal += char
	rescue => exception
		print "Exception!! ",exception.message, "\n"
	end
end

printf("%8d %8d %8d %s\n", lineTotal,wordTotal,charTotal,"total")
			

すると、早速以下のような例外が・・・

Exception!! can't convert Fixnum into String
Exception!! can't convert Fixnum into String
Exception!! can't convert Fixnum into String
       0        0        0 total

ここで見るとわかるように、
0 0 0 total
まではちゃんと出力されている。
これは、例外処理をすると、プログラムは例外が発生しても止まらず動く、ということである。

さて、
can't convert Fixnum into Stringとは、数値型を文字列に変換することはできない、ということである。

何がおかしいのか見てみると・・・

		line = 0
		word = 0
		char = 0
		while line = input.gets
			line += 1			#1行ごとに足していく
			char += line.size	#文字数を加えていく
			line.sub!(/^\s/,"") #行頭の空白を削除
			ary = line.split(/\s+/) #空白文字で分解して配列につっこむ
			word += ary.size    #単語数の変数に上で分解した配列の箱の数(=単語数)を代入する
		end

ここで、lineという数値型の変数と、文字列を突っ込む文字列型のlineが混在してしまっている。

なので、数値型のlineをline_iとすると、

lineTotal = 0
wordTotal = 0
charTotal = 0

ARGV.each do |file|
	begin 
		input = open(file)
		line_i = 0
		word = 0
		char = 0
		while line = input.gets
			line_i += 1			#1行ごとに足していく
			char += line.size	#文字数を加えていく
			line.sub!(/^\s/,"") #行頭の空白を削除
			ary = line.split(/\s+/) #空白文字で分解して配列につっこむ
			word += ary.size    #単語数の変数に上で分解した配列の箱の数(=単語数)を代入する
		end
		input.close
		printf("%8d %8d %8d %s\n",line_i,word,char,file)  #整形して出力する
		lineTotal += line_i
		wordTotal += word
		charTotal += char
	rescue => exception
		print "Exception!! ",exception.message, "\n"
	end
end

printf("%8d %8d %8d %s\n", lineTotal,wordTotal,charTotal,"total")
			

例外は発生しなくなった。
結果は以下の通り。

>ruby wc.rb 20130114_1.txt 20130114_2.txt 20130114_3.txt
130114_2.txt 20130114_3.txt
      59      202     2984 20130114_1.txt
      59       52     4031 20130114_2.txt
     138      515    14625 20130114_3.txt
     256      769    21640 total

今日の今までで21640文字分のブログ記事を書いていることになる。
そういえば学部の卒業論文の目安文字数が30000字だった気がするけど、ずいぶんタイピングが早くなったなぁ。笑
まぁ、ブログは全然考えて書いていないし、論文でもないから全く比較対象にはならないけれど。

def copy(from, to)
	src = open(from)
	begin
		dst = open(to, "w")
		data = src.read
		dst.write(data)
		dst.close
	ensure
		src.close
	end
end

#ファイルをコピーする
from = ARGV[0]
to = "copy.txt"
copy(from,to)

ensureはJavaでいうfinallyと同じ。
例外が起こっても起こらなくても、常に実行したい処理があるときに書く。


■気になる本のメモ

はじめてのOSコードリーディング ~UNIX V6で学ぶカーネルのしくみ (Software Design plus)

はじめてのOSコードリーディング ~UNIX V6で学ぶカーネルのしくみ (Software Design plus)