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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

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

Q&A

解決済

2回答

1658閲覧

文の意味

yusuke.

総合スコア66

Ruby

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

0グッド

0クリップ

投稿2017/04/18 06:20

編集2017/04/20 06:33

見ていただきありがとうございます。
この文の一文一文が、どういう働きをしているのかがよくわかりません。
英単語のプログラムを作っています。
一応、ファイルの中にある文を、@monndaiのなかなどにいれて表示させようとするプログラムの一部です。

ruby

1def yomikomi() 2 i = 0 3 j = 0 4 @moji =[] 5 f = open("./dat/#{@jikkoufile}","r") 6 while text = f.gets do 7 @moji[i] = text.chomp 8 i += 1 9 end 10 f.close 11 @mondaisu = i/2 12 while j <= i/2 13 eval("@q#{j} = [@moji[j*2+0],@moji[j*2+1]]") 14 j += 1 15 end 16 17 18 q = [] 19 eval("q = @q#{rand(@mondaisu)}.clone") 20 @mondai = q[0] 21 @kotae = q[1] 22 23 @matigai = open("./dat/matigai.dat","a") 24end 25 26

これ以外の文の書き方とかってありますか。
あと、eval が具体的にどんな働きをしているのかなど教えていただけると嬉しいです。
---追記
日本語を表示して、その英単語を入力して、それが正しいかどうかを判断するというプログラムを作りたいです。
原型はできているのですが、今のままだと、ファイルを、一つしか選択できないので、複数のファイルを一気に読みこんで、ランダムに表示させるということがしたいです。

休み vacation takeの過去 took catchの過去 caught seeの過去 saw 魚釣りに行く go fishing 庭 garden 伝統的な traditional 初めて for the first time am,isの過去 was areの過去 were

問題の文はこのように、日本語、英語の順に1行ずつかいてあります。

コードを全文出します。

ruby

1#! ruby -Ks 2require "color_echo" 3 4@score = 0 5@count = 0 6@naoshi = Array.new 7@jikkoufile = Array.new 8 9def yomikomi() 10 i = 0 11 j = 0 12 @moji =[] 13 f = open("./dat/#{@jikkoufile}","r") 14 while text = f.gets do 15 @moji[i] = text.chomp 16 i += 1 17 end 18 f.close 19 @mondaisu = i/2 20 while j <= i/2 21 eval("@q#{j} = [@moji[j*2+0],@moji[j*2+1]]") 22 j += 1 23 end 24 25 26 q = [] 27 eval("q = @q#{rand(@mondaisu)}.clone") 28 @mondai = q[0] 29 @kotae = q[1] 30 31 @matigai = open("./dat/matigai.dat","a") 32end 33 34 35def hon 36 37 filenames = Dir.open("dat").to_a 38 puts filenames 39 puts "reset" 40 41 puts "\n\nやりたいファイルを選択してください。" 42 @jikkoufile << gets.chomp 43 puts @jikkoufile 44 while true do 45 if filenames.include?(@jikkoufile) 46 puts " ほかにもファイルを選択しますか。 y or n" 47 filesentaku = gets.chomp 48 if filesentaku == "y" 49 puts "入力してください。" 50 jikkoufile2 = gets.chomp 51 unless filenames.include?(jikkoufile2) 52 CE.once.fg :red 53 puts "そのファイルは存在しません。" 54 else 55 @jikkoufile.push(jikkoufile2) 56 end 57 redo 58 elsif filesentaku == "n" 59 break 60 else 61 CE.once.fg :red 62 puts "入力するならyを、しないならnを入力してください。" 63 redo 64 end 65 end 66 67 if @jikkoufile == "reset" 68 puts "Reset matigai.dat" 69 File.open("dat/matigai.dat","w") 70 sleep 2 71 exit 72 end 73 CE.once.fg :red 74 puts "再入力してください" 75 @jikkoufile << gets.chomp 76 end 77 78 puts "何回実行しますか?" 79 @a = gets.chomp.to_i 80 puts "次の日本語を英語に直しなさい" 81 count = 0 82 while true do 83 yomikomi 84 puts @mondai 85 s = gets.chomp 86 87 puts "正解は#{@kotae}です。" 88 sleep 1 89 90 if s == @kotae 91 puts "正解です " 92 @score = @score + 1 93 else 94 @count = @count + 1 95 CE.once.fg :red 96 puts "間違いです。\n" 97 @naoshi.push(@mondai,@kotae) 98 end 99 count = count + 1 100 if count >= @a 101 puts "\n\n終了です","\n#{@a}問中、#{@score}問正解しました" 102 unless @naoshi.empty? #empty? は何もなかったらtrueを返す 103 CE.once.fg :index47 104 puts "間違えた問題 復習しておこう!" 105 CE.bg :blue 106 puts @naoshi 107 @matigai.puts @naoshi 108 else 109 CE.rainbow 110 puts "----------------------------------------------" 111 puts "全問正解!!おめでとう!" 112 puts "----------------------------------------------" 113 end 114 exit 115 end 116 end 117end 118hon 119

インデントとかをうまく使えてなくて読みにくいですが、すいません。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2017/04/18 12:23

これだけだと質問者様の意図を理解するのが難しいので可能であれば、どういった結果になったらよいのかという実行結果例を教えていただけると幸いです。
gouf

2017/04/18 22:11

プログラム中で「実行ファイル」「間違いファイル」なるものを読み込んでる & 書き込んでいるように見られますが、そのファイルを公開することはできますか
yusuke.

2017/04/19 08:41

実行ファイルを見せることは可能です。
yusuke.

2017/04/19 08:42

全部の文を表示した方がいいですか。
yusuke.

2017/04/19 08:47

全部のソースを表示した方が
guest

回答2

0

提示されたコードに可能な限りコメントをつけてみました

ruby

1def yomikomi() 2 # インデックスの初期化 3 i = 0 4 j = 0 5 6 # 配列の初期化 7 @moji =[] 8 9 # 実行ファイルのオープン(読み取り設定) 10 f = open("./dat/#{@jikkoufile}", 'r') 11 12 # ファイル終端までテキストの読み込み 13 while text = f.gets do 14 # 配列に実行ファイルの行を読み込み(読み込み後は次の行を指す) 15 @moji[i] = text.chomp 16 # インデックスのインクリメント 17 i += 1 18 end 19 # 読み込み終わったので実行ファイルの開放 20 f.close 21 22 # 問題数を計算して代入 23 @mondaisu = i/2 24 25 # 問題数の分だけ問題と答えを読み込み 26 while j <= i/2 27 # インスタンス変数にデータを配列として代入 28 # @q0 = [問題, answer] 29 # @q1 = [問題2, answer2]... 30 # (データの中身は不明) 31 eval("@q#{j} = [@moji[j*2+0],@moji[j*2+1]]") 32 j += 1 33 end 34 35 36 # 問題と答えを代入する配列を初期化 37 q = [] 38 # 問題集の中から問題と答えをランダムに抽出 39 eval("q = @q#{rand(@mondaisu)}.clone") 40 @mondai = q[0] 41 @kotae = q[1] 42 43 # 間違いをファイルに記録できるよう、ファイルを追加モードで開く 44 @matigai = open("./dat/matigai.dat", 'a') 45end 46

2点、気になるところがありました

可能であれば、eval の使用は極力控えたほうがいいかもしれません
だいたいは他の方法で実装できますし、また、想定・意図しない入力によってセキュリティ的に問題のあるコードが実行されてしまうかもしれません

それと、インスタンス変数(@variable_name)を、あたかもグローバル変数かのように使用するのも、コードの可読性・メンテナンス性の面から避けられるべきでしょう


仮に私が書くとすればこう書く、といった例です
(※イメージを伝えたかったので、実際には動かない部分があるかもしれません)

ruby

1class QA 2 # 問題と答えのペアを保持する雛形 3 QASet = Struct.new(:question, :answer) 4 5 # クラスのインスタンス生成時の初期設定 6 def initialize(qa_file_name = 'qa.txt') 7 @question_and_answers = read_question_and_answers 8 @questions_count = @question_and_answers.size 9 @qa_file_name = qa_file_name 10 end 11 12 # 問題集の中から問題と答えをランダムに抽出 13 def take_question_and_answer_set 14 questions_index = rand(@questions_count) 15 @question_and_answers[questions_index] 16 end 17 18 # 問題と答えのペアを一行ごとに表示 19 def print_question_and_answers 20 @question_and_answers.each do |qa_set| 21 puts "#{qa_set.question}:\t#{qa_set.answer}" 22 end 23 end 24 25 private 26 27 def read_question_and_answers 28 # 問題と答えのファイルの読み込み 29 question_and_answers_file = File.read("./dat/#{@qa_file_name}") 30 31 # 読み込んだデータを問題と答えのセット、その集合に変換 32 question_and_answers = 33 question_and_answers_file 34 .lines 35 .each_slice(2) { |question, answer| QASet.new(question, answer) } 36 37 question_and_answers 38 end 39 40 # def wrong_answers_file 41 # # 間違いをファイルに記録できるよう、ファイルを追加モードで開く 42 # open('./dat/matigai.dat', 'a') 43 # end 44end 45 46qa = QA.new 47qa_set = qa.take_question_and_answer_set 48p qa_set.question # => 日本語単語 49p qa_set.answer # => 英語単語 50 51# qa.print_question_and_answers # 問題と答えのセットを一覧表示

以上、なにか参考になれば幸いです


Links

投稿2017/04/19 18:25

gouf

総合スコア2321

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

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

yusuke.

2017/04/20 06:28

