16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル
"括弧・演算子優先計算"
この発言に対し以下のコメントが寄せられています
#00667 J-OH! さん 括弧・演算子優先計算/修正
◆説明◆
Edit などに入力された ((8+10/5)*2)-((20-15)*2) などという
計算式を、括弧優先・演算子優先に従って計算します。
プログラマの間では、一般的に "逆ポーランド法" が知られてい
ますが、配布することを前提としたソフトでユーザー指定の式に対
してこのような処理が行われるような場合、その Readme.txt など
に「・・・なお、計算式の記述は逆ポーランド法で行って下さい」
というのは、ちょっと無理があるかも知れません。
(そんなソフトないかな (^^; )
◆使用法◆
Edit1 に計算式を入力し、その答えを Edit2 に表示させるような
場合、
Edit2.Text := MainCalk(Edit1.Text);
として御使用してみて下さい。
◆注意◆
・入力される計算式は、半角文字のみで、スペースは使用しない
ようにして下さい。
・コンバートエラー等、発生しうるエラーには対応していません。
(・それ以前に、バグがあるかも知れません。 (;_;) )
◆サンプルコード◆
unit Unit1;
interface
・
・
type
TForm1 = class(TForm)
・
・
private
{ Private 宣言 }
function MainCalk(Value: String): String; // ← 記入
function SubCalk(Value: String): String; // ← 記入
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
function TForm1.MainCalk(Value: String): String;
var
Moto, Moji, Frnt, Back, data: String;
Stt, Max, Cnt: Integer;
Fin: Boolean;
begin
Moto := Value;
Fin := False;
while Fin = False do
begin
Max := 0;
Cnt := 0;
// 最内の () のスタート位置判定
for Stt := 1 to Length(Moto) do
begin
Moji := Copy(Moto, Stt, 1);
if Moji = '(' then
begin
inc(Cnt);
if Cnt > Max then Max := Cnt;
end else
if Moji = ')' then dec(Cnt);
end;
// 入力データに () がある場合の処理
if Max <> 0 then
begin
Stt := 1;
Cnt := 0;
Frnt := '';
Back := '';
data := '';
{ 最内の "(" の位置まで、変数 Frnt に一文字ずつ代入
しながら進む}
while Cnt < Max do
begin
Moji := Copy(Moto, Stt, 1);
if Moji = '(' then inc(Cnt) else
if Moji = ')' then dec(Cnt);
if Cnt < Max then Frnt := Frnt + Moji;
inc(Stt);
end;
// 最内の () 内を計算
Moji := Copy(Moto, Stt, 1);
while Moji <> ')' do
begin
data := data + Moji;
inc(Stt);
Moji := Copy(Moto, Stt, 1);
end;
data := SubCalk(data);
inc(Stt);
Back := Copy(Moto, Stt, Length(Moto)-Stt+1);
{ 変数 Moto に、Moto の最内の () 内だけを計算した形の
文字列を代入 }
Moto := Frnt + data + Back;
end else
begin
Moto := SubCalk(Moto);
Fin := True;
end;
end;
Result := Moto;
end;
function TForm1.SubCalk(Value: String): String;
var
Stt, Bgn: Integer;
Moto, data, Moji, Kigou, Frnt, Back: String;
Usen, Fin: Boolean;
Fext, Bext: Extended;
begin
Moto := Value;
Fin := False;
while Fin = False do
begin
Usen := False;
for Stt := 1 to Length(Moto) do
begin
Moji := Copy(Moto, Stt, 1);
if (Moji = '*') or (Moji = '/') then Usen := True;
end;
if Usen = True then
begin
Stt := 0;
Moji := '';
while (Moji <> '*') and (Moji <> '/') do
begin
inc(Stt);
Moji := Copy(Moto, Stt, 1);
end;
Kigou := Moji;
data := '';
Bgn := Stt-1;
Moji := Copy(Moto, Bgn, 1);
while (Moji <> '+') and (Moji <> '-') and
(Moji <> '*') and (Moji <> '/') and (Bgn > 0) do
begin
data := Moji + data;
dec(Bgn);
if Bgn > 0 then Moji := Copy(Moto, Bgn, 1);
end;
Fext := StrToFloat(data);
Frnt := Copy(Moto, 1, Bgn);
data := '';
Bgn := Stt+1;
Moji := Copy(Moto, Bgn, 1);
while (Moji <> '+') and (Moji <> '-') and
(Moji <> '*') and (Moji <> '/') and
(Bgn <= Length(Moto)) do
begin
data := data+Moji;
inc(Bgn);
if Bgn <= Length(Moto) then Moji := Copy(Moto, Bgn, 1);
end;
Bext := StrToFloat(data);
Back := Copy(Moto, Bgn, Length(Moto)-Bgn+1);
if Kigou = '*' then data := FloatToStr(Fext*Bext) else
if Bext = 0 then data := '0' else
data := FloatToStr(Fext/Bext);
Moto := Frnt + data + Back;
end else
begin
Fin := True;
for Stt := 1 to Length(Moto) do
begin
Moji := Copy(Moto, Stt, 1);
if (Moji = '+') or (Moji = '-') then Fin := False;
end;
if Fin = False then
begin
Stt := 0;
Moji := '';
while (Moji <> '+') and (Moji <> '-') do
begin
inc(Stt);
Moji := Copy(Moto, Stt, 1);
end;
Kigou := Moji;
data := '';
Bgn := Stt-1;
Moji := Copy(Moto, Bgn, 1);
while (Moji <> '+') and (Moji <> '-') and
(Moji <> '*') and (Moji <> '/') and
(Bgn > 0) do
begin
data := Moji + data;
dec(Bgn);
if Bgn > 0 then Moji := Copy(Moto, Bgn, 1);
end;
Fext := StrToFloat(data);
Frnt := Copy(Moto, 1, Bgn);
data := '';
Bgn := Stt+1;
Moji := Copy(Moto, Bgn, 1);
while (Moji <> '+') and (Moji <> '-') and
(Moji <> '*') and (Moji <> '/') and
(Bgn <= Length(Moto)) do
begin
data := data+Moji;
inc(Bgn);
if Bgn <= Length(Moto) then
Moji := Copy(Moto, Bgn, 1);
end;
Bext := StrToFloat(data);
Back := Copy(Moto, Bgn, Length(Moto)-Bgn+1);
if Kigou = '+' then data := FloatToStr(Fext+Bext) else
data := FloatToStr(Fext-Bext);
Moto := Frnt + data + Back;
end;
end;
end;
Result := Moto;
end;
J-OH!(VEC05267)
Original document by J-OH! 氏 ID:(VEC05267)
ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。
Copyright 1996-2002 Delphi Users' Forum
|