文字列で四則演算を行うプログラム。
動作はするが、ロジックはあまりきれいではない。時間をおいて作り直したい。// コマンドライン電卓
#runtime "hsp3cl"
#module
// 文字列置換命令
// v1 : 置換する文字型変数
// s1 : 置換する文字列
// i1 : 開始インデックス
// i2 : 消去する文字列の数
#deffunc replace var v1, str s1, int i1, int i2, local s
sdim s, 20
if i1 : memcpy s, v1, i1, 0, 0
s += s1
memcpy s, v1, strlen(v1) - i1 - i2, i1 + strlen(s1), i1 + i2
v1 = s
return
#deffunc doCalc var s1, int i1, local target, local right, local r, local left, local l, local type, local i
target = s1
type = peek(target, i1)
result = ""
left = 0
right = 0
l = 0
r = 0
repeat i1
i = peek(target, i1 - cnt - 1) - '0'
if (0 <= i)&(i <= 9) {
repeat cnt
i *= 10
loop
left += i
l++
} else {
break
}
loop
repeat strlen(target) - i1 - 1
i = peek(target, i1 + cnt + 1) - '0'
if (0 <= i)&(i <= 9) {
r++
right = right * 10 + i
} else {
break
}
loop
if type != '-' {
if (l == 0)|(r == 0) {
error = "数式が不正です"
return 0
}
}
switch type
case '+'
result = str(left + right)
swbreak
case '-'
if r == 0 {
error = "数式が不正です"
return 0
}
if l == 0 {
result = "noExchange"
} else {
result = str(left - right)
}
swbreak
case '*'
result = str(left * right)
swbreak
case '/'
if right {
result = str(left / right)
} else {
error = "ゼロでは除算できません"
}
swbreak
default
error = "数式が不正です"
swbreak
swend
if error != "" : return 0
if result == "noExchange" : return 1
replace s1, result, i1 - l, l+1+r
return 0
// 内部で再帰的に用いる命令
// 括弧を判別して括弧内を対象に自らを呼び出す
#defcfunc subCalc str s1, local cmd, local i, local l, local s
cmd = s1
repeat
i = instr(cmd, 0, "(")
if i >= 0 {
l = instr(cmd, i+1, ")")
s = strmid(cmd, i + 1, l)
replace cmd, subCalc(s), i, l + 2 // ( と ) の分で+2
} else {
break
}
loop
// 括弧がない場合
// *, /を計算
repeat
i = instr(cmd, 0, "*")
l = instr(cmd, 0, "/")
if (i == -1)&(l == -1) : break
if (i == -1)&(0 <= l) : i = l
if 0 <= i {
if (0 <= l)&(l < i) : i = l // i にはiとlのうち小さい方が格納される
}
doCalc cmd, i // インデックスiにある演算子で演算を行う
if error != "" : break
loop
if error != "" : return error
// +, -を計算
k = 0
repeat
i = instr(cmd, k, "+")
l = instr(cmd, k, "-")
if (i == -1)&(l == -1) : break
if (i == -1) : i = l
if (0 <= l)&(0 <= i)&(l < i) : i = l
i += k
doCalc cmd, i // インデックスiにある演算子で演算を行う
if stat : k = i + 1
if error != "" : break
loop
if error != "" : return error
return cmd
// 外部から呼び出す命令 整数の数式を文字列として渡す
#deffunc calc str s1
error = ""
// 括弧の個数を調べる
lt = 0 : gt = 0
cmd = s1
repeat strlen(cmd)
tmp = peek(cmd, cnt)
if tmp == '(' : lt++
if tmp == ')' : gt++
loop
if lt != gt : error = "正しい数式ではありません"
if error != "" : return error
mes "Q:"+cmd
return subCalc(s1)
#global
calc "10*10+8/2*3"
mes " = " + refstr
2007年5月12日土曜日
インタプリンタ電卓もどき
登録:
コメントの投稿 (Atom)
0 件のコメント:
コメントを投稿