本日の基礎練習問題(22/3/31)

# 問題
以下の仕様を満たすアプリケーションを作成してください。また、必ず注意書きを読んでから作成に取り掛かってください。

**仕様**
プログラムを実行すると、以下の3つの選択肢が表示され、直後にユーザーに対して値の入力を求めること。
[1] : 商品を登録する
[2] : 商品の一覧を確認する
[3] : アプリを終了する
[1]を選択した場合は、商品名、販売価格、仕入れ値を入力させ、保存する。
[2]を選択した場合は、保存された全ての商品情報（商品名・販売価格・仕入れ値）を商品ごとに一覧表示する。
[3]を選択した場合は、アプリケーションを終了する。
アプリケーションを終了するまで、処理を繰り返すこと。

**注意**
雛形を使用すること
引数は雛形で考慮していないため、必要に応じて引数を設定すること

**雛形**
```.rb
def register_item(registered_item)
  # 商品名・販売価格・仕入れ値の入力を促し、入力された値をハッシュオブジェクトで管理する
  puts "商品名を入力してください："
  puts "販売価格を入力してください："
  puts "仕入れ値を入力してください："
  line = "---------------------------"

  # 入力された値（ハッシュオブジェクトで管理している値）を表示する
  puts "商品名 : \n#{line}"
  puts "販売価格 : 円\n#{line}"
  puts "仕入れ値 : 円\n#{line}"
end

def check_items(registered_item)
  # 保存された全ての商品情報（商品名・販売価格・仕入れ値）を商品ごとに一覧表示する
  line = "---------------------------"
  puts "【商品一覧】\n#{line}"

  registered_item.each do |item|
    puts "商品名："
    puts "販売価格：円"
    puts "仕入れ値：円"
  end
end

def end_program
  exit
end

def exception
  puts "入力された値は無効な値です"
end

item_list = []         # 配列オブジェクトitem_listの生成

while true do
  # メニューの表示
  puts "商品数: #{item_list.length}"
  puts "[1]商品を登録する"
  unless item_list.empty?
    puts "[2]商品の一覧を確認する"
  end
  puts "[3]アプリを終了する"

  input = gets.to_i

  if input == 1 then
    item_list = register_item(item_list)  # register_itemメソッドの呼び出し
  elsif input == 2 then
    check_items(item_list)     # check_itemsメソッドの呼び出し
  elsif input == 3 then
    end_program     # end_programメソッドの呼び出し
  else
    exception       # exceptionメソッドの呼び出し
  end
end
```

# 私の回答
```.rb
def register_item(registered_item)
  # 商品名・販売価格・仕入れ値の入力を促し、入力された値をハッシュオブジェクトで管理する
  item = {}
  puts "商品名を入力してください："
  item[:name] = gets.chomp
  puts "販売価格を入力してください："
  item[:selling_price] = gets.to_i
  puts "仕入れ値を入力してください："
  item[:cost_price] = gets.to_i
  line = "---------------------------"

  # 入力された値（ハッシュオブジェクトで管理している値）を表示する
  puts "商品名 : #{item[:name]}\n#{line}"
  puts "販売価格 : #{item[:selling_price]}円\n#{line}"
  puts "仕入れ値 : #{item[:cost_price]}円\n#{line}"

  registered_item << item

end

def check_items(registered_item)
  # 保存された全ての商品情報（商品名・販売価格・仕入れ値）を商品ごとに一覧表示する
  line = "---------------------------"
  puts "【商品一覧】\n#{line}"

  registered_item.each do |item|
    puts "商品名：#{item[:name]}"
    puts "販売価格：#{item[:selling_price]}円"
    puts "仕入れ値：#{item[:cost_price]}円\n#{line}"
  end
end

def end_program
  exit
end

def exception
  puts "入力された値は無効な値です"
end

item_list = []         # 配列オブジェクトitem_listの生成

while true do
  # メニューの表示
  puts "商品数: #{item_list.length}"
  puts "[1]商品を登録する"
  unless item_list.empty?
    puts "[2]商品の一覧を確認する"
  end
  puts "[3]アプリを終了する"

  input = gets.to_i

  if input == 1 then
    item_list = register_item(item_list)  # register_itemメソッドの呼び出し
  elsif input == 2 then
    check_items(item_list)     # check_itemsメソッドの呼び出し
  elsif input == 3 then
    end_program     # end_programメソッドの呼び出し
  else
    exception       # exceptionメソッドの呼び出し
  end
end
```
# 解説
まず空のハッシュを変数itemに代入する
その後ユーザーから入力された値をitemキーに代入する
表示はキーを利用して出力し、ユーザーから入力された情報が入っているitemハッシュをregistered_item配列に追加する。

