質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

933閲覧

中間記法から逆ポーランド/シグメントエラー

sakippe

総合スコア21

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2022/06/08 04:52

編集2022/06/08 05:08

中間記法から逆ポーランドに変換するプログラムを作っていて、コンパイルはできたのですが、「セグメントエラー」と表示され困っています。例えば、read<1+5と実行すると次の行に「セグメントエラー」出てしまいます。どこがいけないのでしょうか。

C

1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4#include "lib1.h" 5 6#define MAX_TOKEN_NUM 200 7 8#define QUEUE_SIZE 100 9typedef char *QUEUE_TYPE; 10 11#define STACK_SIZE 100 12typedef char *STACK_TYPE; 13 14QUEUE_TYPE gQueue[QUEUE_SIZE]; 15int gQNum = 0; 16 17STACK_TYPE gStack[STACK_SIZE]; 18int gSNum = 0; 19 20 21void initQueue(void){ 22 gQNum = 0; 23} 24 25void initStack(void){ 26 gSNum = 0; 27} 28 29int isStackEmpty(void){ 30 return gSNum == 0; 31} 32 33void push(STACK_TYPE x){ 34 gStack[gSNum] = x; 35 gSNum++; 36} 37 38STACK_TYPE pop(void){ 39 STACK_TYPE x; 40 41 x = gStack[gSNum - 1]; 42 gSNum--; 43 return x; 44} 45 46void enqueue(QUEUE_TYPE x){ 47 gQueue[gQNum++] = x; 48} 49 50/*tを数字、演算子、"("、")"のどれかを判断する 51参考work37のtaiou関数 52数字を0(else)、演算子を1、"("を2、")"を3*/ 53int tnohantei(char *t){ 54 int result; 55 56 if(strcmp(t, "+") == 0){ 57 result = 1; 58 }else if(strcmp(t, "-") == 0){ 59 result = 1; 60 }else if(strcmp(t, "*") == 0){ 61 result = 1; 62 }else if(strcmp(t, "/") == 0){ 63 result = 1; 64 }else if(strcmp(t, "(") == 0){ 65 result = 2; 66 }else if(strcmp(t, ")") == 0){ 67 result = 3; 68 }else{ 69 result = 0; 70 } 71 72 return result; 73} 74 75void enzansizyouken(char *ops, char *opt){ 76 char *op1 = "+"; 77 char *op2 = "-"; 78 char *op3 = "*"; 79 char *op4 = "/"; 80 char *stacktop = gStack[gSNum-1]; 81 char *x; 82 83 if(strcmp(ops, op1) == 0 && strcmp(opt, op3) == 0){ 84 push(opt); 85 }else if(strcmp(ops, op1) == 0 && strcmp(opt, op4) == 0){ 86 push(opt); 87 }else if(strcmp(ops, op2) == 0 && strcmp(opt, op3) == 0){ 88 push(opt); 89 }else if(strcmp(ops, op2) == 0 && strcmp(opt, op4) == 0){ 90 push(opt); 91 92 }else{ 93 while(!isStackEmpty() || strcmp(stacktop,"(") != 0 || strcmp(stacktop,op3) != 0 || strcmp(stacktop,op4) != 0){ 94 x = pop(); 95 enqueue(x); 96 } 97 push(opt); 98 } 99 return; 100} 101 102int main(int argc, char *argv[]){ 103 char *token[MAX_TOKEN_NUM]; 104 char *k; 105 char *t; 106 char *a; 107 int tnum, i, suuzi; 108 109 tnum = read(token, MAX_TOKEN_NUM); /* 最初の入力 */ 110 while (tnum > 0){ 111 112 113 initQueue(); 114 initStack(); 115 116 for(i=0;i<tnum;i++){ 117 t = token[i]; 118 suuzi = tnohantei(token[i]); 119 if(suuzi == 0){ 120 enqueue(t); 121 }else if(suuzi == 1){ 122 enzansizyouken(argv[1], argv[2]); 123 }else if(suuzi == 2){ 124 push(t); 125 }else if(suuzi == 3){ 126 while(!k){ 127 k = pop(); 128 enqueue(k); 129 if(isStackEmpty()){ 130 printf("スタックエラー"); 131 } 132 } 133 } 134 } 135 while(!isStackEmpty()){ 136 a = pop(); 137 if(strcmp(a, "(") == 0){ 138 printf("エラー\n"); 139 }else{ 140 enqueue(a); 141 } 142 } 143 144 /*トークンの中を表示*/ 145 for (i=0; i<tnum; i++){ 146 printf("token[%d]:%-4s ", i, token[i]); 147 148 149 tnum = read(token, MAX_TOKEN_NUM); /* 次の入力 */ 150 } 151 return 0; 152} 153

lib1は先生の補助プログラムを使っています。変更できません。
int read(char *token[], int n)
キーボードから数式を読み込み,数式の構成要素(トークン)に分割する.分割
した各トークンは文字列の形で,第 1 引数に指定した配列 token に格納される.

C

1#define MAX_INPUT_STRLEN 512 /* 1回の入力の最大長 */ 2#define BUFCOUNT 64 3 4/* 標準入力から1行分の文字列を読み込み,トークンに分割する. 5 * 第1引数: token[]: 分割した各トークン(文字列)を格納する配列. 6 * 第2引数: maxTokenNum: token[]の要素数. 7 * 第3引数: 読み込んだトークンの個数. 8 * 戻り値: 読み込んだトークンの個数. 9 */ 10static int read_core(char *token[], int maxTokenNum){ 11 static char buf[BUFCOUNT][MAX_INPUT_STRLEN * 2]; 12 static int k=-1; 13 static int callcnt = 0; 14 15 int i, j; 16 char str[MAX_INPUT_STRLEN]; 17 int count; 18 19 20 if (callcnt++ > 0){ 21 printf("\n"); 22 } 23 printf("read> "); 24 fflush(stdout); 25 26 27 if (fgets(str, MAX_INPUT_STRLEN, stdin) == NULL){ 28 token[0] = NULL; 29 count = -1; 30 return -1; 31 } 32 33 i = 0; 34 j = 0; 35 k = (k+1)%BUFCOUNT; 36 count = 0; 37 while (str[i] != '\0'){ 38 39 if (isWhitespace(str[i])){ 40 i++; 41 continue; 42 43 } else if (str[i]=='q' || str[i]=='Q'){ 44 count = -1; 45 return -1; 46 47 } else if (isNumberChar(str[i]) || str[i]=='.'){ 48 int dotcnt = 0; 49 50 token[(count)++] = &buf[k][j]; 51 52 while (isNumberChar(str[i]) || str[i] == '.'){ 53 if (str[i] == '.'){ 54 dotcnt++; 55 } 56 buf[k][j++] = str[i++]; 57 } 58 buf[k][j++] = '\0'; 59 60 if (dotcnt >= 2){ 61 fprintf(stderr, "Error: read(): 小数点が2個以上ある数値(%s)を読み込みました\n", buf[k]); 62 exit(1); 63 } 64 if (buf[k][0]=='.' || buf[k][j-2]=='.' ){ 65 fprintf(stderr, "Error: read(): 実数(%s)の形式が不正です.\n", buf[k]); 66 exit(1); 67 } 68 69 } else if (isSymbolChar(str[i])){ 70 token[(count)++] = &buf[k][j]; 71 buf[k][j++] = str[i++]; 72 buf[k][j++] = '\0'; 73 74 } else { 75 printf("Error: read(): 未知の文字('%c', %d)を検出しました\n", str[i], str[i]); 76 exit(1); 77 } 78 79 if (count > maxTokenNum-1){ 80 fprintf(stderr, "Error: read(): 分割したトークンの数が多過ぎます.\n"); 81 exit(1); 82 } 83 } 84 return count; 85} 86 87int read(char *token[], int maxTokenNum){ 88 int r; 89 r = read_core(token, maxTokenNum); 90 while (r == 0){ 91 r = read_core(token, maxTokenNum); 92 } 93 return r; 94}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

can110

2022/06/08 05:02

read関数の実装(ソース)も提示ください。
guest

回答2

0

自己解決

enzansizyouken(argv[1], argv[2]);→enzansizyouken(s, t);
スタックの頂点をpeek関数で参照し、第1引数をs,第2引数をとしました。セグメントエラーは解消されましたが、他のエラーが出ているのでこのプログラムは正しくありません。

投稿2022/06/10 05:57

sakippe

総合スコア21

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

enzansizyouken(argv[1], argv[2]);

argv[]にアクセスしてクラッシュしているのかもしれません。質問文を見る限り、argv[] の出番はないはずです。

enzansizyouken() は、読みこんだ演算子と演算子スタックのトップの内容を比較してアレコレする関数でしょうから、引数は t ひとつだけでいいのでは。

投稿2022/06/08 05:08

編集2022/06/08 06:47
int32_t

総合スコア20923

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

int32_t

2022/06/10 06:16

低評価を付けた方はその理由を教えていただきたいですー。改善いたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問