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

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

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

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

Q&A

解決済

2回答

1891閲覧

Cで逆ポーランド記法のプログラムのバグ

awellbottom

総合スコア14

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

0グッド

0クリップ

投稿2016/04/22 08:12

編集2016/04/22 09:01

###前提・実現したいこと
被演算数(1文字分の英字)、演算子、および括弧(左括弧「(」と右括弧「)」) のトークンで構成された中置記法の算術式を読み込み、 スタックを用いて逆ポーランド記法の式を出力する Cのプログラムを作成する。

###発生している問題・エラーメッセージ
セグメントエラーが発生してしまう。

エラーメッセージ

./a.out
中置記法で入力する文字列の文字個数を指定してください:13
中置記法の順に代入文の文字列を一文字ずつ入力してください:A=(B-C)/D+EF
s[0]:A
s[1]:=
s[2]:(
s[3]:B
s[4]:-
s[5]:C
s[6]:)
s[7]:/
s[8]:D
s[9]:+
s[10]:E
s[11]:

s[12]:F
セグメントエラー

###該当のソースコード

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define TRUE 1
#define FALSE 0
#define SUCCESS 1 /* 成功 /
#define FAILURE 0 /
失敗 */

typedef char data_type; /*char型をdata_type型に置き換える */

typedef struct node_tag {
data_type data;
struct node_tag next; / 後続ノードへのポインタ /
} node_type; /
ノードの型 */

node_type head; / スタックの先頭へのポインタ (変数宣言)*/

void initialize(node_type *pp) / スタックの初期化 */
{
pp = NULL; / スタックは空(先頭ノードなし) */
}

/* ノードを後ろに付け加える*/

node_type* new_node(data_type data, node_type** head) {
node_type* n = malloc(sizeof(data_type));
node_type* p;
n->data = data;
n->next = NULL;
if (*head == NULL) {
*head = n;
return n;
}
p = *head;
while(1) {
if (p->next == NULL) {
p->next = n;
break;
}
p = p->next;
}
return n;
}

//末尾のノードの文字を出力する
data_type last_node(node_type **pp)
{
node_type *temp=*pp;
while (temp != NULL) {
temp = (temp)->next;
}
return(temp->data);
}

int is_empty(node_type p) { / 空スタックのとき真、 そうでないならば偽を返す /
if (p == NULL) return TRUE; /
空スタックのとき /
else return FALSE; /
空スタックでないとき */
}

//スタックの先頭ノードの削除
int pop(node_type **pp)
{
node_type *temp;
if (*pp != NULL) {
temp = (*pp)->next;
free(pp); / メモリの解放 */
*pp = temp;
return SUCCESS;
}
else return FAILURE;
}

//スタックの先頭へのノードの挿入
int push(node_type **pp, data_type x)
{
node_type *temp;
temp = new_node(x, pp);
if (temp == NULL) return FAILURE;
*pp = temp;
return SUCCESS;
}

int prior(data_type s){

if(s=('A' || 'B' || 'C' || 'D' || 'E' || 'F' ||'G'))
return 5;
if(s='=')
return 0;
if(s='(')
return 4;
if(s=')')
return 1;
if(s='+'||'-')
return 2;
if (s='*'||'/')
return 3;

}

//スタックの先頭のデータの取得
data_type top(node_type p)
{
if (p == NULL) /
空スタックのとき /
return ('\0');
else /
空スタックでないとき /
return p->data; /
スタックの先頭のデータを返す */
}

int main(void){
int n=0,i=0,j=0;
data_type s[50],p[50];
printf("中置記法で入力する文字列の文字個数を指定してください:");
scanf("%d",&n);
printf("中置記法の順に代入文の文字列を一文字ずつ入力してください:");
scanf("%c",&s[i]);
for(i=0;i<n;i++){
scanf("%c",&s[i]);
}

for(i=0;i<n;i++){
printf("s[%d]:%c\n",i,s[i]);
}
printf("hello");

initialize(&head);
new_node(s[0],&head);

printf("hello");
for(i=1;i<n;i++){
if(prior(top(head))<prior(s[i])){
new_node(s[i], &head);
}
if(prior(top(head))>=prior(s[i])){
p[j]=last_node(&head);
j++;
}
}
for(i=0;i<j;i++){
printf("%c",p[i]);
}

return 0;

}

###試したこと

###補足情報(言語/FW/ツール等のバージョンなど)

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

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

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

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

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

guest

回答2

0

順序が変わらないのはprior関数のif分が
比較(==)ではなくて代入(=)になっているので
すべての文字の優先度が同じになっているため

終わらないのはlast_nodeで
値を変更しないポインタppをwhileの条件にしているから

ざっと見た感じ原因はこんなところでしょうか

投稿2016/04/22 09:01

kutsulog

総合スコア985

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

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

awellbottom

2016/04/25 07:47

ですね。ありがとうございます。
guest

0

ベストアンサー

さらっとしか見てませんが、無限ループしそうなところ。

C

1data_type last_node(node_type **pp) 2{ 3 node_type *temp; 4 while (*pp != NULL) { 5 temp = (*pp)->next; 6 } 7 return(temp->data); 8}

ppの値が変わらないのでループから抜け出せないのでは。
こんな感じでどうでしょうか。

C

1data_type last_node(node_type **pp) 2{ 3 node_type *temp = *pp; 4 while (temp != NULL) { 5 temp = (*temp)->next; 6 } 7 return(temp->data); 8}

コンパイルを通してないのでエラーが出たらすみません。

投稿2016/04/22 08:54

ttyp03

総合スコア16998

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

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

awellbottom

2016/04/22 08:58

なるほど。確かにそうですね。しかし今度は、下のようにセグメントエラーがでてしました。 ./a.out 中置記法で入力する文字列の文字個数を指定してください:13 中置記法の順に代入文の文字列を一文字ずつ入力してください:A=(B-C)/D+E*F s[0]:A s[1]:= s[2]:( s[3]:B s[4]:- s[5]:C s[6]:) s[7]:/ s[8]:D s[9]:+ s[10]:E s[11]:* s[12]:F セグメントエラー
kutsulog

2016/04/22 09:06

NULLでない間whileを回すということは whileを抜けたときtempはNULLですので NULLに対してdata要素の参照を行ったら 当然セグメンテーションエラーになります while (pp != NULL) { temp = pp; pp = (*temp)->next; } にする必要があります
awellbottom

2016/04/22 15:59

コメントに沿って以下のようにlast_nodeをかえたところセグメントエラーは出なかったのですが、下のように警告がふたつ出てきました。 なにかよくないことでもあるのでしょうか data_type last_node(node_type **pp) { node_type *temp=*pp; while (pp != NULL) { temp = pp; pp = temp->next; } return(temp->data); } gcc revp.c revp.c: 関数 ‘last_node’ 内: revp.c:74:9: 警告: 互換性のないポインタ型からの代入です [デフォルトで有効] temp = pp; ^ revp.c:75:7: 警告: 互換性のないポインタ型からの代入です [デフォルトで有効] pp = temp->next; ^ $ ./a.out 中置記法で入力する文字列の文字個数を指定してください:13 中置記法の順に代入文の文字列を一文字ずつ入力してください:A=(B-C)/D+E*F s[0]:A s[1]:= s[2]:( s[3]:B s[4]:- s[5]:C s[6]:) s[7]:/ s[8]:D s[9]:+ s[10]:E s[11]:* s[12]:F hellohello
kutsulog

2016/04/25 01:48

ppがnode_type ** tempがnode_type * なので temp = ppではなくtemp = *pp pp = temp->nextではなく*pp = temp->next ではないでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問