Newer
Older
Ruby / keisan7.rb
@SAITO Minoru SAITO Minoru on 24 Jan 2 KB 2026-01-24 15:53:13
require "curses"
def keisan(shiki, ichi=0, ans=0.0)
  suuji,enzan = [], []
  yuusen = {'+'=>1,'-'=>1,'*'=>2,'/'=>2 }
  tekiyou = ->{
    b, a, e, = suuji.pop, suuji.pop, enzan.pop
    suuji << (e=='+' ? a+b : e=='-' ? a-b : e=='*' ? a*b : a/b)}
  yomu_atai = lambda do
    ichi += 1 while shiki[ichi]==' '
    raise "式の途中で終わりました" unless shiki[ichi]
    if shiki[ichi,3] && shiki[ichi,3].downcase=="ans"
      next [ans, ichi+3]
    end
    if shiki[ichi]=='-'
      ichi += 1
      v, ichi = yomu_atai.call
      next [-v, ichi]
    end
    if shiki[ichi]=='('
      v, ichi2 = keisan(shiki, ichi+1, ans)
      raise "閉じカッコ ) がありません" unless shiki[ichi2]==')'
      next [v, ichi2+1]
    end
    hajime=ichi
    ichi += 1 while shiki[ichi] && shiki[ichi]=~/[0-9.]/
    raise "数値が見つかりません" if hajime==ichi
    [shiki[hajime...ichi].to_f, ichi]
  end
  atai_hoshii=true
  while ichi < shiki.length
    ichi += 1 while shiki[ichi]==' '
    break if ichi>=shiki.length || shiki[ichi]==')'
    if atai_hoshii
      v, ichi = yomu_atai.call
      suuji << v
      atai_hoshii=false
      next
    end
    e=shiki[ichi]
    raise "演算子が不正です" unless yuusen[e]
    while enzan.any? && yuusen[enzan[-1]] && yuusen[enzan[-1]] >= yuusen[e]
      tekiyou.call
    end
    enzan << e
    ichi += 1
    atai_hoshii=true
  end
  tekiyou.call while enzan.any?
  [suuji[0], ichi]
end
include Curses
init_screen
cbreak
noecho
curs_set(0)
nyuryoku=""
messeji="Enter=計算 / BS=削除 / Ctrl+L=クリア / q=終了"
kekka, ans ="", 0.0
begin
  loop do
    clear
    setpos(0,0)
    addstr("curses電卓(+-*/() 小数)"[0,cols-1])
    setpos(1,0)
    addstr(messeji[0,cols-1])
    setpos(2,0)
    addstr(("> "+nyuryoku)[0,cols-1])
    setpos(3,0)
    addstr(("= "+kekka)[0,cols-1])
    key=getch
    case key
    when 'q','Q' then break
    when 10,13
      begin
        shiki = nyuryoku.strip
        shiki = ans.to_s if shiki.empty?
        shiki = ans.to_s + shiki if shiki.start_with?('+','*','/')
        kotae, owari = keisan(shiki, 0, ans)
        owari += 1 while shiki[owari]==' '
        raise "式の後ろに余計な文字があります" if owari < shiki.length
        ans = kotae
        kekka, nyuryoku, messeji = kotae.to_s, "", "計算しました (ans=#{ans} )"
      rescue => e
        kekka, nyuryoku, messeji = "", "", "エラー: #{e.message}"
      end
    when 12
      nyuryoku, kekka, messeji = "", "", "クリアしました"
    when KEY_BACKSPACE,127,8
      nyuryoku = nyuryoku[0...-1]
    when Integer
      nyuryoku << key.chr if key>=32 && key<127
    when String
      nyuryoku << key if key.ord>=32 && key.ord<127
    end
  end
ensure
  close_screen
end