こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

C言語のソースの説明なんですが

#include <stdio.h>
#define MAX 256
void pushdown(char *S, char x);
char popup(char *S);
void initialize(char *S);
int empty(char *S);
int top=0;
void pushdown(char *S, char x){ /*スタックSにデータxを記憶*/
if(top<MAX){
top++;
S[top]=x;
}
else{
printf("Stack S overflows.\n");
}
}
char popup(char *S){ /*スタックSからデータの取出し*/
if(top>0){
top--;
return(S[top+1]);
}
else{
printf("Stack S is empty.\n");
return('\0');
}
}
void initialize(char *S){
int i;
top=0;
for(i=1;i<MAX;i++){
S[i]='\0';
}
}
int empty(char *S){
if(top==0){
return(1);
}
return(0);
}
int main(void){
char x;
char S[MAX];
pushdown(S,'a');
pushdown(S,'b');
pushdown(S,'c');
x=popup(S);
x=popup(S);
pushdown(S,'d');
x=popup(S);
pushdown(S,'e');
while(!empty(S)){
printf("%c", popup(S));
}
printf("\n");
return(0);
}

上記のソースリストに説明を載せなくてはいけないのですがどれが何をしているのかほとんど分からなくて困っています。(わかったのは既に書いてある2行分ぐらい)
長くて面倒ですが判る方、どうか助けてください。
(インデント等は省いています)

投稿日時 - 2011-05-30 17:24:53

QNo.6774649

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.2

そもそも、質問者さんはスタックというデータ構造そのものを理解できていないようですので、
説明を載せてもらっても理解できないのではないでしょうか。大丈夫ですか?

>#1さん
質問者さんの投稿がOKWave本体からなのか提携掲示板からなのかわかりませんが、
少なくとも、OKWave本体においては、インデントを無視してしまいます。これは仕方のないことです。

また、#1さんがなさったような、全角空白による疑似インデントは、
投稿されたコードをそのままコンパイルしようとする側にとってはかえってじゃまです。
ご理解のほどお願いいたします。

投稿日時 - 2011-05-30 21:59:32

ANo.1

質問ならば、インデントこそ省くべきではありません
コンパイラにとってインデントは不要なものですが、人間が理解しやすくするために、空行やインデントを付けてソースがかかれているのです。
質問の記載状態では、関数のまとまりがどこからどこまでなのかすら見えません。

#include <stdio.h>
#define MAX 256
void pushdown(char *S, char x);
char popup(char *S);
void initialize(char *S);
int empty(char *S);
int top = 0;

void pushdown(char *S, char x){ /*スタックSにデータxを記憶*/
    if (top<MAX) {
        top++;
        S[top] = x;
    } else {
        printf("Stack S overflows.\n");
    }
}

char popup(char *S){ /*スタックSからデータの取出し*/
    if (top>0) {
        top--;
        return (S[top+1]);
    } else {
        printf("Stack S is empty.\n");
        return ('\0');
    }
}

// スタックの初期化
// しかし正直、配列を0クリアする部分は不要(top=0だけで十分)。
void initialize(char *S){
    int i;
    top = 0;
    for (i = 1; i < MAX; i++) {
        S[i] = '\0';
    }
}

// スタックが空かどうか調べる関数
int empty(char *S){
    if (top == 0) {
        return (1); // 空
    }
    return (0); // 空ではない
}

int main(void){
    char x;
    char S[MAX];
    
    pushdown(S,'a');    // 'a' をpush
    pushdown(S,'b');    // 'b' をpush
    pushdown(S,'c');    // 'c' をpush
    x = popup(S);    // pop→ 'c' 取り出し(しかしその値はどこにも使われない)
    x = popup(S);    // pop→ 'b' 取り出し(しかしその値はどこにも使われない)
    pushdown(S,'d');    // 'd' をpush
    x = popup(S);    // pop→ 'd' 取り出し(しかしその値はどこにも使われない)
    pushdown(S,'e');    // 'e' をpush
    while (!empty(S)) {    // スタックにある値を全て取り出しつつ、表示する    // ここまでのpush/popで、'a' 'e' が残っているはず
        printf("%c", popup(S));
    }
    printf("\n");
    return (0);
}


こんなところですか。

しかし、このプログラムにはバグがありますね。

char S[256]; として確保されるのは、S[0]~S[255] の256個です。
しかし、pushdownでは top++ してから値を保管しているので、最悪 S[256] という確保されていない領域に値を書き込んでしまいます。
とりあえず、char S[MAX+1];と宣言(確保)した方が良いでしょう。(きちんと0~255を使うようにpush/popを書き換えるほうがより良いんですが。)

また、initialize では、S[1]~S[255] を初期化していますが、S[0]の初期化を忘れています。
(上のコメントに書いたとおり、0クリアは意味がないんですが。なぜなら、初期化しなくても、pushで書き込んだ領域からしか読み込まないので、未定義の値を読み出す可能性は無いためです。)
このプログラムでは影響の出ないバグですが、本当に初期化しなければいけないときはきちんとしないと、バグが出たり出なかったりという厄介なパターンになる可能性があります。

投稿日時 - 2011-05-30 18:24:48

お礼

ご丁寧な説明とアドバイスありがとうございます。
バグに関してはこれから書きなおしてみます。

あとインデントも気を付けるようにします。
ありがとうございました。

投稿日時 - 2011-05-30 19:32:17

あなたにオススメの質問