ありがとうございます。 なぜevalはあまりつかはないほうがいいのでしょうか。
yusuke.

2017/04/20 06:34

追記しました。また見ていただけると嬉しいです。
guest

0

ベストアンサー

単語テスト1.txt

休み vacation takeの過去 took catchの過去 caught seeの過去 saw 魚釣りに行く go fishing 庭 garden 伝統的な traditional 初めて for the first time am,isの過去 was areの過去 were

単語テスト2.txt

ナポリタン パスタ

単語テスト3.txt

らーめん しお

Ruby

1#encoding: utf-8 2 3def wordTest(array) 4 puts "次の問題に答えよ" 5 loop{ 6 all_clear = 0 7 huse = [] 8 puts "" 9 array.each do |q, a| 10 print "#{q}:" 11 answer = gets.chomp.to_s 12 if answer == a then 13 puts "〇正解!" 14 all_clear += 1 15 else 16 puts"X不正解!" 17 print"正解を見ますか?[y/n]:" 18 userselect = gets.chomp.to_s.tr("Y", "y") 19 if userselect == "y"; puts a; end 20 huse << [q, a] 21 end 22 puts "-" * 20 23 puts "" 24 end 25 if all_clear == array.length 26 puts "全問正解!!" 27 break 28 else 29 puts "#{array.length}問中#{all_clear}問正解しました!!" 30 puts "間違った問題は復習しておこう!!" 31 array = huse 32 end 33 } 34end 35 36def selectFiles() 37 puts "単語テストをしますか?[y/n]" 38 userselect = gets.chomp.to_s.tr("N", "n") 39 if userselect == "n"; exit; end 40 puts "" 41 files = Dir.glob("問題集/*.txt") 42 if files.none?; puts "問題集がありません。"; exit; end 43 puts "やりたい問題を選択してください。" 44 files.each_with_index do |element, i| 45 puts "#{i + 1}:\s#{File.basename(element)}" 46 end 47 userselect = gets.chomp.to_s.split("\s").map{|e| e.to_i - 1} 48 puts "" 49 tmp = [] 50 userselect.each do |element| 51 if element > files.length || element < 0 52 element = 1 53 end 54 tmp << File.read(files[element]).chomp.split("\n").each_slice(2).to_a 55 end 56 return tmp.flatten(1).shuffle 57end 58 59wordTest(selectFiles())

単語試験プログラムを作ってみました。
問題集というフォルダの中に単語テスト.txtなどの
問題が書かれたテキストファイルを入れて使います。

単語テスト.txtの選択は半角英数字で区切り文字はスペースです。

可読性が高いとか処理が速くなるなどのメリットは一切ありません。

#補足

Ruby

1userselect = gets.chomp.to_s.split("\s").map{|e| e.to_i - 1}
全体の意味: 選択してもらった結果をuserselectに入れる。 細かい説明: 1.利用者は表示された問題集の一覧から「半角英数字」でファイルを選択する。  結果はこのようになる「1 2 3 4 5」(数字と数字の間は半角スペース。) 2.getsで入力された文字列を取得。末尾の改行文字をchompでとってto_sで文字列化する。 3.splitを使って入力された文字列を半角スペースで区切る。  結果はこのようになる「[1, 2, 3, 4, 5]」(配列になる。) 4.mapは配列の要素を入れ替える時に使う。今回は、3の配列の要素が1つずつeに入る。  e = e.to_i - 1みたいなことが行われて、3の配列の要素が全て交換される。 5.最終的にuserselectは  userselect = [0, 1, 2, 3, 4] みたいな配列になる。

 

投稿2017/04/19 11:21

編集2017/04/21 10:00
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

yusuke.

2017/04/20 06:30

回答ありがとうございます。 ごめんなさい。質問の仕方が悪かったです。 このプログラムで、日本語を表示して、その英単語を入力して正解かどうかを判断するというプログラムなんです。 追記しときます。
退会済みユーザー

退会済みユーザー

2017/04/20 08:46

いえいえ。追記された内容に対応しました。
yusuke.

2017/04/21 07:09

回答ありがとうございます。 userselect = gets.chomp.to_s.split("\s").map{|e| e.to_i - 1} この文の意味がよくわかりません。教えてください。
退会済みユーザー

退会済みユーザー

2017/04/21 10:00 編集

見た目を重視して、ファイルを選択するときの数字を1からにしています。 配列は0から始まるので配列の1番目は0番です。 userselect = gets.chomp.to_s.split("\s").map{|e| e.to_i - 1} この部分で利用者に入力してもらった数字から1引くことで 配列の数字と合わせています。 puts "#{i + 1}:\s#{File.basename(element)}"を puts "#{i}:\s#{File.basename(element)}"とすることで userselect = gets.chomp.to_s.split("\s").map(&:to_i) にできます。(-1しなくてよくなる。) 回答にも説明を追加しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問