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

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

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

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

Q&A

解決済

2回答

407閲覧

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

wagon

総合スコア11

C

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

0グッド

0クリップ

投稿2018/06/18 14:38

編集2018/06/19 08:12

前提・実現したいこと

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

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

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

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

#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 を使いました

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

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

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

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

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

guest

回答2

0

ベストアンサー

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

c

1//int Pop(CharStack *s, char *x) 2int Pop(CharStack *s, char **x) 3{ 4 if (s->ptr <= 0) /* スタックは空 */ 5 return -1; 6 //x = s->stk[--s->ptr]; 7 *x = s->stk[--s->ptr]; 8 return 0; 9} 10int main(void) 11{ 12//~省略~ 13 while(1) 14 { 15 //if(Pop(&s,data[j]) == -1) 16 if(Pop(&s,&data[j]) == -1) 17 { 18 19//~省略~ 20}

投稿2018/06/19 01:34

ttyp03

総合スコア16998

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

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

wagon

2018/06/19 08:14 編集

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

2018/06/19 08:22

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

2018/06/19 13:39

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

0

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

投稿2018/06/18 21:09

y_waiwai

総合スコア87749

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

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

wagon

2018/06/19 08:10

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問