ページ 11

スタックについて質問させていただきたいものです。

Posted: 2015年5月20日(水) 19:54
by tutomeru
私は教科書のスタックの見本を元に身体測定のデータ(氏名、体重、年齢、視力、身長)を記録するプログラムを作りたいのですが、pushが正しく働いてくれません。もしかしたら他の部分も間違っているのかもしれないです。助言をいただけるとありがたいです。それと名前を入力するところで強制終了するようになってしまいました。C言語の能力は低いです。
申し訳ないのですがソースコードが長いです。

コード:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <limits.h>
#define line 100


typedef struct{
	double weight;
	double eyesight;
	int age;
	int height;
} Data;

typedef struct{
	char *name;
	Data data;
} sinntaisokutei ;
 
typedef struct{ 
int max;  
int pos;  
sinntaisokutei **stack; 
} sinntaisokuteistack;


int Initialize(sinntaisokuteistack *s, int max){ 
s->pos = 0; 
if ((s->stack = calloc(max, sizeof(sinntaisokutei *))) == NULL) { 
s->max = 0; 
return -1; 
} 

s->max = max; 
return 0; 
} 
 
void Terminate(sinntaisokuteistack *s){ 
if (s->stack != NULL){ 
while( --s->pos >= 0) 
free(s->stack[s->pos]); 
free(s->stack); 
} 
s->max = s->pos = 0; 
} 
 
int Push(sinntaisokuteistack *s, sinntaisokutei *x){ 
if (s->pos >= s->max) {
return -1;
} 
if ((s->stack[s->pos] = calloc(1, sizeof(sinntaisokutei))) == NULL) {
return -1; 
}
memcpy(s->stack[s->pos++],x,sizeof(sinntaisokutei));
return 0; 
} 

int Pop(sinntaisokuteistack *s, sinntaisokutei *x){ 
if (s->pos <= 0){
 return -1; 
}
s->pos--;
memcpy(x,s->stack[s->pos],sizeof(sinntaisokutei));
free(s->stack[s->pos]); 
return 0; 
} 

int Peek(sinntaisokuteistack *s, sinntaisokutei *x){ 
if (s->pos <= 0) {
return -1; 
}
memcpy(x,s->stack[s->pos-1],sizeof(sinntaisokutei)); 
return 0; 
} 

int Maximumnumber(const sinntaisokuteistack *s){ 
return s->max; 
} 

int Registrationnumber(const sinntaisokuteistack *s){ 
return s->pos; 
} 


void Print2(const sinntaisokutei *x){
	printf("%-18.18s%.2lf%5.4d%5.4d%.2lf\n", x->name, x->data.weight, x->data.age, x->data.height, x->data.eyesight);
}


void Print(const sinntaisokuteistack *s){ 
int i; 
for(i = 0; i < s->pos; i++) {
Print2(s->stack[i]); 
}
putchar('\n');
} 


int main(void){ 
sinntaisokuteistack s; 
int max; 
printf("何人登録しますか"); 
scanf("%d", &max); 
if (Initialize(&s, max)==-1){ 
puts("登録できません.\n"); 
return 1; 
} 

while (1) { 
int select; 
sinntaisokutei x[line]; 
printf("現在のデータ数:%d/%d\n",Registrationnumber(&s), Maximumnumber(&s)); 
printf("(1)登録 (2)削除 (3)次に削除されるデータ (4)全データ表\示 (0)終了:"); 
scanf("%d", &select); 
if (select == 0) break; 

switch (select) { 
case 1: 
printf("名前: "); scanf("%s", x->name);
printf("体重: "); scanf("%lf", &(x->data.weight));
printf("年齢: "); scanf("%d", &(x->data.age));
printf("視力: "); scanf("%lf", &(x->data.eyesight));
printf("身長: "); scanf("%d", &(x->data.height));
if (Push(&s, x) == -1) 
puts("\aエラー:登録できませんでした.\n"); 
break; 
case 2: 
if (Pop(&s, x) == -1) 
puts("\aエラー:削除出来ませんでした.\n"); 
else{ 
printf("削除したしたデータは"); 
Print2(x);
} 
break; 
case 3: 
if (Peek(&s, x) == -1) 
puts("\aエラー:表\示できませんでした.\n"); 
else{ 
printf("次に削除されるデータは%s", x); 
} 
break; 
case 4: 
Print(&s); 
break; 
} 
} 
Terminate(&s); 
return 0; 
}
よろしくお願いします。

Re: スタックについて質問させていただきたいものです。

Posted: 2015年5月20日(水) 22:24
by みけCAT
tutomeru さんが書きました:pushが正しく働いてくれません。
せっかくcallocで領域を確保しても、別の場所へのポインタで上書きしてしまったら意味がありません。
memcpyなどでデータのコピーを行ってください。
それと、mbstrlenなどという謎の関数は使用せず、callocの第一引数は1でいいです。
tutomeru さんが書きました:それと名前を入力するところで強制終了するようになってしまいました。
初期化されていないポインタが指している謎の領域に書き込もうとしたからですね。
例えば、このようにして入力しながら必要な領域を確保するといいでしょう。

コード:

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

char *readOneLine(void) {
	struct readBuffer {
		char buf[16];
		struct readBuffer *next;
	};
	struct readBuffer *head=NULL;
	struct readBuffer **current=&head;
	struct readBuffer *next;
	int input;
	int count=0;
	int allCount=0;
	char *result;
	int i;
	for(;;) {
		input=getchar();
		if(input=='\n' || input==EOF)break;
		if(*current==NULL) {
			*current=(struct readBuffer*)malloc(sizeof(struct readBuffer));
			if(head==NULL) {
				/* メモリ確保失敗 */
				while (head!=NULL) {
					next=head->next;
					free(head);
					head=next;
				}
				return NULL;
			}
			(*current)->next=NULL;
			count=0;
		}
		(*current)->buf[count++]=input;
		allCount++;
		if(count>=(int)(sizeof((*current)->buf)/sizeof((*current)->buf[0]))) {
			current=&(*current)->next;
		}
	}
	result=(char*)malloc(allCount+1);
	if(result==NULL) {
		/* メモリ確保失敗 */
		while (head!=NULL) {
			next=head->next;
			free(head);
			head=next;
		}
		return NULL;
	}
	current=&head;
	count=0;
	for(i=0;i<allCount;i++) {
		result[i]=(*current)->buf[count++];
		if(count>=(int)(sizeof((*current)->buf)/sizeof((*current)->buf[0]))) {
			current=&(*current)->next;
			count=0;
		}
	}
	result[allCount]='\0';
	while (head!=NULL) {
		next=head->next;
		free(head);
		head=next;
	}
	return result;
}

/* 使用例 : 1行読み込んでそのまま出力する */
int main(void) {
	char *data = readOneLine();
	puts(data);
	free(data);
	return 0;
}

Re: スタックについて質問させていただきたいものです。

Posted: 2015年5月21日(木) 03:03
by tutomeru
助言ありがとうございます。
見本のプログラムをみて強制終了の件の疑問は解決したのですが実行結果がおかしいです。

memcpy(s->stack[s->pos++],x,sizeof(sinntaisokutei));
というふうにすれば正しくコピーされると考えたのですが
tanaka 1 1 1 1
yamamoto 2 2 2 2
と入力してから全データ表示をすると
実行結果が
tanaka 1 1 1 1
tanaka 1 1 1 1
となります。
xの構造体をスタックに積むという動作になると考えているのですが・・・

実行結果が
tanaka 1 1 1 1
yamamoto 2 2 2 2
にならないのでしょうか?

よろしくお願いします。

Re: スタックについて質問させていただきたいものです。

Posted: 2015年5月21日(木) 09:08
by みけCAT
tutomeru さんが書きました:tanaka 1 1 1 1
yamamoto 2 2 2 2
と入力してから全データ表示をすると
実行結果が
tanaka 1 1 1 1
tanaka 1 1 1 1
となります。
現状のコードをそのまま実行したところRuntime Errorになってしまったのでメモリを確保する処理を追加して実験したのですが、
1件目と2件目で異なるデータが表示され、再現できませんでした。
一応、そちらでテストに使用した(起動~終了の)入力一式を提示していただけますか?

Re: スタックについて質問させていただきたいものです。

Posted: 2015年5月21日(木) 12:30
by tutomeru
中途半端に編集をしてしまい申し訳ありません。
いろいろ改変した結果、現在の時点の私の使っているソースです。

