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

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

ただいまの
回答率

90.84%

  • C

    3350questions

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

スタックのやり方がわかりません。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 161

wagon

score 3

 前提・実現したいこと

c言語でスタックの実現をしようとしています。
ファイルからデータをスタックに格納するところまではできたのですが、スタックからデータをブッシュするのがうまくいきません。

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

Pop関数をソースファイル内で使うとデータ文字列で読み込んだ最後の配列のみをスタックの容量分だけポップしてしまいます。
アクセス違反が発生してしまっています。

stack.exe の 0x0f73d540 (msvcr100d.dll) でハンドルされていない例外が発生しました: 0xC0000005: 場所 0xcccccccc を読み込み中にアクセス違反が発生しました。

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


ソースコード

#include <stdio.h>
#include "mystack.h"

int main(void)
{
    char buffer[128];
    char *data[100];
    struct student *seito[100];
    int i = 0;
    int j = 0;
    FILE *fpin;
    CharStack s;
    if(Initialize(&s,64) == -1)
    {
        puts("スタックの生成に失敗しました");
        return 1;
    }
        fpin = fopen( "input.txt", "r");
        if(fpin == NULL)
        {
                fprintf(stderr,"入力するファイルがオープンできません");
                return 0;
        }
        while(fgets(&buffer[0], sizeof(buffer),fpin) != NULL)
        {
                //スタックに代入
                if(Push(&s, &buffer[0]) == -1)
                {
                    puts("ブッシュに失敗しました");
                    break;
                }
                printf("%d\n",Size(&s));
                printf("%s\n",s.stk[i]);
                i++;
                //100人を超えたら読み込みを終了
                if(i>99)
                {
                    break;
                }

        }
        while(1)
        {
            if(Pop(&s,data[j]) == -1)
            {
                puts("ポップ終了");
                break;
            }
            printf("%s\n",s.stk[j]);
            printf("%d\n",Size(&s));
            j++;
        }
        //ファイルを閉じる
        fclose(fpin);
        set_data_student(&data[0],&seito[0],j);
        Terminate(&s);


    return 0;
}

ヘッダファイル

ifndef MYSTACK_H

define MYSTACK_H

include <stdio.h>

include <stdlib.h>

include <string.h>

define BUFFER_LENGTH 128

typedef struct
{
int max;    //スタックのサイズ
int ptr;    //スタックのポインタ
char **stk;    //スタック(の先頭要素へのポインタ)
} CharStack;

struct student
{
char name[12];
int math;
int eng;
};
/*--- スタックの初期化 ---*/
int Initialize(CharStack *s, int max)
{
s->ptr = 0;
if ((s->stk = calloc(max, sizeof(char *))) == NULL) {
s->max = 0;                                /* 配列の生成に失敗 */
return -1;
}
s->max = max;
return 0;
}
/*--- スタックの後始末 ---*/
void Terminate(CharStack *s)
{
if (s->stk != NULL)
free(s->stk);        /* 配列を破棄 */
s->max = s->ptr = 0;
}
/*--- スタックにデータをプッシュ ---*/
int Push(CharStack *s, char *x)
{
if (s->ptr >= s->max)                        /* スタックは満杯 */
return -1;
s->stk[s->ptr++] = x;
return 0;
}

/*--- スタックからデータをポップ ---*/
int Pop(CharStack *s, char *x)
{
if (s->ptr <= 0)                            /* スタックは空 */
return -1;
x = s->stk[--s->ptr];
return 0;
}
int Size(const CharStack *s)
{
return s->ptr;
}
//struct student構造体オブジェクトのメンバに値を格納する関数
struct student *set_student(char *n, int m, int e)
{
struct student *ps = NULL;
ps = (struct student*)malloc(1 * sizeof(struct student));
if(ps == NULL)
{
puts("記憶域の確保に失敗しました");
return NULL;    
}
strcpy(ps->name, n);
ps->math = m;
ps->eng = e;
return ps;
}
/*--データ文字列から数値や文字列にデータ変換をし構造体にまとめて管理する関数--*/
void set_data_student(char *data[], struct student *seito[],int length)
{
char n[12];
int m,e,i;
for(i=0;i<length;i++)
{
sscanf(data[i],"%s%d%d",n,&m,&e);
seito[i] = set_student(n,m,e);
}
}

 試したこと

ブレイクポイントを使ったところエラーはset_data_studentで起きているようでした。

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

visual C++ 2010 を使いました

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+2

CharStackのstkにアドレスを積んでいく構造のようですが、Push関数に渡している変数がmain関数で確保しているbuffer変数の先頭アドレス固定なので、積んだアドレスは全て同じ領域を指しています。
つまりファイルから読み込んだ最後の行が格納されているので、ポップしても全て同じ値が取得されます。
またPop関数で、data配列に積んだアドレスを格納しようとしているようですが、Pop関数側はダブルポインタにする必要があります。
今のままだと単にローカル変数を書き換えるだけなので、呼び出し元は変更されません。
これが原因で最後のset_data_studentで落ちていると思います。
以下の修正で落ちなくはなりますが、最初に挙げた問題があるので、そもそもの構成を見直す必要があります。

//int Pop(CharStack *s, char *x)
int Pop(CharStack *s, char **x)
{
    if (s->ptr <= 0)                            /* スタックは空 */
        return -1;
    //x = s->stk[--s->ptr];
    *x = s->stk[--s->ptr];
    return 0;
}
int main(void)
{
//~省略~
    while(1)
    {
        //if(Pop(&s,data[j]) == -1)
        if(Pop(&s,&data[j]) == -1)
        {

//~省略~
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/19 17:09 編集

    回答ありがとうございます。
    Pushの引数が固定になってしまっているのとPopの引数に問題があったんですね。
    もう一度構成から見直そうと思います。
    ベストアンサーにしたかったのですが押し間違えてしまいました。

    キャンセル

  • 2018/06/19 17:22

    ベストアンサーは後からでも変更できますよ(強要してるわけではありませんw)

    キャンセル

  • 2018/06/19 22:39

    ベストアンサーにさせていただきました。
    ありがとうございました。

    キャンセル

+1

push/pop でアドレスを読み書きしてますが、これだとアドレスが指した先のバッファまでは保存されません
バッファが開放されてしまうとアクセス違反となりますね

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/19 17:10

    回答ありがとうございます。
    もう一度見直そうと思います。

    キャンセル

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

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

関連した質問

同じタグがついた質問を見る

  • C

    3350questions

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