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

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

ただいまの
回答率

89.70%

スタックの応用

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,176

indehi

score 5

スタックを利用して入力された文字列の回文を作るプログラムを作成したら、出力されません。

例えば、「abcd」と入力したら、「abcddcba」と主著力される。

発生している問題・エラーメッセージ

文字列かendを入力してください->this

文字列かendを入力してください->end

該当のソースコード

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct cell{
  char c;
  struct cell *next;
};

struct cell *stack,*listhead=NULL;
char pop();
void free_stack();
void push(char ic[10]);
void print_stack();

int main(void){
  char moji[10];
  while(1){
    printf("文字列かendを入力してください->");
    scanf("%s",moji);

 if(strcmp(moji,"end")==0){
  free_stack();
  return 0;
  }


 else{
   while(stack!=NULL){
    push(moji);
   }
  print_stack();
  while(stack!=NULL){
    printf("%c",pop());
  print_stack();
  }

 }
  }
}

char pop(){
  char popdata;
  popdata=listhead->c;
  stack = listhead;
  listhead = listhead->next;
  free(stack);
  return popdata;
}
void free_stack(){
  if(listhead!=NULL)
    free(stack);
}
void push(char ic[10]){
  stack = (struct cell *)malloc(sizeof(struct cell));
  stack->c=ic[0];
  stack->next =listhead;
  listhead = stack;
}
void print_stack(){
  stack = listhead;
  while(stack!=NULL){
    printf("->%c",stack->c);
    stack = stack->next;
  }
  printf("\n");
}

試したこと

forループで回す

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

より詳細な情報

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • wake_up_kemeko

    2016/05/28 17:18 編集

    文字列かendを入力してください->abcd \n
    abcddcba \n

    文字列かendを入力してください-> \n
    という結果がほしいのでしょうか?

    キャンセル

  • indehi

    2016/05/28 17:46

    そうです!それです!
    配列使った方がいいんでしょうか

    キャンセル

  • HogeAnimalLover

    2016/05/28 21:50

    固定長配列で良いならその方が作りやすい、可変長への対応は少し高度なので、いきなり試すようなものではないよ。そもそも回文を作るだけならば入力文字列を出力後、逆順に出力すれば良いだけ。練習用の課題としてみるならば可変長の対応の方がずっと高度なので、慣れてからの方が良いよ。

    キャンセル

回答 3

+2

やりたいのはこういうことでしょうか?

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

#define STRLEN 10
struct cell {
    char c[STRLEN]; //文字列を持つなら配列orポインタ
    struct cell *next;
};

struct cell *stack=NULL, *listhead = NULL;
char pop();
void free_stack();
void push(char ic[]);
void print_stack();

int main(void) {


    char moji[STRLEN] = {'\0'};

    while (1) {
        printf("文字列かendを入力してください->");
        scanf_s("%s", moji,STRLEN);//セキュリティ向上 VSさんが言うこと聞かないので

        if (strcmp(moji, "end") == 0) {
            free_stack();
            return 0;
        }


        else {
            if (strlen(moji) >= STRLEN) {
                puts("文字長ながすぎんよ");
                continue;
            }

            push(moji);
            print_stack();
            while (stack != NULL) {
                printf("%c", pop());
                print_stack();
            }

        }
    }
}

char pop() {
    char popdata;
    popdata = listhead->c;
    stack = listhead;
    listhead = listhead->next;
    free(stack);
    return popdata;
}
void free_stack() {
    if (listhead != NULL)
        free(stack);
}
void push(char ic[]) {
    stack = (struct cell *)malloc(sizeof(struct cell));
    strcpy_s(stack->c,STRLEN,ic);//文字のコピー
    stack->next = listhead;
    listhead = stack;
}
void print_stack() {
    stack = listhead;
    while (stack != NULL) {
        printf("->%s", stack->c);
        stack = stack->next;
    }
    printf("\n");
}

それともこちら?

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

#define STRLEN 10
struct cell {
    char c; 
    struct cell *next;
};

struct cell *stack=NULL, *listhead = NULL;
char pop();
void free_stack();
void push(char ic);
void print_stack();

int main(void) {

    int i;
    char moji[STRLEN] = {'\0'};

    while (1) {
        printf("文字列かendを入力してください->");
        scanf_s("%s", moji,STRLEN);//セキュリティ向上 VSさんが言うこと聞かないので

        if (strcmp(moji, "end") == 0) {
            free_stack();
            return 0;
        }


        else {
            if (strlen(moji) >= STRLEN) {
                puts("文字長ながすぎんよ");
                continue;
            }

            for (i = 0; moji[i]; ++i)push(moji[i]);//文字が入力されてるだけ格納

            while (listhead != NULL) {//listheadに変更
                printf("%c", pop());
                print_stack();
            }

        }
    }
}

char pop() {
    char popdata;
    popdata = listhead->c;
    stack = listhead;
    listhead = listhead->next;
    free(stack);
    return popdata;
}
void free_stack() {
    if (listhead != NULL)
        free(stack);
}
void push(char ic) {//一文字読み込みなら配列じゃなくていい
    stack = (struct cell *)malloc(sizeof(struct cell));
    stack->c = ic;
    stack->next = listhead;
    listhead = stack;
}
void print_stack() {
    stack = listhead;
    while (stack != NULL) {
        printf("->%c", stack->c);
        stack = stack->next;
    }
    printf("\n");
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

本題に入る前に。

  1. 整形しよう。
    せめてインデントは揃えるようにしてください。ソースコードは綺麗に整形しているだけで、読みやすさが断然違います。読みやすければ、動きもわかりやすくなり、どこに問題があるかも把握しやすくなります。ツールなどを用いても良いでしょう。
  2. グローバル変数は使わずに、ローカル変数を引数で渡そう。
    グローバル変数はです。どうしても使用しなければ実現できない場合を除き、使用すべきではありません。変数は基本的にローカル変数を使いましょう。関数間で使用する変数は引数として渡しましょう。
  3. 変数の複数宣言は使わないようにしよう。
    int *a, b = 0;と言った変数の複数宣言は混乱の元になりやすく、使用すべきではありません。一つの宣言で一つ変数だけを宣言するようにしてください。
  4. マジックナンバーはマクロ定数で定義しよう。
    char str[256];としたときの256部分はマジックナンバーと言われます。このマジックナンバーがソースコードの複数箇所に現れると、問題が起きるときがあります。それは、数を変えたときです。全部変更したつもりが変更し忘れがあったりすると、バッファオーバーフローなどの致命的な問題を引き起こします。マクロ定数にして、一括で変更できるようにしましょう。
  5. printf()が'\n'で終わらないときは、flushしよう。
    C言語の入出力ではバッファリングというものを行っています。ある程度バッファにため込むことで、低速な入出力をなるべく停止しないように行うという仕組みです。printf()も直接標準出力に書き込むのではなく、標準出力のバッファに書き込むに過ぎません。そして、C言語の標準出力のバッファでは、バッファが一杯になるか、改行'\n'が現るまで、出力をしないようになっています。つまり、prinf()が'\n'で終わってなければ、最後まですぐに出力しない場合があります。そういうときはfflush()を使用して、バッファ内容を強制的に出力するように必要があります。
  6. scanf()で'%s'のみは危険なので、大きさを指定するか、scanf_s()fegts()を使おう。
    scanf("%s", str)とした場合gets()と同じぐらいの危険性をはらんでいます。絶対にこのままにすべきではありません。scanf("%9s", str)scanf_s("%s", str, 10)等とするか、またはfgets()を使いましょう。
  7. scanf()等を使用したときは、戻り値チェックとバッファ空読みをしよう。
    標準入力が閉じられるなどの理由でscanf()等が失敗するときがあります。必ず戻り値チェックをして、それ以上読み込みできないときは終了するようにしてください。そうでないと無限ループになり、プログラムが暴走するときがあります。また、用意した文字列の長さが足りず、改行まで読み込まれなかった場合もあります。次の読み込みでは読み込まれなかった文がバッファに残っているため、邪魔になります。空読みをして、バッファを空にしてから、次の読み込みを待ちましょう。
  8. malloc()の戻り値がNULLでないかをチェックしよう。
    メモリが足りないときはmalloc()は失敗し、NULLを返します。そのまま続行してしまうと、アプリケーションが落ちてしまいます。戻り値がNULLでないかをチェックして、失敗した場合は、エラーメッセージなどを出してから、終了するようにしましょう。
  9. void hoge()と関数宣言/定義で()内を省略するのはやめよう。
    C言語ではvoid hoge()void hoge(void)は意味が異なります。混同してはいけません。()とするのは引数が何でも良いという意味で、古い書き方であり、引数の型チェックがされなくなるためバグの元になります。引数無しであれば、(void)と明示しましょう。

以上を踏まえて、書き換えたら全く別物になってしまいました。ごめんなさい。

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

#define MOJI_SIZE 256

struct cell {
    char c;
    struct cell *next;
};

void push(struct cell **p_stack, char c);
char pop(struct cell **p_stack);
struct cell *make_stack(char *str);
void free_stack(struct cell *stcak);
void print_stack(struct cell *stack);

int main(void)
{
    while (1) {
        printf(u8"文字列かendを入力してください->");
        fflush(stdout);

        char moji[MOJI_SIZE];
        char *result_str = fgets(moji, MOJI_SIZE, stdin);

        if (result_str == NULL) {
            break;
        }

        if (moji[strlen(moji) - 1] == '\n') {
            moji[strlen(moji) - 1] = '\0';
        } else {
            printf(u8"入力文字が多すぎます。\n");
            while (1) {
                int c = getchar();
                if (c == EOF || c == '\n') {
                    break;
                }
            }
            continue;
        }

        if (strcmp(moji, "end") == 0) {
            break;
        }

        struct cell *stack = make_stack(moji);
        struct cell *reverse_stack = NULL;
        print_stack(stack);
        while (stack != NULL) {
            push(&reverse_stack, pop(&stack));
        }
        print_stack(reverse_stack);
        printf("\n");
        free_stack(stack);
        stack = NULL;
        free_stack(reverse_stack);
        reverse_stack = NULL;
    }
    return 0;
}

void push(struct cell **p_stack, char c)
{
    if (*p_stack == NULL) {
        *p_stack = (struct cell *)malloc(sizeof(struct cell));
        if (*p_stack == NULL) {
            fprintf(stderr, u8"メモリ確保に失敗しました。");
            exit(1);
        }
        (*p_stack)->c = c;
        (*p_stack)->next = NULL;
        return;
    }
    push(&((*p_stack)->next), c);
}

char pop(struct cell **p_stack)
{
    struct cell **p_next = &((*p_stack)->next);
    if (*p_next == NULL) {
        char c = (*p_stack)->c;
        free_stack(*p_stack);
        *p_stack = NULL;
        return c;
    }
    return pop(p_next);
}

struct cell *make_stack(char *str)
{
    struct cell *stack = NULL;
    for (char *p_c = str; *p_c != '\0'; p_c++) {
        push(&stack, *p_c);
    }
    return stack;
}

void free_stack(struct cell *stack)
{
    if (stack == NULL)
        return;
    struct cell *next = stack->next;
    free(stack);
    free_stack(next);
}

void print_stack(struct cell *stack)
{
    if (stack == NULL) {
        return;
    }
    printf("%c", stack->c);
    print_stack(stack->next);
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

0

こんなのでいいのでしょうか? 質問は随時どうぞ。

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

#define STRLEN 10
struct cell {
    char c;
    struct cell *next;
};

struct cell *stack = NULL, *listhead = NULL;
char pop();
void free_stack();
void push(char ic);
void print_stack();

int main(void) {

    int i;
    char moji[STRLEN] = { '\0' };

    while (1) {
        printf("文字列かendを入力してください->");
        scanf_s("%s", moji, STRLEN);//セキュリティ向上 VSさんが言うこと聞かないので

        if (strcmp(moji, "end") == 0) {
            free_stack();
            return 0;
        }


        else {
            if (strlen(moji) >= STRLEN) {
                puts("文字長ながすぎんよ");
                continue;
            }

            for (i = 0; moji[i]; ++i)push(moji[i]);//文字が入力されてるだけ格納

            while (listhead != NULL) {//listheadに変更
                printf("%c", pop());
            }
            puts("");

        }
    }
}

char pop() {
    char popdata;
    popdata = listhead->c;
    stack = listhead;
    listhead = listhead->next;
    free(stack);
    return popdata;
}
void free_stack() {
    if (listhead != NULL)
        free(stack);
}
void push(char ic) {//一文字読み込みなら配列じゃなくていい
    stack = (struct cell *)malloc(sizeof(struct cell));
    stack->c = ic;
    stack->next = listhead;
    listhead = stack;
    printf("%c",ic);//挿入される文字を表示
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 89.70%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる