![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?8acaa2e)
数字と演算子をそれぞれ入力し、優先順位の高い順に四則演算させるにはどのような考え方をすればよいのでしょうか。
数字をa[7]とおいて、演算子をop[7]としてそれぞれ配列に格納しましたが、そこから先に進めません。
オペランドと演算子の組み合わせならば優先順に計算してくれるのはわかっていますが、オペランドと演算子を格納した配列では上手く行きません。
実は既に全ての演算子の組み合わせをIfで表示させるプログラムを根性で作ったのですが、最適解を知りたいです。
言語はCでvisualstudioを使っております。
条件はn回数字を入力したらn-1回演算子を入力し、n回目に=を入力する。nの最大値は7とする。です。
だらだらと見辛い文章で申し訳ありませんが、何卒宜しくお願いします。
A 回答 (8件)
- 最新から表示
- 回答順に表示
No.8
- 回答日時:
> だめだめじゃん > 自分
> 乗除が続いたときうまくいかない。
ということで、修正しました。
int* pLeft = &a[0];
for (int i = 0; i < sizeof(op)/sizeof(op[0]); ++i)
{
switch (op[i])
{
case '*':*pLeft *= a[i+1];break;
case '/':*pLeft /= a[i+1];break;
default:pLeft = &a[i+1];break;
}
}
int result = a[0];
for (int i = 0; i < sizeof(op)/sizeof(op[0]); ++i)
{
switch (op[i])
{
case '+':result += a[i+1];break;
case '-':result -= a[i+1];break;
default:break;
}
}
こんなんでいかがでしょう。
最適とは言えないでしょうけど...
優先度グループが二つしかないから2回のループ、グループが3つなら3回のループになるけど、
3回のループを回すなら、構文解析ツリーにくみなおす方がきれいかな。
No.6
- 回答日時:
>優先順位の高い順に四則演算させるには
四則演算は加減乗除で、その中で優先順位があるは加減と乗除で乗除を先に行う必要があるだけ。
簡単に考えれば、一回目のループで乗除を行い、二回目のループで加減を行えばよい。
一回目の演算結果は演算子の左側に残しておく。
二回目のループでは有効な演算の右側のオペランドを順次演算していく。
実際のプログラムは以下の通り。
int a[] = {1, 2, 3, 4, 5, 6, 7};
char op[] = {'+', '*', '-', '/', '+', '*'};
for (int i = 0; i < sizeof(op)/sizeof(op[0]); ++i)
{
switch (op[i])
{
case '*': a[i] *= a[i+1]; break;
case '/': a[i] /= a[i+1]; break;
default: break;
}
}
int result = a[0];
for (int i = 0; i < sizeof(op)/sizeof(op[0]); ++i)
{
switch (op[i])
{
case '+': result += a[i+1]; break;
case '-': result -= a[i+1]; break;
default: break;
}
}
printf("Result = %d", result);
No.5
- 回答日時:
コンパイラコンパイラを使って構文解析ルーチンを作る。
参考文献:coco 構文解析 で検索してください。
以下のコードは、数式をエクセルのように扱うために作成したものです。
これから、コンパイラコンパイラを使って、構文解析ルーチンを作成します。
-- Attribute grammar of s
-- ====================================================
GRAMMAR s
SEMANTIC DECLARATIONS
--=====================
TERMINALS
--===========
NUM --1
CELL --2
FUNC --3
"+" --4
"-" --5
"*" --6
"/" --7
"^" --8
"(" --9
")" --10
":" --11
nococosy --12
NONTERMINALS
--=============
s
e
t
f
x
u
o
--=========== Scanner rules =================
RULES
s = e sem
if(isformula)
{*att = FORMULA;}
else
{*att = VALUE;}
push(&curtoken);
break;
endsem.
e = t
{"+" sem push(&curtoken); break; endsem
t sem
token1 = pop();
curtoken.x.value += token1.x.value;
break;
endsem
|"-" sem push(&curtoken); break; endsem
t sem
token1 = pop();
curtoken.x.value = token1.x.value - curtoken.x.value ;
break;
endsem}.
t = f
{"*" sem push(&curtoken); break; endsem
f sem
token1 = pop();
curtoken.x.value *= token1.x.value;
break;
endsem
|"/" sem push(&curtoken); break; endsem
f sem
token1 = pop();
if (curtoken.x.value == 0)
curtoken.x.value = HUGE_VAL;
else
curtoken.x.value = token1.x.value/curtoken.x.value;;
break;
endsem}.
f = x
["^" sem push(&curtoken); break; endsem
f sem
token1 = pop();
curtoken.x.value = pow( token1.x.value, curtoken.x.value,);
break;
endsem ].
x = u
| "-"u sem
curtoken.x.value = -curtoken.x.value;
break;
endsem.
u = CELL sem
curtoken.x.value = cellvalue(curtoken.x.c.col, curtoken.x.c.row);
break;
endsem
[ ":" sem push(&curtoken); break; endsem
CELL
sem
push(&curtoken);
token1 = pop();
token2 = pop();
curtoken.x.value = 0;
if (token1.x.c.row == token2.x.c.row)
{
if (token1.x.c.col < token2.x.c.col)
error = TRUE;
else
{
for (counter = token2.x.c.col; counter <= token1.x.c.col; counter++)
curtoken.x.value += cellvalue(counter, token1.x.c.row);
}
}
else if (token1.x.c.col == token2.x.c.col)
{
if (token1.x.c.row < token2.x.c.row)
error = TRUE;
else
{
for (counter = token2.x.c.row; counter <= token1.x.c.row; counter++)
curtoken.x.value += cellvalue(token1.x.c.col, counter);
}
}
else
error = TRUE;
break;
endsem ]
| o.
o = "("e")"
| NUM
| FUNC"(" sem push(&curtoken); break; endsem
e
sem
token1 = pop();
if (strcmp(token1.x.funcname, "ABS") == 0)
curtoken.x.value = fabs(curtoken.x.value);
else if (strcmp(token1.x.funcname, "ACOS") == 0)
curtoken.x.value = acos(curtoken.x.value);
else if (strcmp(token1.x.funcname, "ASIN") == 0)
curtoken.x.value = asin(curtoken.x.value);
else if (strcmp(token1.x.funcname, "ATAN") == 0)
curtoken.x.value = atan(curtoken.x.value);
else if (strcmp(token1.x.funcname, "COSH") == 0)
curtoken.x.value = cosh(curtoken.x.value);
else if (strcmp(token1.x.funcname, "COS") == 0)
curtoken.x.value = cos(curtoken.x.value);
else if (strcmp(token1.x.funcname, "EXP") == 0)
curtoken.x.value = exp(curtoken.x.value);
else if (strcmp(token1.x.funcname, "LOG10") == 0)
curtoken.x.value = log10(curtoken.x.value);
else if (strcmp(token1.x.funcname, "LOG") == 0)
curtoken.x.value = log(curtoken.x.value);
else if (strcmp(token1.x.funcname, "ROUND") == 0)
curtoken.x.value = (int)(curtoken.x.value + 0.5);
else if (strcmp(token1.x.funcname, "POW10") == 0)
curtoken.x.value = pow10(curtoken.x.value);
else if (strcmp(token1.x.funcname, "SINH") == 0)
curtoken.x.value = sinh(curtoken.x.value);
else if (strcmp(token1.x.funcname, "SIN") == 0)
curtoken.x.value = sin(curtoken.x.value);
else if (strcmp(token1.x.funcname, "SQRT") == 0)
curtoken.x.value = sqrt(curtoken.x.value);
else if (strcmp(token1.x.funcname, "SQR") == 0)
curtoken.x.value *= curtoken.x.value;
else if (strcmp(token1.x.funcname, "TANH") == 0)
curtoken.x.value = tanh(curtoken.x.value);
else if (strcmp(token1.x.funcname, "TAN") == 0)
curtoken.x.value = tan(curtoken.x.value);
else if (strcmp(token1.x.funcname, "TRUNC") == 0)
curtoken.x.value = (int)curtoken.x.value;
break;
endsem
")".
ENDGR
![](http://oshiete.xgoo.jp/images/v2/common/profile/M/noimageicon_setting_02.png?8acaa2e)
No.4
- 回答日時:
> オペランドと演算子の組み合わせならば優先順に計算してくれるのはわかっていますが
これを、具体的にはどのようにして実現しているのか興味があります。
この方法が理解できていれば、「配列でも同じようにすればOKです」というのが、本来の回答なのですが。
あと、
> 実は既に全ての演算子の組み合わせをIfで表示させるプログラムを根性で作った
ということですが、四則演算(括弧無し)なら、優先順位は2つしかありません。
なので、「すべての演算子の組み合わせ」ではなくて、
・op とは別に、「優先順序」の配列を作る
・優先順序の組み合わせを網羅したプログラムを書く
とすれば、とりあえず、複雑さは半減するはずです。
No.2
- 回答日時:
最適では無いかもしれませんが、一般には式の構造を解析して「木」構造や、逆ポーランド記法等の「順番に処理できる」形にします。
抽象構文木
http://home.a00.itscom.net/hatada/c-tips/ast/ast …
とりあえず、検索で上位にあったものを一つ書きますが、より詳しい説明もあると思うので、探してみてください。
No.1
- 回答日時:
>数字をa[7]とおいて、演算子をop[7]として
演算子はop[6]でいいのでは?
四則演算で、乗除を加減より優先して演算する際の
一つのやり方として、逆ポーランド記法を使うことが
考えられます。
例:
簡単のため、数値を5個、演算子を4個とします。
1 + 2 × 3 - 4 ÷ 5 = 6.2
左辺を逆ポーランド記法で記述すると、
1 2 3 × + 4 5 ÷ -
読み方は
1に、2に3をかけた結果を足し、4を5で割った結果を引く
見事に日本語の語順と対応していますね。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java java 飾子を付けること(public static・・・) ・コンソールへの出力処理はmainメ 2 2022/06/16 19:34
- PHP 空文字 "" ですが 空文字の意味を教えてください。 3 2022/08/05 03:51
- C言語・C++・C# プログラミング初心者です。 演算子を習い、自力で計算機を作ろうと思い、写真のようなプログラムを書きま 2 2022/08/14 21:27
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- SQL Server SQLについて質問です。 a表がありその表には従業員名を保存するname列があります。 LIKE演算 1 2022/05/17 17:49
- Excel(エクセル) エクセルの演算子の利用について 3 2023/06/19 19:49
- Java javaの質問です 次の機能を有するメソッド4つを自クラスに作成し、実装したいです 【機能】 足し算 1 2022/06/15 17:49
- 物理学 運動量演算子の交換関係について 5 2022/06/14 17:17
- その他(プログラミング・Web制作) プログラミング pythonの問題について 2 2022/04/19 00:41
- Excel(エクセル) VBAで組み合わせ算出やCOUNTIFSの処理を高速化したいです。 4 2022/04/07 02:38
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
value内に変数を入れたい
-
hiddenのvalueの値を変えたい
-
テキストボックスに入力された...
-
value.replaceがうまく動作しま...
-
CDOMailで本文テキストの文字コ...
-
プルダウン選択時、既に入力済...
-
selectboxのoptionタグのvalue...
-
javascriptの入力制限keycode除く
-
ユーザーフォームでの検索結果...
-
name属性が同じフォームが複数...
-
ラジオボタンと連動して文字列...
-
eval()を使わずに数値を取得し...
-
フォームで入力した値を別のフ...
-
HTMLとJavaScriptについて解答...
-
[Javascript]TEXTAREAで改行さ...
-
javascriptを教えてください。
-
visual sutudio2012でのコード...
-
HTML、Javascriptでトグルボタ...
-
フレーム内のJavaスクリプトの...
-
ラジオボタンの選択で解答・点...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
value内に変数を入れたい
-
hiddenのvalueの値を変えたい
-
javascriptでhiddenに二次元配...
-
複数のsubmitボタンで押された...
-
テキストボックスに入力された...
-
switchを使って四則演算のプロ...
-
VB.NET DateTimeの型について
-
クイズ作成:15個の問題から5個...
-
セレクトボックスの初期選択状...
-
C言語クイックソートの比較総回...
-
ラジオボタンの選択で解答・点...
-
子から親へチェックボックスの...
-
ラジオボタンと連動して文字列...
-
setIntervalの間隔を途中で変更...
-
JAVASCRIPTで、ボタンを押した...
-
sessionStorageを調べています。
-
クリックの度に加算していくには?
-
3桁区切りのカンマをつけたい...
-
マクロ オブジェクト変数With...
-
selectboxのoptionタグのvalue...
おすすめ情報