回答編集履歴
6
コードの短縮化
test
CHANGED
@@ -82,8 +82,6 @@
|
|
82
82
|
|
83
83
|
}
|
84
84
|
|
85
|
-
|
86
|
-
|
87
85
|
|
88
86
|
|
89
87
|
double term(void) // 項(term)は因数(factor)の積商
|
@@ -170,19 +168,105 @@
|
|
170
168
|
|
171
169
|
```C
|
172
170
|
|
171
|
+
#include <stdio.h> // scanf, printf, puts
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
int priority(char op)
|
176
|
+
|
177
|
+
{
|
178
|
+
|
179
|
+
if (op == '+' || op == '-') return 1;
|
180
|
+
|
181
|
+
if (op == '*' || op == '/') return 2;
|
182
|
+
|
183
|
+
return 0; // op == '='
|
184
|
+
|
185
|
+
}
|
186
|
+
|
187
|
+
|
188
|
+
|
189
|
+
int main(void)
|
190
|
+
|
191
|
+
{
|
192
|
+
|
193
|
+
double val[3];
|
194
|
+
|
195
|
+
char op[3];
|
196
|
+
|
197
|
+
if (scanf("%lf %c", &val[0], &op[0]) != 2) return puts("error");
|
198
|
+
|
199
|
+
for (int i = 1; op[i-1] != '='; i++) {
|
200
|
+
|
201
|
+
if (scanf("%lf %c", &val[i], &op[i]) != 2) return puts("error");
|
202
|
+
|
203
|
+
while (i > 0 && priority(op[i-1]) >= priority(op[i])) {
|
204
|
+
|
205
|
+
switch (op[--i]) {
|
206
|
+
|
207
|
+
case '+': val[i] += val[i+1]; break;
|
208
|
+
|
209
|
+
case '-': val[i] -= val[i+1]; break;
|
210
|
+
|
211
|
+
case '*': val[i] *= val[i+1]; break;
|
212
|
+
|
213
|
+
case '/': val[i] /= val[i+1]; break;
|
214
|
+
|
215
|
+
default: return puts("error");
|
216
|
+
|
217
|
+
}
|
218
|
+
|
219
|
+
op[i] = op[i+1];
|
220
|
+
|
221
|
+
}
|
222
|
+
|
223
|
+
}
|
224
|
+
|
225
|
+
printf("%.15g\n", val[0]);
|
226
|
+
|
227
|
+
}
|
228
|
+
|
229
|
+
```
|
230
|
+
|
231
|
+
理解できますか?
|
232
|
+
|
233
|
+
|
234
|
+
|
235
|
+
**追記2**
|
236
|
+
|
237
|
+
演算子の優先順位を比較しないほうが行数が多いのですが、
|
238
|
+
|
239
|
+
工夫すれば減らすことができます。
|
240
|
+
|
241
|
+
|
242
|
+
|
243
|
+
```C
|
244
|
+
|
173
245
|
#include <stdio.h> // scanf, printf
|
174
246
|
|
175
247
|
|
176
248
|
|
249
|
+
char c, op[] = "+-*/";
|
250
|
+
|
251
|
+
|
252
|
+
|
177
|
-
|
253
|
+
double expr(int i)
|
178
|
-
|
254
|
+
|
179
|
-
{
|
255
|
+
{
|
256
|
+
|
180
|
-
|
257
|
+
double val = 0;
|
258
|
+
|
259
|
+
if (i < 4)
|
260
|
+
|
261
|
+
for (val = expr(i+2); c == op[i] || c == op[i+1]; )
|
262
|
+
|
181
|
-
|
263
|
+
c == '+' ? val += expr(i+2) : c == '-' ? val -= expr(i+2) :
|
182
|
-
|
264
|
+
|
183
|
-
|
265
|
+
c == '*' ? val *= expr(i+2) : (val /= expr(i+2));
|
184
|
-
|
266
|
+
|
185
|
-
|
267
|
+
else if (scanf("%lf %c", &val, &c) != 2) c = 0;
|
268
|
+
|
269
|
+
return val;
|
186
270
|
|
187
271
|
}
|
188
272
|
|
@@ -192,42 +276,18 @@
|
|
192
276
|
|
193
277
|
{
|
194
278
|
|
195
|
-
|
279
|
+
double val = expr(0);
|
196
|
-
|
197
|
-
|
280
|
+
|
198
|
-
|
199
|
-
i
|
281
|
+
printf(c == '=' ? "%.15g\n" : "error\n", val);
|
200
|
-
|
201
|
-
for (int i = 1; op[i-1] != '='; i++) {
|
202
|
-
|
203
|
-
if (scanf("%lf %c", &val[i], &op[i]) != 2) return puts("error");
|
204
|
-
|
205
|
-
while (i > 0 && priority(op[i-1]) >= priority(op[i])) {
|
206
|
-
|
207
|
-
switch (op[--i]) {
|
208
|
-
|
209
|
-
case '+': val[i] += val[i+1]; break;
|
210
|
-
|
211
|
-
case '-': val[i] -= val[i+1]; break;
|
212
|
-
|
213
|
-
case '*': val[i] *= val[i+1]; break;
|
214
|
-
|
215
|
-
case '/': val[i] /= val[i+1]; break;
|
216
|
-
|
217
|
-
default: return puts("error");
|
218
|
-
|
219
|
-
}
|
220
|
-
|
221
|
-
op[i] = op[i+1];
|
222
|
-
|
223
|
-
}
|
224
|
-
|
225
|
-
}
|
226
|
-
|
227
|
-
printf("%.15g\n", val[0]);
|
228
282
|
|
229
283
|
}
|
230
284
|
|
231
285
|
```
|
232
286
|
|
287
|
+
expr と term がよく似ているから一つにまとめられないか、
|
288
|
+
|
289
|
+
いっそのこと factor もまとめてしまおうということで、
|
290
|
+
|
291
|
+
expr、term、factor を expr 一つにして、expr(0)、expr(2)、expr(4) の
|
292
|
+
|
233
|
-
|
293
|
+
呼出しで区別するようにしました。
|
5
不正な演算子の処理を追加
test
CHANGED
@@ -214,6 +214,8 @@
|
|
214
214
|
|
215
215
|
case '/': val[i] /= val[i+1]; break;
|
216
216
|
|
217
|
+
default: return puts("error");
|
218
|
+
|
217
219
|
}
|
218
220
|
|
219
221
|
op[i] = op[i+1];
|
4
演算子の優先順位を比較するコードを追加
test
CHANGED
@@ -161,3 +161,71 @@
|
|
161
161
|
非効率な方法でもよいので思いつくなら、それを質問に追記してもらえれば
|
162
162
|
|
163
163
|
アドバイスできると思います。
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
**追記**
|
168
|
+
|
169
|
+
演算子の優先順位を比較するやり方も書いてみました。
|
170
|
+
|
171
|
+
```C
|
172
|
+
|
173
|
+
#include <stdio.h> // scanf, printf
|
174
|
+
|
175
|
+
|
176
|
+
|
177
|
+
int priority(char op)
|
178
|
+
|
179
|
+
{
|
180
|
+
|
181
|
+
if (op == '+' || op == '-') return 1;
|
182
|
+
|
183
|
+
if (op == '*' || op == '/') return 2;
|
184
|
+
|
185
|
+
return 0; // op == '='
|
186
|
+
|
187
|
+
}
|
188
|
+
|
189
|
+
|
190
|
+
|
191
|
+
int main(void)
|
192
|
+
|
193
|
+
{
|
194
|
+
|
195
|
+
double val[3];
|
196
|
+
|
197
|
+
char op[3];
|
198
|
+
|
199
|
+
if (scanf("%lf %c", &val[0], &op[0]) != 2) return puts("error");
|
200
|
+
|
201
|
+
for (int i = 1; op[i-1] != '='; i++) {
|
202
|
+
|
203
|
+
if (scanf("%lf %c", &val[i], &op[i]) != 2) return puts("error");
|
204
|
+
|
205
|
+
while (i > 0 && priority(op[i-1]) >= priority(op[i])) {
|
206
|
+
|
207
|
+
switch (op[--i]) {
|
208
|
+
|
209
|
+
case '+': val[i] += val[i+1]; break;
|
210
|
+
|
211
|
+
case '-': val[i] -= val[i+1]; break;
|
212
|
+
|
213
|
+
case '*': val[i] *= val[i+1]; break;
|
214
|
+
|
215
|
+
case '/': val[i] /= val[i+1]; break;
|
216
|
+
|
217
|
+
}
|
218
|
+
|
219
|
+
op[i] = op[i+1];
|
220
|
+
|
221
|
+
}
|
222
|
+
|
223
|
+
}
|
224
|
+
|
225
|
+
printf("%.15g\n", val[0]);
|
226
|
+
|
227
|
+
}
|
228
|
+
|
229
|
+
```
|
230
|
+
|
231
|
+
理解できますか?
|
3
誤字修正
test
CHANGED
@@ -42,7 +42,7 @@
|
|
42
42
|
|
43
43
|
優先順位の比較がそれほど難しいことでしょうか?
|
44
44
|
|
45
|
-
+ と - の優先順位を 1、* と / の優先
|
45
|
+
+ と - の優先順位を 1、* と / の優先順位を 2 とすると、
|
46
46
|
|
47
47
|
単にそれを比較するだけです。
|
48
48
|
|
2
インデント修正
test
CHANGED
@@ -146,11 +146,11 @@
|
|
146
146
|
|
147
147
|
if (c == '=')
|
148
148
|
|
149
|
-
|
149
|
+
printf("%.15g\n", val);
|
150
150
|
|
151
151
|
else
|
152
152
|
|
153
|
-
|
153
|
+
puts("error");
|
154
154
|
|
155
155
|
}
|
156
156
|
|
1
ispace -> isspace
test
CHANGED
@@ -56,7 +56,7 @@
|
|
56
56
|
|
57
57
|
#include <stdio.h> // getchar, scanf, printf, puts
|
58
58
|
|
59
|
-
#include <ctype.h> // ispace
|
59
|
+
#include <ctype.h> // isspace
|
60
60
|
|
61
61
|
|
62
62
|
|