コード:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <limits.h>
#define Line 80


typedef struct{
	double weight;
	int height;
	int age;
} Data;

typedef struct{
	char *name;
	Data data;
} Measurements ;


typedef struct{ 
int max; 
int pos;
Measurements **stk; 
} MeasurementsStack;

 
int Initialize(MeasurementsStack *s, int max){ 
s->pos = 0; 
if ((s->stk = calloc(max, sizeof(Measurements *))) == NULL) { 
s->max = 0;
return -1; 
} 
 
s->max = max; 
return 0; 
} 
 
void Terminate(MeasurementsStack *s){ 
if (s->stk != NULL){ 
while( --s->pos >= 0) 
free(s->stk[s->pos]);  
free(s->stk); 
} 
s->max = s->pos = 0; 
} 

int Push(MeasurementsStack *s, Measurements *x){ 
if (s->pos >= s->max) return -1; 
if ((s->stk[s->pos] = calloc(1, sizeof(Measurements))) == NULL) 
 
return -1; 
memcpy(s->stk[s->pos],x,sizeof(Measurements));  
s->pos++; 
return 0; 
} 

int Pop(MeasurementsStack *s, Measurements *x){ 
if (s->pos <= 0) return -1;  

s->pos--; 
memcpy(x,s->stk[s->pos],sizeof(Measurements));  
return 0; 
} 
 
int Peek(MeasurementsStack *s, Measurements *x){ 
if (s->pos <= 0) return -1; 
memcpy(x,s->stk[s->pos-1],sizeof(Measurements));  
return 0; 
} 

int Capacity(const MeasurementsStack *s){ 
return s->max; 
} 

int Occupancy(const MeasurementsStack *s){ 
return s->pos; 
} 
 

void Print2(const Measurements *x){
	printf("名前%-10.10s年齢%2d 身長%d 体重%3.1lf\n", x->name,x->data.age,x->data.height,x->data.weight);
}


void Print(const MeasurementsStack *s){ 
int i; 
for(i = 0; i < s->pos; i++) 
Print2(s->stk[i]); 
putchar('\n');
} 


int main(void){ 
MeasurementsStack s; 
int max; 
printf("何人登録しますか"); 
scanf("%d", &max); 
if (Initialize(&s, max)==-1){ 
puts("スタックの作成に失敗しました.\n"); 
return 1; 
} 

while (1) { 
int select; 
Measurements x[Line]; 
printf("現在のデータ数:%d/%d\n",Occupancy(&s), Capacity(&s)); 
printf("(1)登録 (2)削除 (3)削除されるデータ確認 (4)表\示 (0)終了:"); 
scanf("%d", &select); 
if (select == 0) break; 
switch (select) { 
case 1: /* プッシュ */ 
printf("名前: "); scanf("%s", x->name);
printf("年齢: "); scanf("%d", &(x->data.age));
printf("身長: "); scanf("%d", &(x->data.height));
printf("体重: "); scanf("%lf", &(x->data.weight));
if (Push(&s, x) == -1) 
puts("\aエラー:登録に失敗しました.\n"); 
break; 
case 2: /* ポップ */ 
if (Pop(&s, x) == -1) 
puts("\aエラー:削除に失敗しました.\n"); 
else{ 
printf("削除したデータは"); 
Print2(x);
} 
break; 
case 3: /* ピーク */ 
if (Peek(&s, x) == -1) 
puts("\aエラー:表\示に失敗しました.\n"); 
else{ 
printf("次に削除されるデータは%s,", x); 
} 
break; 
case 4: 
Print(&s); 
break; 
} 
} 
Terminate(&s); 
return 0; 
}
疑問に思うこと
①typedef structのDataの中の変数を4つ以上にすると名前を登録するところで強制終了してしまうこと。
②typedef structのMeasurementsの中の*nameのままなら
tanaka 29 31 99
yamamoto 33 193 34
と入力した場合に
tanaka 29 31 99
tanaka 33 193 34
という実行結果になってしまうが
typedef structのMeasurementsの中のname[20]にすると
tanaka 29 31 99
yamamoto 33 193 34
と入力した場合に
tanaka 29 31 99
yamamoto 33 193 34
と正しく表示される理由。
2点の理由を教えていただけるとありがたいです。

Re: スタックについて質問させていただきたいものです。

Posted: 2015年5月21日(木) 13:29
by みけCAT
tutomeru さんが書きました:疑問に思うこと
①typedef structのDataの中の変数を4つ以上にすると名前を登録するところで強制終了してしまうこと。
②typedef structのMeasurementsの中の*nameのままなら
tanaka 29 31 99
yamamoto 33 193 34
と入力した場合に
tanaka 29 31 99
tanaka 33 193 34
という実行結果になってしまうが
typedef structのMeasurementsの中のname[20]にすると
tanaka 29 31 99
yamamoto 33 193 34
と入力した場合に
tanaka 29 31 99
yamamoto 33 193 34
と正しく表示される理由。
2点の理由を教えていただけるとありがたいです。
わかりません。
自動記憶域期間のオブジェクトの値が不定の時に使用された場合。 (6.2.4, 6.7.8, 6.8)
(http://www.c-lang.org/detail/undefined_behavior.html)
に該当し、未定義動作になります。
tutomeru さんが書きました:typedef structのMeasurementsの中のname[20]にすると
この場合は(入力が長すぎなければ)きちんと読み込み先が確保されているので、正常に動作しそうだと思います。

Re: スタックについて質問させていただきたいものです。

Posted: 2015年5月21日(木) 15:02
by tutomeru
返信ありがとうございます。
*nameで正しく動かす方法が分かると次に困る確率が減るので誰か知っている方は教えていただけると助かります。

Re: スタックについて質問させていただきたいものです。

Posted: 2015年5月21日(木) 16:46
by みけCAT
tutomeru さんが書きました:返信ありがとうございます。
*nameで正しく動かす方法が分かると次に困る確率が減るので誰か知っている方は教えていただけると助かります。
自分がNo: 2で投稿したreadOneLine関数を使ってください。
scanfの仕様に近づけたければ、

コード:

if(input=='\n' || input==EOF)break;
という行を、

コード:

if(input=='\n' || input=='\t' || input==' ' || input==EOF)break;
のようにするといいでしょう。

Re: スタックについて質問させていただきたいものです。

Posted: 2015年5月21日(木) 17:03
by みけCAT
さらにscanf("%s",hoge)の挙動に近づけてみました。

コード:

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

char *readOneLine(void) {
	struct readBuffer {
		char buf[16];
		struct readBuffer *next;
	};
	struct readBuffer *head=NULL;
	struct readBuffer **current=&head;
	struct readBuffer *next;
	int input;
	int count=0;
	int allCount=0;
	char *result;
	int i;
	for(;;) {
		input=getchar();
		if (allCount==0 && isspace(input)) continue; /* 最初の空白を読み飛ばす */
		if(input==EOF || isspace(input)) {
			if(input!=EOF) ungetc(input, stdin);
			break;
		}
		if(*current==NULL) {
			*current=(struct readBuffer*)malloc(sizeof(struct readBuffer));
			if(head==NULL) {
				/* メモリ確保失敗 */
				while (head!=NULL) {
					next=head->next;
					free(head);
					head=next;
				}
				return NULL;
			}
			(*current)->next=NULL;
			count=0;
		}
		(*current)->buf[count++]=input;
		allCount++;
		if(count>=(int)(sizeof((*current)->buf)/sizeof((*current)->buf[0]))) {
			current=&(*current)->next;
		}
	}
	result=(char*)malloc(allCount+1);
	if(result==NULL) {
		/* メモリ確保失敗 */
		while (head!=NULL) {
			next=head->next;
			free(head);
			head=next;
		}
		return NULL;
	}
	current=&head;
	count=0;
	for(i=0;i<allCount;i++) {
		result[i]=(*current)->buf[count++];
		if(count>=(int)(sizeof((*current)->buf)/sizeof((*current)->buf[0]))) {
			current=&(*current)->next;
			count=0;
		}
	}
	result[allCount]='\0';
	while (head!=NULL) {
		next=head->next;
		free(head);
		head=next;
	}
	return result;
}

/* 使用例 : 1語読み込んで引用符を付けてそのまま出力する */
int main(void) {
	char *data = readOneLine();
	printf("\"%s\"\n",data);
	free(data);
	return 0;
}

Re: スタックについて質問させていただきたいものです。

Posted: 2015年5月21日(木) 17:05
by tutomeru
申し訳ないです。私のC言語の能力が低くて、いただいたプログラムの利用方法が悪いのか実行結果が変わりません。

コード:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <limits.h>
#define Line 80
 
 
typedef struct{
    double weight;
    int height;
    int age;
} Data;
typedef struct{
    char *name;
    Data data;
} Measurements ;
 
 
typedef struct{ 
int max; 
int pos;
Measurements **stk; 
} MeasurementsStack;
 
 
 char *readOneLine(void) {
    struct readBuffer {
        char buf[16];
        struct readBuffer *next;
    };
    struct readBuffer *head=NULL;
    struct readBuffer **current=&head;
    struct readBuffer *next;
    int input;
    int count=0;
    int allCount=0;
    char *result;
    int i;
    for(;;) {
        input=getchar();
        if(input=='\n' || input=='\t' || input==' ' || input==EOF)break;
        if(*current==NULL) {
            *current=(struct readBuffer*)malloc(sizeof(struct readBuffer));
            if(head==NULL) {
                /* メモリ確保失敗 */
                while (head!=NULL) {
                    next=head->next;
                    free(head);
                    head=next;
                }
                return NULL;
            }
            (*current)->next=NULL;
            count=0;
        }
        (*current)->buf[count++]=input;
        allCount++;
        if(count>=(int)(sizeof((*current)->buf)/sizeof((*current)->buf[0]))) {
            current=&(*current)->next;
        }
    }
    result=(char*)malloc(allCount+1);
    if(result==NULL) {
        /* メモリ確保失敗 */
        while (head!=NULL) {
            next=head->next;
            free(head);
            head=next;
        }
        return NULL;
    }
    current=&head;
    count=0;
    for(i=0;i<allCount;i++) {
        result[i]=(*current)->buf[count++];
        if(count>=(int)(sizeof((*current)->buf)/sizeof((*current)->buf[0]))) {
            current=&(*current)->next;
            count=0;
        }
    }
    result[allCount]='\0';
    while (head!=NULL) {
        next=head->next;
        free(head);
        head=next;
    }
    return result;
}

 
int Initialize(MeasurementsStack *s, int max){ 
s->pos = 0; 
if ((s->stk = calloc(max, sizeof(Measurements *))) == NULL) { 
s->max = 0;
return -1; 
} 
 
s->max = max; 
return 0; 
} 
 
void Terminate(MeasurementsStack *s){ 
if (s->stk != NULL){ 
while( --s->pos >= 0) 
free(s->stk[s->pos]);  
free(s->stk);
} 
s->max = s->pos = 0; 
} 
 
int Push(MeasurementsStack *s, Measurements *x){ 

if (s->pos >= s->max) return -1; 
if ((s->stk[s->pos] = calloc(1, sizeof(Measurements))) == NULL) 

return -1; 
memcpy(s->stk[s->pos],x,sizeof(Measurements));  
s->pos++; 
return 0; 
} 
 
int Pop(MeasurementsStack *s, Measurements *x){ 
if (s->pos <= 0) return -1;  
 
s->pos--; 
memcpy(x,s->stk[s->pos],sizeof(Measurements));  
return 0; 
} 
 
int Peek(MeasurementsStack *s, Measurements *x){ 
if (s->pos <= 0) return -1; 
memcpy(x,s->stk[s->pos-1],sizeof(Measurements));  
return 0; 
} 
 
int Capacity(const MeasurementsStack *s){ 
return s->max; 
} 
 
int Occupancy(const MeasurementsStack *s){ 
return s->pos; 
} 
 
 
void Print2(const Measurements *x){
    printf("名前%-10.10s年齢%2d 身長%d 体重%3.1lf\n", x->name,x->data.age,x->data.height,x->data.weight);
}
 
 
void Print(const MeasurementsStack *s){ 
int i; 
for(i = 0; i < s->pos; i++) 
Print2(s->stk[i]); 
putchar('\n');
} 
 
 
int main(void){ 
MeasurementsStack s; 
int max; 
printf("何人登録しますか"); 
scanf("%d", &max); 
if (Initialize(&s, max)==-1){ 
puts("スタックの作成に失敗しました.\n"); 
return 1; 
} 
char *data = readOneLine();
 
while (1) { 
int select; 
Measurements x[Line]; 
printf("現在のデータ数:%d/%d\n",Occupancy(&s), Capacity(&s)); 
printf("(1)登録 (2)削除 (3)削除されるデータ確認 (4)表\示 (0)終了:"); 
scanf("%d", &select); 
if (select == 0) break; 
switch (select) { 
case 1: /* プッシュ */ 
printf("名前: "); scanf("%s", x->name);
printf("年齢: "); scanf("%d", &(x->data.age));
printf("身長: "); scanf("%d", &(x->data.height));
printf("体重: "); scanf("%lf", &(x->data.weight));
if (Push(&s, x) == -1) 
puts("\aエラー:登録に失敗しました.\n"); 
break; 
case 2: /* ポップ */ 
if (Pop(&s, x) == -1) 
puts("\aエラー:削除に失敗しました.\n"); 
else{ 
printf("削除したデータは"); 
Print2(x);
} 
break; 
case 3: /* ピーク */ 
if (Peek(&s, x) == -1) 
puts("\aエラー:表\示に失敗しました.\n"); 
else{ 
printf("次に削除されるデータは%s,", x); 
} 
break; 
case 4: 
Print(&s); 
break; 
} 
} 
Terminate(&s); 
 free(data);
return 0; 
}
tanaka 29 31 99
yamamoto 33 193 34
と入力した場合に
tanaka 29 31 99
tanaka 33 193 34
となってしまいます。
申し訳ないです。

Re: スタックについて質問させていただきたいものです。

Posted: 2015年5月21日(木) 19:24
by みけCAT
tutomeru さんが書きました:申し訳ないです。私のC言語の能力が低くて、いただいたプログラムの利用方法が悪いのか実行結果が変わりません。
デタラメな場所に書き込もうとしてはいけません。
ちゃんとreadOneLine関数をデータの入力に使用してください。

また、このプログラムでは、3の削除されるデータ確認を実行すると、
意図しないデータが出力されそうです。

さらに、インデントを整え、main関数内のxの2番目以降の無駄な領域を確保しないようにすると、
よりよいプログラムになりそうだと思います。

コード:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <limits.h>
#include <ctype.h>
#define Line 80
 
 
typedef struct{
    double weight;
    int height;
    int age;
} Data;
typedef struct{
    char *name;
    Data data;
} Measurements ;
 
 
typedef struct{ 
int max; 
int pos;
Measurements **stk; 
} MeasurementsStack;
 
 
char *readOneLine(void) {
	struct readBuffer {
		char buf[16];
		struct readBuffer *next;
	};
	struct readBuffer *head=NULL;
	struct readBuffer **current=&head;
	struct readBuffer *next;
	int input;
	int count=0;
	int allCount=0;
	char *result;
	int i;
	for(;;) {
		input=getchar();
		if (allCount==0 && isspace(input)) continue; /* 最初の空白を読み飛ばす */
		if(input==EOF || isspace(input)) {
			if(input!=EOF) ungetc(input, stdin);
			break;
		}
		if(*current==NULL) {
			*current=(struct readBuffer*)malloc(sizeof(struct readBuffer));
			if(head==NULL) {
				/* メモリ確保失敗 */
				while (head!=NULL) {
					next=head->next;
					free(head);
					head=next;
				}
				return NULL;
			}
			(*current)->next=NULL;
			count=0;
		}
		(*current)->buf[count++]=input;
		allCount++;
		if(count>=(int)(sizeof((*current)->buf)/sizeof((*current)->buf[0]))) {
			current=&(*current)->next;
		}
	}
	result=(char*)malloc(allCount+1);
	if(result==NULL) {
		/* メモリ確保失敗 */
		while (head!=NULL) {
			next=head->next;
			free(head);
			head=next;
		}
		return NULL;
	}
	current=&head;
	count=0;
	for(i=0;i<allCount;i++) {
		result[i]=(*current)->buf[count++];
		if(count>=(int)(sizeof((*current)->buf)/sizeof((*current)->buf[0]))) {
			current=&(*current)->next;
			count=0;
		}
	}
	result[allCount]='\0';
	while (head!=NULL) {
		next=head->next;
		free(head);
		head=next;
	}
	return result;
}

 
int Initialize(MeasurementsStack *s, int max){ 
s->pos = 0; 
if ((s->stk = calloc(max, sizeof(Measurements *))) == NULL) { 
s->max = 0;
return -1; 
} 
 
s->max = max; 
return 0; 
} 
 
void Terminate(MeasurementsStack *s){ 
if (s->stk != NULL){ 
while( --s->pos >= 0) 
free(s->stk[s->pos]);  
free(s->stk);
} 
s->max = s->pos = 0; 
} 
 
int Push(MeasurementsStack *s, Measurements *x){ 

if (s->pos >= s->max) return -1; 
if ((s->stk[s->pos] = calloc(1, sizeof(Measurements))) == NULL) 

return -1; 
memcpy(s->stk[s->pos],x,sizeof(Measurements));  
s->pos++; 
return 0; 
} 
 
int Pop(MeasurementsStack *s, Measurements *x){ 
if (s->pos <= 0) return -1;  
 
s->pos--; 
memcpy(x,s->stk[s->pos],sizeof(Measurements));  
return 0; 
} 
 
int Peek(MeasurementsStack *s, Measurements *x){ 
if (s->pos <= 0) return -1; 
memcpy(x,s->stk[s->pos-1],sizeof(Measurements));  
return 0; 
} 
 
int Capacity(const MeasurementsStack *s){ 
return s->max; 
} 
 
int Occupancy(const MeasurementsStack *s){ 
return s->pos; 
} 
 
 
void Print2(const Measurements *x){
    printf("名前%-10.10s年齢%2d 身長%d 体重%3.1lf\n", x->name,x->data.age,x->data.height,x->data.weight);
}
 
 
void Print(const MeasurementsStack *s){ 
int i; 
for(i = 0; i < s->pos; i++) 
Print2(s->stk[i]); 
putchar('\n');
} 
 
 
int main(void){ 
MeasurementsStack s; 
int max; 
printf("何人登録しますか"); 
scanf("%d", &max); 
if (Initialize(&s, max)==-1){ 
puts("スタックの作成に失敗しました.\n"); 
return 1; 
} 
 
while (1) { 
int select; 
Measurements x[Line]; 
printf("現在のデータ数:%d/%d\n",Occupancy(&s), Capacity(&s)); 
printf("(1)登録 (2)削除 (3)削除されるデータ確認 (4)表\示 (0)終了:"); 
scanf("%d", &select); 
if (select == 0) break; 
switch (select) { 
case 1: /* プッシュ */ 
printf("名前: "); x->name = readOneLine();
printf("年齢: "); scanf("%d", &(x->data.age));
printf("身長: "); scanf("%d", &(x->data.height));
printf("体重: "); scanf("%lf", &(x->data.weight));
if (Push(&s, x) == -1) 
puts("\aエラー:登録に失敗しました.\n"); 
break; 
case 2: /* ポップ */ 
if (Pop(&s, x) == -1) 
puts("\aエラー:削除に失敗しました.\n"); 
else{ 
printf("削除したデータは"); 
Print2(x);
} 
break; 
case 3: /* ピーク */ 
if (Peek(&s, x) == -1) 
puts("\aエラー:表\示に失敗しました.\n"); 
else{ 
printf("次に削除されるデータは%s,", x); 
} 
break; 
case 4: 
Print(&s); 
break; 
} 
} 
Terminate(&s); 
return 0; 
}
オフトピック
読み込んだ文字列がメモリリークしますが…二重開放のリスクの方が高いので無視しましょう。
メモリリークも二重開放も回避するには、Pushなどでコピーするときにシャローコピーをするのではなく、
nameが指す文字列もコピーし、コピー元とコピー先で別の領域の文字列を利用するようにするとよいでしょう。

Re: スタックについて質問させていただきたいものです。

Posted: 2015年5月21日(木) 20:41
by tutomeru
ありがとうございました。間違えて理解していたようです。
もう一度C言語の勉強を基礎からやり直さないと、また根本的な間違いを起こすと感じました。
みけCAT さん、質問への回答ありがとうございました。