質問編集履歴

3

意図的に内容を抹消する行為にあたるため

2021/05/31 10:09

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -1 +1,665 @@
1
+ ### 前提・実現したいこと
2
+
3
+ プログラミングの勉強を初めて2ヶ月ほどのものです。
4
+
5
+ まだまだわからないことが多いので、お手柔らかにお願いいたします。
6
+
7
+ c言語について、通常の式を逆ポーランド記法に変換して式自体を出力するプログラムを制作しています。
8
+
9
+ main.c(関数を使って逆ポーランド記法に変換していくコード)
10
+
11
+ stack.c(スタック関連の関数を入れているコード)
12
+
13
+ stack.h (ヘッダファイル)
14
+
15
+ queue.c (キュー関連の関数を入れているコード)
16
+
17
+ queue.c(ヘッダファイル)
18
+
19
+ lib1.c(課題で提供されている関数の入った補助コード)
20
+
21
+ lib1.h(ヘッダファイル)
22
+
23
+ これらが関連のファイルで分割コンパイルして実行ファイルmain.exeを作ります。
24
+
25
+ 最終的には括弧の含んだ式の処理もしたいのですが、一旦数字と符号のみの式を考えることにしました。
26
+
27
+ 想定しているアルゴリズムは、
28
+
29
+ (キーボード入力から得た文字列をトークンtとする。)
30
+
31
+ (スタックの頂上の内容をsとする。)
32
+
33
+ ・tが数字のとき
34
+
35
+   →tをenqueue
36
+
37
+ ・tが符号のとき
38
+
39
+   →スタックが空ならtをpush
40
+
41
+   ・スタックになにかあるとき
42
+
43
+    ・符号優先度がs<tのとき
44
+
45
+     →tをpush
46
+
47
+    ・符号優先度がs>=tのとき
48
+
49
+     →スタックが空になるかs<tになるまでpopしてその内容をenqueue
50
+
51
+ これを入力したトークンtの数だけ実行していき、最後までtを見終えたらスタックをすべてpopして、その内容をenqueueし、
52
+
53
+ queueを出力すると逆ポーランド記法になっているというものです。
54
+
55
+ ### 発生している問題・エラーメッセージ
56
+
57
+ 以下、式:1-4*3+2 で実行した実行結果です。
58
+
59
+ ちなみに、ほしい結果は、143*-2+ です。
60
+
61
+ ```
62
+
63
+ % ./main.exe
64
+
65
+ これは最新版です
66
+
67
+ input> 1-4*3+2
68
+
69
+ 数字をエンキューします
70
+
71
+ enqueue(1)
72
+
73
+ 記号の処理を始めます
74
+
75
+ push(-)
76
+
77
+ 数字をエンキューします
78
+
79
+ enqueue(4)
80
+
81
+ 記号の処理を始めます
82
+
83
+ 演算子の比較を始めます
84
+
85
+ s = - 優先度は6        <ーーー(1)
86
+
87
+ t = * 優先度は7
88
+
89
+ t>s
90
+
91
+ push(*)
92
+
93
+ 数字をエンキューします
94
+
95
+ enqueue(3)
96
+
97
+ 記号の処理を始めます
98
+
99
+ 演算子の比較を始めます
100
+
101
+ t<s
102
+
103
+ s = * 優先度は7
104
+
105
+ t = + 優先度は6
106
+
107
+ pop = *
108
+
109
+ enqueue(*)
110
+
111
+ s = - 優先度は-1       <ーーー(2)
112
+
113
+ t = + 優先度は6
114
+
115
+ push(+)
116
+
117
+ 数字をエンキューします
118
+
119
+ enqueue(2)
120
+
121
+ --- スタックの中身出していきます ---
122
+
123
+ pop = +
124
+
125
+ enqueue(+)
126
+
127
+ pop = -
128
+
129
+ enqueue(-)
130
+
131
+ 1 4 3 * 2 + -
132
+
133
+ %
134
+
135
+ ```
136
+
137
+ 1行目出力は、今までの変更のバックアップとごっちゃにならないために出力してるものなので気にしないでください...()
138
+
139
+ 問題の箇所は、「<ーーーー(2)」で指している部分で、優先度が正しく得ることが出来ていません。
140
+
141
+ ちなみに優先度における「-1」という出力はどの符号にも当てはまらなかった場合に出力される値です。
142
+
143
+ ### 該当のソースコード
144
+
145
+ main.c
146
+
147
+ ```c
148
+
149
+ #include <stdio.h>
150
+
151
+ #include <stdlib.h>
152
+
153
+ #include <string.h>
154
+
155
+ #include "lib1.h"
156
+
157
+ #include "stack.h"
158
+
159
+ #include "queue.h"
160
+
161
+ #define MAX_TOKEN_NUM 200
162
+
163
+ int main(void){
164
+
165
+ int i,j,k,kakko,result,tnum;
166
+
167
+ char a,*s,m,*sp,*tp,*token[MAX_TOKEN_NUM],*p,x;
168
+
169
+ printf("これは最新版です\n");
170
+
171
+ // 標準入力から1行分の文字列を読み込み,トークンに分割する.
172
+
173
+ tnum = input(token,MAX_TOKEN_NUM);
174
+
175
+ //■ 中置記法の式の構成要素(トークン)を先頭から順に注目しながら以下を繰り返す.
176
+
177
+ for (i = 0; i < tnum; i++) {
178
+
179
+ //● 今注目中のトークン t と記号スタックの状態に応じて,表 2 の通り処理する.
180
+
181
+
182
+
183
+ if (isNumberStr(token[i])) {
184
+
185
+ //・数字だったとき
186
+
187
+ printf("数字をエンキューします\n");
188
+
189
+ enqueue(*token[i]);
190
+
191
+ }else if (isOperatorStr(token[i])) {
192
+
193
+ //・記号だったとき
194
+
195
+ printf("記号の処理を始めます\n");
196
+
197
+ if (isStackEmpty()) {
198
+
199
+ //・スタックが空だったとき
200
+
201
+ push(*token[i]);
202
+
203
+ }else{
204
+
205
+ //・スタックになにかあるとき
206
+
207
+ printf("演算子の比較を始めます\n");
208
+
209
+ m = peek();
210
+
211
+ sp = &m; //spはpeekの値のアドレス
212
+
213
+ tp = &*token[i]; //tpは注目中のトークンのアドレス
214
+
215
+ //スタックの中身が演算子だったとき
216
+
217
+ if (priority(tp)/*t*/ >= /*s*/priority(sp)) {
218
+
219
+ printf("s = %c 優先度は%d\n",peek(),priority(sp));
220
+
221
+ printf("t = %c 優先度は%d\n",*token[i],priority(tp));
222
+
223
+ //・tのほうがsより優先度が高いとき
224
+
225
+ //演算子tをpushする
226
+
227
+ printf("t>s\n");
228
+
229
+ push(*token[i]);
230
+
231
+ }else{
232
+
233
+ printf("t<s\n"); //・sのほうがtより優先度が高いとき
234
+
235
+ while(isStackEmpty()==0){ //スタックが空になるまでpopしenqueue
236
+
237
+ m = peek();
238
+
239
+ sp = &m;
240
+
241
+ printf("s = %c 優先度は%d\n",peek(),priority(sp));
242
+
243
+ printf("t = %c 優先度は%d\n",*token[i],priority(tp));
244
+
245
+ if (priority(tp)/*t*/ <= /*s*/priority(sp)) {
246
+
247
+ a = pop();
248
+
249
+ p = &a;//この文が何故かpriority(-1)問題において大切
250
+
251
+ enqueue(a);//ここでaの内容をenqueueしている時点で上の行の文は関係はいはず
252
+
253
+ }else break;
254
+
255
+ }
256
+
257
+ push(*token[i]);//演算子tをpushする
258
+
259
+ }
260
+
261
+ }
262
+
263
+ }
264
+
265
+ }
266
+
267
+ //stackが空になるまでenqueue
268
+
269
+ printf("--- スタックの中身出していきます ---\n");
270
+
271
+ while(isStackEmpty()==0){
272
+
273
+ a = pop();
274
+
275
+ enqueue(a);
276
+
277
+ }
278
+
279
+ printQueue();
280
+
281
+ }
282
+
283
+ ```
284
+
285
+ stack.c
286
+
287
+ ```c
288
+
289
+ #include <stdio.h>
290
+
291
+ #include <stdlib.h>
292
+
293
+ #include <string.h>
294
+
295
+ #include "stack.h"
296
+
297
+
298
+
299
+ STACK_TYPE gStack[STACK_SIZE];
300
+
301
+ int gSNum = 0;
302
+
303
+
304
+
305
+ void push(STACK_TYPE x){
306
+
307
+ gStack[gSNum++] = x;
308
+
309
+ printf("push(%c)\n",x);
310
+
311
+ }
312
+
313
+
314
+
315
+ STACK_TYPE pop(void){
316
+
317
+ char x = gStack[gSNum - 1];
318
+
319
+
320
+
321
+ gSNum--;
322
+
323
+ printf("pop = %c\n",x);
324
+
325
+ return x;
326
+
327
+ }
328
+
329
+
330
+
331
+ void printStack(void){
332
+
333
+ int i;
334
+
335
+ printf("STACK[ ");
336
+
337
+ for (i=0; i<gSNum; i++){
338
+
339
+ printf("%.1lf ", gStack[i]);
340
+
341
+ }
342
+
343
+ printf("]\n");
344
+
345
+ }
346
+
347
+
348
+
349
+ int isStackEmpty(void){
350
+
351
+ return gSNum == 0;
352
+
353
+ }
354
+
355
+
356
+
357
+ int isStackFull(void){
358
+
359
+ return gSNum == STACK_SIZE;
360
+
361
+ }
362
+
363
+ STACK_TYPE peek(void){
364
+
365
+ STACK_TYPE x;
366
+
367
+ if(isStackEmpty() != 1){
368
+
369
+ //空じゃないなら
370
+
371
+ x = gStack[gSNum-1];
372
+
373
+ return x;
374
+
375
+ }else{
376
+
377
+ //空状態なら
378
+
379
+ fprintf(stderr,"エラー:空状態でpeekはできません\n");
380
+
381
+ exit(1);
382
+
383
+ }
384
+
385
+ }
386
+
387
+ //符号優先度を出す関数
388
+
389
+ int priority(char *op){
390
+
391
+ int result,a=-1;
392
+
393
+ result = strcmp(op,"=");
394
+
395
+ if(result == 0){
396
+
397
+ a = 2;
398
+
399
+ }
400
+
401
+ result = strcmp(op,"==");
402
+
403
+ if(result == 0){
404
+
405
+ a = 3;
406
+
407
+ }
408
+
409
+ result = strcmp(op,"!=");
410
+
411
+ if(result == 0){
412
+
413
+ a = 3;
414
+
415
+ }
416
+
417
+ result = strcmp(op,"+");
418
+
419
+ if(result == 0){
420
+
421
+ a = 6;
422
+
423
+ }
424
+
425
+ result = strcmp(op,"-");
426
+
427
+ if(result == 0){
428
+
429
+ a = 6;
430
+
431
+ }
432
+
433
+ result = strcmp(op,"*");
434
+
435
+ if(result == 0){
436
+
437
+ a = 7;
438
+
439
+ }
440
+
441
+ result = strcmp(op,"/");
442
+
443
+ if(result == 0){
444
+
445
+ a = 7;
446
+
447
+ }
448
+
449
+ result = strcmp(op,"%");
450
+
451
+ if(result == 0){
452
+
453
+ a = 7;
454
+
455
+ }
456
+
457
+ result = strcmp(op,"^");
458
+
459
+ if(result == 0){
460
+
461
+ a = 8;
462
+
463
+ }
464
+
465
+ result = strcmp(op,"(");
466
+
467
+ if(result == 0){
468
+
469
+ a = 99;
470
+
471
+ }
472
+
473
+ return a;
474
+
475
+ }
476
+
477
+ STACK_TYPE retrieve(POSITION n){
478
+
479
+ if(isStackEmpty()) fprintf(stderr,"retrieve:スタックが空状態です\n");
480
+
481
+ if(n<0 || n >= gSNum) fprintf(stderr,"retrieve:位置が正しくありません\n");
482
+
483
+
484
+
485
+ return gStack[n];
486
+
487
+ }
488
+
489
+ int stackTop(void){
490
+
491
+ int a;
492
+
493
+ a = gSNum;
494
+
495
+
496
+
497
+ return a;
498
+
499
+ }
500
+
501
+ ```
502
+
503
+ queue.c
504
+
505
+ ```c
506
+
507
+ #include <stdio.h>
508
+
509
+ #include <stdlib.h>
510
+
511
+ #include "queue.h"
512
+
513
+ QUEUE_TYPE gQueue[QUEUE_SIZE];
514
+
515
+ int gQNum = 0;
516
+
517
+ void error(char *s){
518
+
519
+ fflush(stdout);
520
+
521
+ fprintf(stderr,"\n%s\n",s);
522
+
523
+ exit(1);
524
+
525
+ }
526
+
527
+ void enqueue(QUEUE_TYPE x){
528
+
529
+ if(isQueueFull())
530
+
531
+ error("enqueue:待ち行列はフル状態です\n");
532
+
533
+
534
+
535
+ gQueue[gQNum++] = x;
536
+
537
+ printf("enqueue(%c)\n",x);
538
+
539
+ }
540
+
541
+ QUEUE_TYPE dequeue(void){
542
+
543
+ QUEUE_TYPE x;
544
+
545
+ int i;
546
+
547
+
548
+
549
+ if(isQueueEmpty())
550
+
551
+ error("dequeue:待ち行列は空状態です\n");
552
+
553
+
554
+
555
+ x = gQueue[0];
556
+
557
+ for(i=1;i<=gQNum-1;i++)
558
+
559
+ gQueue[i-1] = gQueue[i];
560
+
561
+ gQNum--;
562
+
563
+ return x;
564
+
565
+ }
566
+
567
+ int isQueueEmpty(void){
568
+
569
+ return gQNum == 0;
570
+
571
+ }
572
+
573
+ int isQueueFull(void){
574
+
575
+ return gQNum == QUEUE_SIZE;
576
+
577
+ }
578
+
579
+ void printQueue(void){
580
+
581
+ int i;
582
+
583
+ for(i=0; i<gQNum; i++){
584
+
585
+ printf("%c",gQueue[i]);
586
+
587
+ if(i != gQNum -1)printf(" ");
588
+
589
+ }
590
+
591
+ printf("\n");
592
+
593
+ }
594
+
595
+ ```
596
+
597
+ かなり試行錯誤を繰り返して、宣言しているのに使っていない変数や関数がたくさんあり、
598
+
599
+ ごちゃごちゃしていて申し訳ないです。
600
+
601
+ また、lib1.cは提供されたものなので、公開できません。
602
+
1
- 削除まし
603
+ ### 試したこと
604
+
605
+ とにかくpriority関数あたりがなんだかうまく行ってないので、どのようなときに「-1」と出力されてしまうのかいろんな式で実行しましたが、どういう条件でうまく行かないのかわかりませんでした。
606
+
607
+ さらに、
608
+
609
+ main.cの一部抜粋
610
+
611
+ ```c
612
+
613
+ p = &a;//この文が何故かpriority(-1)問題において大切
614
+
615
+ enqueue(a);//ここでaの内容をenqueueしている時点で上の行の文は関係はいはず
616
+
617
+ ```
618
+
619
+ 上記、main.cのコメントでも書いたとおり、ここのp=&a;があるのと無いのとで、出力が変わってきます。
620
+
621
+ 2行目コメントの通り、アルゴリズム上全く関係のない行なのですが、どういう事情なのでしょうか。
622
+
623
+ ### 補足情報(課題について)
624
+
625
+ この課題は授業で出された課題の一部です。
626
+
627
+ 教員はこれまでに習ったことを理解すれば解けるといい、質問は一切受け付けていない状況です。
628
+
629
+ しかし、問題の箇所はアドレスが関連してそうな気が素人なりに勘づいているのですが、そこは授業で習っていません。
630
+
631
+ おおよそ、スタックとキューと逆ポーランド記法について学んだと言った感じです。
632
+
633
+ 逆に言うと、スタックとキューと逆ポーランド記法以外はなんとなくな理解なので、
634
+
635
+ もしかするとかなり初歩的な勘違いをしている可能性も大いにあります。
636
+
637
+ 自信がないところとすれば、priority関数について引数の入れ方をpriority(sp) (sp = &m)のようなアドレスで渡すようなやり方は授業内でしたことがない。(習っていない)
638
+
639
+ 授業ではこんなふうに使っていました。
640
+
641
+ ``` c
642
+
643
+ int main(void){
644
+
645
+ char *op[OPNUM] = {"+", "*", "-", "/", "&", "^", "%", "=", "==", "!="};
646
+
647
+ int i;
648
+
649
+ for (i=0; i<OPNUM; i++){
650
+
651
+ printf("%s -> %d\n", op[i], priority(op[i]));
652
+
653
+ }
654
+
655
+ return 0;
656
+
657
+ }
658
+
659
+ ```
660
+
661
+ 理解度かなり低い状態ではあると思いますが、
662
+
663
+ 教員に質問できない状況下でかなり時間かけて取り組みました。
664
+
665
+ 回答よろしくおねがいします。

2

削除

2021/05/31 10:09

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -1,755 +1 @@
1
- ### 前提・実現したいこと
2
-
3
-
4
-
5
- プログラミングの勉強を初めて2ヶ月ほどのものです。
6
-
7
- まだまだわからないことが多いので、お手柔らかにお願いいたします。
8
-
9
-
10
-
11
- c言語について、通常の式を逆ポーランド記法に変換して式自体を出力するプログラムを制作しています。
12
-
13
-
14
-
15
- main.c(関数を使って逆ポーランド記法に変換していくコード)
16
-
17
- stack.c(スタック関連の関数を入れているコード)
18
-
19
- stack.h (ヘッダファイル)
20
-
21
- queue.c (キュー関連の関数を入れているコード)
22
-
23
- queue.c(ヘッダファイル)
24
-
25
- lib1.c(課題で提供されている関数の入った補助コード)
26
-
27
- lib1.h(ヘッダファイル)
28
-
29
-
30
-
31
- これらが関連のファイルで分割コンパイルして実行ファイルmain.exeを作ります。
32
-
33
-
34
-
35
- 最終的には括弧の含んだ式の処理もしたいのですが、一旦数字と符号のみの式を考えることにしました。
36
-
37
-
38
-
39
-
40
-
41
- 想定しているアルゴリズムは、
42
-
43
- (キーボード入力から得た文字列をトークンtとする。)
44
-
45
- (スタックの頂上の内容をsとする。)
46
-
47
-
48
-
49
- ・tが数字のとき
50
-
51
-   →tをenqueue
52
-
53
- ・tが符号のとき
54
-
55
-   →スタックが空ならtをpush
56
-
57
-   ・スタックになにかあるとき
58
-
59
-    ・符号優先度がs<tのとき
60
-
61
-     →tをpush
62
-
63
-    ・符号優先度がs>=tのとき
64
-
65
-     →スタックが空になるかs<tになるまでpopしてその内容をenqueue
66
-
67
-
68
-
69
- これを入力したトークンtの数だけ実行していき、最後までtを見終えたらスタックをすべてpopして、その内容をenqueueし、
70
-
71
- queueを出力すると逆ポーランド記法になっているというものです。
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
- ### 発生している問題・エラーメッセージ
82
-
83
-
84
-
85
- 以下、式:1-4*3+2 で実行した実行結果です。
86
-
87
- ちなみに、ほしい結果は、143*-2+ です。
88
-
89
- ```
90
-
91
- % ./main.exe
92
-
93
- これは最新版です
94
-
95
- input> 1-4*3+2
96
-
97
- 数字をエンキューします
98
-
99
- enqueue(1)
100
-
101
- 記号の処理を始めます
102
-
103
- push(-)
104
-
105
- 数字をエンキューします
106
-
107
- enqueue(4)
108
-
109
- 記号の処理を始めます
110
-
111
- 演算子の比較を始めます
112
-
113
- s = - 優先度は6        <ーーー(1)
114
-
115
- t = * 優先度は7
116
-
117
- t>s
118
-
119
- push(*)
120
-
121
- 数字をエンキューします
122
-
123
- enqueue(3)
124
-
125
- 記号の処理を始めます
126
-
127
- 演算子の比較を始めます
128
-
129
- t<s
130
-
131
- s = * 優先度は7
132
-
133
- t = + 優先度は6
134
-
135
- pop = *
136
-
137
- enqueue(*)
138
-
139
- s = - 優先度は-1       <ーーー(2)
140
-
141
- t = + 優先度は6
142
-
143
- push(+)
144
-
145
- 数字をエンキューします
146
-
147
- enqueue(2)
148
-
149
- --- スタックの中身出していきます ---
150
-
151
- pop = +
152
-
153
- enqueue(+)
154
-
155
- pop = -
156
-
157
- enqueue(-)
158
-
159
- 1 4 3 * 2 + -
160
-
161
- %
162
-
163
-
164
-
165
- ```
166
-
167
- 1行目出力は、今までの変更のバックアップとごっちゃにならないために出力してるものなので気にしないでください...()
168
-
169
-
170
-
171
- 問題の箇所は、「<ーーーー(2)」で指している部分で、優先度が正しく得ることが出来ていません。
172
-
173
- ちなみに優先度における「-1」という出力はどの符号にも当てはまらなかった場合に出力される値です。
174
-
175
-
176
-
177
- ### 該当のソースコード
178
-
179
-
180
-
181
- main.c
182
-
183
- ```c
184
-
185
- #include <stdio.h>
186
-
187
- #include <stdlib.h>
188
-
189
- #include <string.h>
190
-
191
- #include "lib1.h"
192
-
193
- #include "stack.h"
194
-
195
- #include "queue.h"
196
-
197
- #define MAX_TOKEN_NUM 200
198
-
199
-
200
-
201
- int main(void){
202
-
203
- int i,j,k,kakko,result,tnum;
204
-
205
- char a,*s,m,*sp,*tp,*token[MAX_TOKEN_NUM],*p,x;
206
-
207
- printf("これは最新版です\n");
208
-
209
- // 標準入力から1行分の文字列を読み込み,トークンに分割する.
210
-
211
- tnum = input(token,MAX_TOKEN_NUM);
212
-
213
-
214
-
215
- //■ 中置記法の式の構成要素(トークン)を先頭から順に注目しながら以下を繰り返す.
216
-
217
- for (i = 0; i < tnum; i++) {
218
-
219
- //● 今注目中のトークン t と記号スタックの状態に応じて,表 2 の通り処理する.
220
-
221
-
222
-
223
- if (isNumberStr(token[i])) {
224
-
225
- //・数字だったとき
226
-
227
- printf("数字をエンキューします\n");
228
-
229
- enqueue(*token[i]);
230
-
231
- }else if (isOperatorStr(token[i])) {
232
-
233
- //・記号だったとき
234
-
235
- printf("記号の処理を始めます\n");
236
-
237
- if (isStackEmpty()) {
238
-
239
- //・スタックが空だったとき
240
-
241
- push(*token[i]);
242
-
243
-
244
-
245
- }else{
246
-
247
- //・スタックになにかあるとき
248
-
249
- printf("演算子の比較を始めます\n");
250
-
251
- m = peek();
252
-
253
- sp = &m; //spはpeekの値のアドレス
254
-
255
- tp = &*token[i]; //tpは注目中のトークンのアドレス
256
-
257
-
258
-
259
- //スタックの中身が演算子だったとき
260
-
261
- if (priority(tp)/*t*/ >= /*s*/priority(sp)) {
262
-
263
- printf("s = %c 優先度は%d\n",peek(),priority(sp));
264
-
265
- printf("t = %c 優先度は%d\n",*token[i],priority(tp));
266
-
267
- //・tのほうがsより優先度が高いとき
268
-
269
- //演算子tをpushする
270
-
271
- printf("t>s\n");
272
-
273
- push(*token[i]);
274
-
275
-
276
-
277
- }else{
278
-
279
- printf("t<s\n"); //・sのほうがtより優先度が高いとき
280
-
281
- while(isStackEmpty()==0){ //スタックが空になるまでpopしenqueue
282
-
283
- m = peek();
284
-
285
- sp = &m;
286
-
287
- printf("s = %c 優先度は%d\n",peek(),priority(sp));
288
-
289
- printf("t = %c 優先度は%d\n",*token[i],priority(tp));
290
-
291
- if (priority(tp)/*t*/ <= /*s*/priority(sp)) {
292
-
293
- a = pop();
294
-
295
- p = &a;//この文が何故かpriority(-1)問題において大切
296
-
297
- enqueue(a);//ここでaの内容をenqueueしている時点で上の行の文は関係はいはず
298
-
299
- }else break;
300
-
301
- }
302
-
303
- push(*token[i]);//演算子tをpushする
304
-
305
- }
306
-
307
- }
308
-
309
- }
310
-
311
- }
312
-
313
- //stackが空になるまでenqueue
314
-
315
- printf("--- スタックの中身出していきます ---\n");
316
-
317
- while(isStackEmpty()==0){
318
-
319
- a = pop();
320
-
321
- enqueue(a);
322
-
323
- }
324
-
325
- printQueue();
326
-
327
- }
328
-
329
- ```
330
-
331
- stack.c
332
-
333
- ```c
334
-
335
- #include <stdio.h>
336
-
337
- #include <stdlib.h>
338
-
339
- #include <string.h>
340
-
341
- #include "stack.h"
342
-
343
-
344
-
345
- STACK_TYPE gStack[STACK_SIZE];
346
-
347
- int gSNum = 0;
348
-
349
-
350
-
351
- void push(STACK_TYPE x){
352
-
353
- gStack[gSNum++] = x;
354
-
355
- printf("push(%c)\n",x);
356
-
357
- }
358
-
359
-
360
-
361
- STACK_TYPE pop(void){
362
-
363
- char x = gStack[gSNum - 1];
364
-
365
-
366
-
367
- gSNum--;
368
-
369
- printf("pop = %c\n",x);
370
-
371
- return x;
372
-
373
- }
374
-
375
-
376
-
377
- void printStack(void){
378
-
379
- int i;
380
-
381
- printf("STACK[ ");
382
-
383
- for (i=0; i<gSNum; i++){
384
-
385
- printf("%.1lf ", gStack[i]);
386
-
387
- }
388
-
389
- printf("]\n");
390
-
391
- }
392
-
393
-
394
-
395
- int isStackEmpty(void){
396
-
397
- return gSNum == 0;
398
-
399
- }
400
-
401
-
402
-
403
- int isStackFull(void){
404
-
405
- return gSNum == STACK_SIZE;
406
-
407
- }
408
-
409
-
410
-
411
- STACK_TYPE peek(void){
412
-
413
- STACK_TYPE x;
414
-
415
- if(isStackEmpty() != 1){
416
-
417
- //空じゃないなら
418
-
419
- x = gStack[gSNum-1];
420
-
421
- return x;
422
-
423
- }else{
424
-
425
- //空状態なら
426
-
427
- fprintf(stderr,"エラー:空状態でpeekはできません\n");
428
-
429
- exit(1);
430
-
431
- }
432
-
433
- }
434
-
435
- //符号優先度を出す関数
436
-
437
- int priority(char *op){
438
-
439
- int result,a=-1;
440
-
441
- result = strcmp(op,"=");
442
-
443
- if(result == 0){
444
-
445
- a = 2;
446
-
447
- }
448
-
449
- result = strcmp(op,"==");
450
-
451
- if(result == 0){
452
-
453
- a = 3;
454
-
455
- }
456
-
457
- result = strcmp(op,"!=");
458
-
459
- if(result == 0){
460
-
461
- a = 3;
462
-
463
- }
464
-
465
- result = strcmp(op,"+");
466
-
467
- if(result == 0){
468
-
469
- a = 6;
470
-
471
- }
472
-
473
- result = strcmp(op,"-");
474
-
475
- if(result == 0){
476
-
477
- a = 6;
478
-
479
- }
480
-
481
- result = strcmp(op,"*");
482
-
483
- if(result == 0){
484
-
485
- a = 7;
486
-
487
- }
488
-
489
- result = strcmp(op,"/");
490
-
491
- if(result == 0){
492
-
493
- a = 7;
494
-
495
- }
496
-
497
- result = strcmp(op,"%");
498
-
499
- if(result == 0){
500
-
501
- a = 7;
502
-
503
- }
504
-
505
- result = strcmp(op,"^");
506
-
507
- if(result == 0){
508
-
509
- a = 8;
510
-
511
- }
512
-
513
- result = strcmp(op,"(");
514
-
515
- if(result == 0){
516
-
517
- a = 99;
518
-
519
- }
520
-
521
- return a;
522
-
523
-
524
-
525
- }
526
-
527
-
528
-
529
- STACK_TYPE retrieve(POSITION n){
530
-
531
- if(isStackEmpty()) fprintf(stderr,"retrieve:スタックが空状態です\n");
532
-
533
- if(n<0 || n >= gSNum) fprintf(stderr,"retrieve:位置が正しくありません\n");
534
-
535
-
536
-
537
- return gStack[n];
538
-
539
- }
540
-
541
-
542
-
543
- int stackTop(void){
544
-
545
- int a;
546
-
547
- a = gSNum;
548
-
549
-
550
-
551
- return a;
552
-
553
- }
554
-
555
- ```
556
-
557
- queue.c
558
-
559
- ```c
560
-
561
- #include <stdio.h>
562
-
563
- #include <stdlib.h>
564
-
565
- #include "queue.h"
566
-
567
-
568
-
569
- QUEUE_TYPE gQueue[QUEUE_SIZE];
570
-
571
- int gQNum = 0;
572
-
573
-
574
-
575
- void error(char *s){
576
-
577
- fflush(stdout);
578
-
579
- fprintf(stderr,"\n%s\n",s);
580
-
581
- exit(1);
582
-
583
- }
584
-
585
- void enqueue(QUEUE_TYPE x){
586
-
587
- if(isQueueFull())
588
-
589
- error("enqueue:待ち行列はフル状態です\n");
590
-
591
-
592
-
593
- gQueue[gQNum++] = x;
594
-
595
- printf("enqueue(%c)\n",x);
596
-
597
- }
598
-
599
-
600
-
601
- QUEUE_TYPE dequeue(void){
602
-
603
- QUEUE_TYPE x;
604
-
605
- int i;
606
-
607
-
608
-
609
- if(isQueueEmpty())
610
-
611
- error("dequeue:待ち行列は空状態です\n");
612
-
613
-
614
-
615
- x = gQueue[0];
616
-
617
- for(i=1;i<=gQNum-1;i++)
618
-
619
- gQueue[i-1] = gQueue[i];
620
-
621
- gQNum--;
622
-
623
- return x;
624
-
625
- }
626
-
627
-
628
-
629
- int isQueueEmpty(void){
630
-
631
- return gQNum == 0;
632
-
633
- }
634
-
635
-
636
-
637
- int isQueueFull(void){
638
-
639
- return gQNum == QUEUE_SIZE;
640
-
641
- }
642
-
643
-
644
-
645
- void printQueue(void){
646
-
647
- int i;
648
-
649
- for(i=0; i<gQNum; i++){
650
-
651
- printf("%c",gQueue[i]);
652
-
653
- if(i != gQNum -1)printf(" ");
654
-
655
- }
656
-
657
- printf("\n");
658
-
659
- }
660
-
661
- ```
662
-
663
-
664
-
665
-
666
-
667
-
668
-
669
-
670
-
671
-
672
-
673
- かなり試行錯誤を繰り返して、宣言しているのに使っていない変数や関数がたくさんあり、
674
-
675
- ごちゃごちゃしていて申し訳ないです。
676
-
677
- また、lib1.cは提供されたものなので、公開できません。
678
-
679
- ### 試したこと
1
+ 削除まし
680
-
681
-
682
-
683
- とにかくpriority関数あたりがなんだかうまく行ってないので、どのようなときに「-1」と出力されてしまうのかいろんな式で実行しましたが、どういう条件でうまく行かないのかわかりませんでした。
684
-
685
-
686
-
687
- さらに、
688
-
689
- main.cの一部抜粋
690
-
691
- ```c
692
-
693
- p = &a;//この文が何故かpriority(-1)問題において大切
694
-
695
- enqueue(a);//ここでaの内容をenqueueしている時点で上の行の文は関係はいはず
696
-
697
- ```
698
-
699
- 上記、main.cのコメントでも書いたとおり、ここのp=&a;があるのと無いのとで、出力が変わってきます。
700
-
701
- 2行目コメントの通り、アルゴリズム上全く関係のない行なのですが、どういう事情なのでしょうか。
702
-
703
-
704
-
705
-
706
-
707
- ### 補足情報(課題について)
708
-
709
-
710
-
711
- この課題は授業で出された課題の一部です。
712
-
713
- 教員はこれまでに習ったことを理解すれば解けるといい、質問は一切受け付けていない状況です。
714
-
715
- しかし、問題の箇所はアドレスが関連してそうな気が素人なりに勘づいているのですが、そこは授業で習っていません。
716
-
717
- おおよそ、スタックとキューと逆ポーランド記法について学んだと言った感じです。
718
-
719
-
720
-
721
- 逆に言うと、スタックとキューと逆ポーランド記法以外はなんとなくな理解なので、
722
-
723
- もしかするとかなり初歩的な勘違いをしている可能性も大いにあります。
724
-
725
-
726
-
727
- 自信がないところとすれば、priority関数について引数の入れ方をpriority(sp) (sp = &m)のようなアドレスで渡すようなやり方は授業内でしたことがない。(習っていない)
728
-
729
- 授業ではこんなふうに使っていました。
730
-
731
- ``` c
732
-
733
- int main(void){
734
-
735
- char *op[OPNUM] = {"+", "*", "-", "/", "&", "^", "%", "=", "==", "!="};
736
-
737
- int i;
738
-
739
- for (i=0; i<OPNUM; i++){
740
-
741
- printf("%s -> %d\n", op[i], priority(op[i]));
742
-
743
- }
744
-
745
- return 0;
746
-
747
- }
748
-
749
- ```
750
-
751
- 理解度かなり低い状態ではあると思いますが、
752
-
753
- 教員に質問できない状況下でかなり時間かけて取り組みました。
754
-
755
- 回答よろしくおねがいします。

1

タグを変えました

2021/05/30 09:05

投稿

退会済みユーザー
test CHANGED
@@ -1 +1 @@
1
- [c言語]通常の式を逆ポーランド記法に変換して式自体を出力するプログラムを制作したい。
1
+ プログラムを制作したい。
test CHANGED
File without changes