回答編集履歴

6

コードの短縮化

2020/11/08 10:55

投稿

kazuma-s
kazuma-s

スコア8224

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
- int priority(char op)
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
- if (op == '+' || op == '-') return 1;
263
+ c == '+' ? val += expr(i+2) : c == '-' ? val -= expr(i+2) :
182
-
264
+
183
- if (op == '*' || op == '/') return 2;
265
+ c == '*' ? val *= expr(i+2) : (val /= expr(i+2));
184
-
266
+
185
- return 0; // op == '='
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
- double val[3];
279
+ double val = expr(0);
196
-
197
- char op[3];
280
+
198
-
199
- if (scanf("%lf %c", &val[0], &op[0]) != 2) return puts("error");
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

不正な演算子の処理を追加

2020/11/08 10:55

投稿

kazuma-s
kazuma-s

スコア8224

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

演算子の優先順位を比較するコードを追加

2020/11/08 04:20

投稿

kazuma-s
kazuma-s

スコア8224

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

誤字修正

2020/11/08 04:11

投稿

kazuma-s
kazuma-s

スコア8224

test CHANGED
@@ -42,7 +42,7 @@
42
42
 
43
43
  優先順位の比較がそれほど難しいことでしょうか?
44
44
 
45
- + と - の優先順位を 1、* と / の優先運意を 2 とすると、
45
+ + と - の優先順位を 1、* と / の優先順位を 2 とすると、
46
46
 
47
47
  単にそれを比較するだけです。
48
48
 

2

インデント修正

2020/11/07 14:43

投稿

kazuma-s
kazuma-s

スコア8224

test CHANGED
@@ -146,11 +146,11 @@
146
146
 
147
147
  if (c == '=')
148
148
 
149
- printf("%.15g\n", val);
149
+ printf("%.15g\n", val);
150
150
 
151
151
  else
152
152
 
153
- puts("error");
153
+ puts("error");
154
154
 
155
155
  }
156
156
 

1

ispace -> isspace

2020/11/07 14:41

投稿

kazuma-s
kazuma-s

スコア8224

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