ここから本文です

C言語に関する質問です。 スタックの操作(push,pop)を利用して、入力された文字列...

mar********さん

2019/6/900:06:48

C言語に関する質問です。
スタックの操作(push,pop)を利用して、入力された文字列中のカッコの関係が正しいかどうかをチェックするプログラムを作っています。

・プログラム
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//構造体の宣言
struct cell{
char C;
struct cell *next;
};
struct cell *stack = NULL, *p = NULL;

//関数のプロトタイプ宣言
void push(char);
char pop();
void free_stack();

//メイン関数
int main(void){
char command[256];
int i;

//文字列の入力
while(strcmp(command,"end")!=0){
printf("チェックする文字列かendを入力してください→ ");
scanf("%s",command);

//end処理
if(strcmp(command,"end")==0){
printf("プログラムを終了します\n");
break;
}

//カッコの関係をチェック
else{
for(i=0;command[i]!='\0';i++){
if((command[i] == '<')||(command[i] == '('))
push(command[i]);
else if(command[i] == '>')
{
if(pop()!='<'){
free_stack();
goto label;
}
}

else if(command[i] == ')')
{
if(pop()!='('){
free_stack();
goto label;
}
}

else
continue;
}

//カッコがすべて対応してるかの確認
if(stack == NULL)
printf("正しい.\n");
else
free_stack();
}
//ループを抜け出す用
label:;
}
return 0;
}

//pushする関数
void push(char in){
p = (struct cell *)malloc(sizeof(struct cell));
p->C = in;
p->next = NULL;
p->next = stack;
stack = p;
}

//popする関数
char pop(){
char popdata;
popdata = stack->C;
p = stack;
stack = stack->next;
free(p);
p = stack;
return popdata;
}

//スタックのメモリ解放をする関数(カッコの関係が正しくないとき)
void free_stack(){
printf("正しくない.\n");
if(stack != NULL){
p = stack;
while(p != NULL){
free(p);
p = p->next;
}
printf("スタックを空にしました.\n");
}
}

これを以下のように入力して実行するとエラーが出てしまいます。

・実行結果
チェックする文字列かendを入力してください→ a<b(c)>
正しい.
チェックする文字列かendを入力してください→ a(b<c)>
正しくない.
スタックを空にしました.
チェックする文字列かendを入力してください→ a<b)c(>
正しくない.
double free or corruption (fasttop)
中止 (コアダンプ)

どうしたら良いのでしょうか。
ご回答よろしくお願いします。

閲覧数:
45
回答数:
3
お礼:
500枚

違反報告

ベストアンサーに選ばれた回答

プロフィール画像

カテゴリマスター

n2q********さん

2019/6/910:53:56

4か所直しますよ。


(1)23行目

【修正前】while (strcmp(command, "end") != 0) {
【修正後】for (;;) {

入力前のため command の中身は不定となります。scanf 後に同様の end 判定処理が入っていますので、ここでは不要です。


(2)94行目

【修正前】p = stack;
【修正後】do pop();

ikt********さんのご指摘の通り、free 後の p を使ってしまっては駄目。せっかく pop 関数があるのですから、これを使うと簡単です。


(3)95行目

【修正前】while (p != NULL) {
【修正後】while (stack != NULL);/*

これは(2)の修正に関連するものです。


(4)98行目

【修正前】}
【修正後】}*/

これも(2)の修正に関連するものです。

質問した人からのコメント

2019/6/11 21:51:31

勉強になりました、ご回答ありがとうございます!

ベストアンサー以外の回答

1〜2件/2件中

並び替え:回答日時の
新しい順
|古い順

プロフィール画像

カテゴリマスター

ikt********さん

2019/6/908:02:09

ぱっと見。

free_stack が、明らかにまちがってます。

free(p); <== pのポイント先メモリを解放した
p = p->next; <== にもかかわらず、事後に p->next を参照してる

返信を取り消しますが
よろしいですか?

  • 取り消す
  • キャンセル

プロフィール画像

カテゴリマスター

tre********さん

2019/6/900:58:49

/*
-----実行結果-----
チェックする文字列かendを入力してください→ a<b(c)>
正しい.
チェックする文字列かendを入力してください→ a(b<c)>
正しくない.
スタックを空にしました.
チェックする文字列かendを入力してください→ a<b)c(>
正しくない.
スタックを空にしました.
チェックする文字列かendを入力してください→ end
プログラムを終了します

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//構造体の宣言
struct cell {
char C;
struct cell *next;
};
struct cell *stack = NULL;

//関数のプロトタイプ宣言
void push(char);
char pop();
void free_stack();

//メイン関数
int main(void) {
char command[256];
int i;

//文字列の入力
while (1) {
printf("チェックする文字列かendを入力してください→ ");
scanf("%s", command);

//end処理
if (strcmp(command, "end") == 0) {
printf("プログラムを終了します\n");
return 0;
}

//カッコの関係をチェック

for (i = 0; command[i] != '\0'; i++) {
char ch = command[i];
if ((ch == '<') || (ch == '('))
push(ch);
else if (ch == '>')
{
if (pop() != '<') break;//エラー
}
else if (ch == ')')
{
if (pop() != '(') break;//エラー
}
}//end for

//カッコがすべて対応してるかの確認
if (command[i] == '\0' && stack == NULL) {
printf("正しい.\n");
}
else {
printf("正しくない.\n");
free_stack();
}

}//end while
return 0;
}//end main

//pushする関数
void push(char in) {
struct cell *p = (struct cell *)malloc(sizeof(struct cell));
p->C = in;
p->next = stack;
stack = p;
}

//popする関数
char pop() {
char popdata;
struct cell *next;

if (stack == NULL)return '\0';//空っぽ

next = stack->next;
popdata = stack->C;
free(stack);
stack = next;
return popdata;
}

//スタックのメモリ解放をする関数(カッコの関係が正しくないとき)
void free_stack() {
while (stack != NULL) {
struct cell *next = stack->next;
free(stack);
stack = next;
}
printf("スタックを空にしました.\n");
}

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる