Newer
Older
Ruby / keisan7.rb
@TAKEDA Kodai TAKEDA Kodai on 28 Jan 2 KB 2026-01-28 07:53:46
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
require "curses"
def keisan(shiki, ichi=0, ans=0.0)
  suuji=[]; enzan=[]; yuusen={'+'=>1,'-'=>1,'*'=>2,'/'=>2}
  tekiyou = ->{
    b=suuji.pop; a=suuji.pop; e=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 = kotae.to_s; nyuryoku=""; messeji="計算しました(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