一覧表示の部分はハッシュキーを使用し繰り返し表示する

その後は雛形通りの処理を行う

# 模範回答
```.rb
def register_item(registered_item)
  # 商品名・販売価格・仕入れ値の入力を促し、入力された値をハッシュオブジェクトで管理する
  item = {}
  puts "商品名を入力してください："
  item[:name] = gets.chomp
  puts "販売価格を入力してください："
  item[:selling_price] = gets.to_i
  puts "仕入れ値を入力してください："
  item[:cost_price] = gets.to_i
  line = "---------------------------"

  # 入力された値（ハッシュオブジェクトで管理している値）を表示する
  puts "商品名 : #{item[:name]}\n#{line}"
  puts "販売価格 : #{item[:selling_price]}円\n#{line}"
  puts "仕入れ値 : #{item[:cost_price]}円\n#{line}"

  # ハッシュを配列オブジェクトに追加する
  registered_item << item

  # registered_itemをメソッドの呼び出し元に返す
  return registered_item
end

def check_items(registered_item)
  # 保存された全ての商品情報（商品名・販売価格・仕入れ値）を商品ごとに表示する
  line = "---------------------------"
  puts "【商品一覧】\n#{line}"

  registered_item.each do |item|
    puts "商品名：#{item[:name]}"
    puts "販売価格：#{item[:selling_price]}円"
    puts "仕入れ値：#{item[:cost_price]}円\n#{line}"
  end
end

def end_program
  exit
end

def exception
  puts "入力された値は無効な値です"
end

item_list = []              # 配列オブジェクトitem_listの生成

while true do
  # メニューの表示
  puts "商品数: #{item_list.length}"
  puts "[1]商品を登録する"
  unless item_list.empty?
    puts "[2]商品の一覧を確認する"
  end
  puts "[3]アプリを終了する"

  input = gets.to_i

  if input == 1 then
    item_list = register_item(item_list)  # register_itemメソッドの呼び出し
  elsif input == 2 then
    check_items(item_list)          # check_itemsメソッドの呼び出し
  elsif input == 3 then
    end_program               # end_programメソッドの呼び出し
  else
    exception            # exceptionメソッドの呼び出し
  end
end
```
# 模範解説
まずは、コード全体を上から順に簡単に説明します。
1〜22行目で、register_itemメソッドを定義しています。このメソッドで、商品情報の登録を行っています。
24〜34行目で、check_itemsメソッドを定義しています。このメソッドで、登録された商品情報の一覧を表示させています。
36〜38行目で、end_programを定義しています。このメソッドで、プログラム自体を終了させます。
40〜42行目で、exceptionを定義しています。このメソッドで、不正な値が入力されたときに警告が出るようにしています。

46〜66行目で、入力された数値によって条件分岐を行い、プログラムが終了されるまで処理を繰り返しています。
処理の中で、ここまでに定義したメソッドを呼び出しています。

次に、処理の順にコードを説明します。
まず、44行目で空の配列item_listを定義しています。この配列に商品情報をストックしていくことになります。

48〜53行目でメニューの表示を行っています。
55行目で、ユーザーに数値の入力を求めています。ここで入力された数値によって、57〜65行目で条件分岐を行っています。

続いて、register_itemメソッド内のコードについて説明します。
3行目で、itemというハッシュを定義しています。
4〜9行目で、それぞれキーを指定し、入力された値をitemハッシュの中に格納しています。
13〜15行目で、itemハッシュの中からキーを指定し、値を取り出して、表示させています。
18行目で、registered_itemオブジェクト、つまり、引数として渡された配列item_listの中にitemハッシュの情報を格納しています。
21行目で、更新されたregistered_itemオブジェクトをregister_itemメソッドの呼び出し元に返しています。
ここまでで配列item_listの中に新しい商品情報がストックされることになります。

続いて、check_itemsメソッド内のコードについて説明します。
29〜33行目で、配列の中からハッシュ形式の要素を1つずつ取り出し、キーを指定することでハッシュの中から値を取り出して表示させています。
この処理は、配列の要素の数だけ繰り返します。
# 感じたこと
今回は雛形がしっかりと用意されていたので、不足している部分を補うことで処理が完成した。
それでも配列やハッシュ、キーバリューの復習をしながらの回答になっていたので
今後は復習などは行わないでパッと記述できるよう修行していきたい。
また商品登録のreturn部分は必要なのか？と疑問に思ったので調べて理解を深めたい。

アドバイスやご指摘等ございましたらぜひお願いします！！

以上