質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
排他制御

排他制御とは、特定のファイル・データへのアクセスや更新を制御することです。特にファイルやデータベースへ書き込みを行う際、データの整合性を保つため別のプログラムによる書き込みを一時的に制御することを指します。

標準出力

標準出力(stdout)は、プログラムが標準的に用いるデータ出力元。標準出力に書き込み要求を発行しすることにより、ディスプレイ装置にデータを表示することができます。UNIX系OSやC言語に実装されて普及した概念ですが、他のOSや言語も含めた総称としても使われます。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

848閲覧

複数行による標準出力と、複数のファイルの書き・読み込みを行いたい

tampopoo

総合スコア1

排他制御

排他制御とは、特定のファイル・データへのアクセスや更新を制御することです。特にファイルやデータベースへ書き込みを行う際、データの整合性を保つため別のプログラムによる書き込みを一時的に制御することを指します。

標準出力

標準出力(stdout)は、プログラムが標準的に用いるデータ出力元。標準出力に書き込み要求を発行しすることにより、ディスプレイ装置にデータを表示することができます。UNIX系OSやC言語に実装されて普及した概念ですが、他のOSや言語も含めた総称としても使われます。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2020/09/28 10:12

編集2020/09/28 10:20

前提・実現したいこと

Eラーニングシステムを作っており、記述式の問題を想定して作っています。
2つの変数(seito、kaitou)に与えられたものをコードとして実行し、比較して正誤判定を行なっています。
出力結果を比較したいため、$stdoutを使って2つのファイルに標準出力を書き出しました。
seitoとseikaiは複数行あり、2行目以降は別の内容なので不正解と出力されるはずですが、
同じ"2\n"である1行目しか反映されず正解と出てしまいます。
複数行、複数のファイルの書き込み・読み込みをしたい場合はどのようにすればよいでしょうか。

発生している問題・エラーメッセージ

"2\n" "2\n" 正解

該当のソースコード

ruby

1# 書き込み 2 3s_filename = './seito.txt' # 正解の実行結果ファイル名 4k_filename = './kaitou.txt' # 回答の実行結果ファイル名 5 6# 正解のプログラムの内容 7@seito = Proc.new { 8 a = 1 9 b = 2 10 p a * b 11 print 20 12 puts "test" 13} 14 15# 回答のプログラムの内容 16@kaitou = Proc.new { 17 a = 1 18 b = 2 19 p a * b 20 print 30 21 puts "test2" 22} 23 24 25# 正解プログラムの実行結果を seito.txt に出力 26 $stdout = File.open(s_filename, 'w') 27 # ここ以降は標準出力がファイルに出力される 28 puts @seito.call 29 $stdout = STDOUT # $stdoutのリセット 30 31 32# 回答プログラムの実行結果を kaitou.txt に出力 33 $stdout = File.open(k_filename, 'w') 34 # ここ以降は標準出力がファイルに出力される 35 puts @kaitou.call 36 $stdout = STDOUT # $stdoutのリセット 37 38######################## 39# 読み込み確認用プログラム 40######################### 41# 正解ファイルの読み込み 42@seitos = File.read(s_filename)#.readlines 43p @seitos 44 45# 回答ファイルの読み込み 46@kaitous = File.read(k_filename)#.readlines 47p @kaitous 48 49#判定 50if @seitos == @kaitous 51 puts "正解" 52else 53 puts "不正解" 54end

試したこと

ファイルの書き込みが完了しないうちに、同じファイルを読み込んでしまっているのが原因だと思い、排他制御というものを行おうと思いました。
出力の際にロックをかける必要があると判断し、$stdoutとFile::LOCKを同時に使う必要があると思いました。
リファレンスで確認すると$stdoutもFile::LOCKも使い方がファイルオープンを使う様であったため同じ行でまとめてしまいましたが、2つを一緒に行うにはどのように使うわかりませんでした。また、ファイルのロックの正しい箇所もわからずにいます。
<正解プログラムの実行結果を seito.txt に出力> の部分を以下に書き換え実行しました。
2
20test
と複数行の書き込みには成功しましたが、2つ目のファイルの読み込みはできず、
$stdout must have write method, Integer given (TypeError)
とエラーがでてしまいました。

Ruby

1# 正解プログラムの実行結果を seito.txt に出力 2 $stdout = File.open(s_filename, 'w'){|f| 3 f.flock(File::LOCK_EX) # ロックする(すでにロックされていたら待つ) 4 # ここ以降は標準出力がファイルに出力される 5 puts @seito.call 6 $stdout = STDOUT # $stdoutのリセット 7 f.flock(File::LOCK_UN) # アンロックし、他のプログラムが読み出せるようにする 8}

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ファイルをクローズしてないからですね。最小限の修整で済ませると、

Ruby

1# 正解プログラムの実行結果を seito.txt に出力 2 $stdout = File.open(s_filename, 'w') 3 # ここ以降は標準出力がファイルに出力される 4 puts @seito.call 5 $stdout.close 6 $stdout = STDOUT # $stdoutのリセット 7 8 9# 回答プログラムの実行結果を kaitou.txt に出力 10 $stdout = File.open(k_filename, 'w') 11 # ここ以降は標準出力がファイルに出力される 12 puts @kaitou.call 13 $stdout.close 14 $stdout = STDOUT # $stdoutのリセット

排他制御とかは必要ないです。

ファイルのオープンとクローズの役割を復習しましょう。

投稿2020/09/28 12:08

otn

総合スコア85901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tampopoo

2020/09/30 04:45

全文の比較できました! 完全に勉強不足でした、、、。 回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問