ページ 11

mallocなどを使わずにすませる方法

Posted: 2008年2月24日(日) 11:21
by 黒猫
こんにちは、初めて質問致します黒猫です。
課題を解いているのですが、途中でつまづいてしまいました。
プログラムは完成しているのですが、教科書の見本などを繋ぎ合わせて作ったので、まだ理解出来ないまま使っているものがあります。「malloc」や「free」などです。
どうにかこれらを使わずに書き換えられないものでしょうか。
すみませんが、アドバイスをお願いいたします><
以下、設問と作成したプログラムです。

・名前(char)、身長(double)、体重(double)、視力(視力構造体)これらのデータをメンバとする構造体を定義して、入力された表示を行うプログラムを作成。
入力件数は最大5件で、名前は19文字までの入力。
範囲外だったならばエラーメッセージ(Sorry. Input less than 20 characters.)を表示し再入力。
名前に"END"が入力されたときは入力を終了して表の表示に移るが、もし最初に"END"が入力された場合は、その旨のメッセージ(Input data is nothing!)を出力。
表示は身長で昇順にソートして出力。
身長、体重は、小数第一位までの表示とし、視力は、小数第三位までの表示。
出力の幅は、名前が19文字、その他は5文字で指定。
視力は右(double)、左(double)をメンバとする構造体で扱うこと。
1件分の入力はinput_data()、表示はdisplay_data()、ソートはsort_data()と処理を関数に分けて行う。

名前の入力の所でつまずいています。
使用環境は、Visual C++2005、Win Vistaです。
#include<stdio.h> 
#include<string.h> 
#include<stdlib.h>

#define BUF 256
#define NAME_MAX 19
#define DATA_MAX 5

typedef struct eye
{ 
	double l_eye;     /*左視力*/
	double r_eye;     /*右視力*/
}Eye;

typedef struct
{
	char name[NAME_MAX + 1];   /*名前*/ 
	double height;     /*身長*/ 
	double weight;     /*体重*/ 
	Eye eye;      /*視力*/ 
}Person;


int input_data(Person *mem);
void sort_data(Person *pmem,int max_cnt);
void display_data(const Person *pmem,int max_cnt);


int main(void)
{
	int cnt;
	Person data[DATA_MAX];
	cnt = input_data(data);
	sort_data(data,cnt);
	display_data(data,cnt);

	return 0;

} 

int input_data(Person *mem)
{
	int i = 0,cnt = 0;
	char *buf;

	while( i < DATA_MAX )
        {
		buf = (char *)malloc( BUF * sizeof( char ) );
		if( buf )
                  {
			printf("\n");
			printf("Name   : ");
			scanf("%255s", buf);
		}

		if( !strcmp(buf,"END") && cnt == 0 )
                  {
			printf("\n Input data is nothing! \n");
			exit(0);
		}
		
		if( !strcmp(buf,"END") )
                  {
			return cnt;
		}

		if ( strlen(buf) > NAME_MAX )
                  { 
			printf("\n Sorry. Input less than %d characters. \n",NAME_MAX + 1);
			continue;
		}
		else
                  {
			strcpy( (mem+i)->name , buf );
			free(buf);
		}

		printf("Height : ");
		scanf("%lf", &((mem+i)->height));

		printf("Weight : "); 
		scanf("%lf", &((mem+i)->weight));

		printf("Eye(L) : ");
		scanf("%lf", &((mem+i)->eye.l_eye)); 

		printf("   (R) : "); 
		scanf("%lf", &((mem+i)->eye.r_eye));
		
		i++;
		cnt++;
	}
	
	return cnt;
}

void sort_data(Person *pmem,int max_cnt)
{
	int cnt1;
	int cnt2;
	Person temp;    /* 一時格納領域 */
	
	for(cnt1 = 0 ; cnt1 < max_cnt-1 ; cnt1++)         /* ソート処理 */
	{

		for(cnt2 = cnt1+1 ; cnt2 < max_cnt ; cnt2++)
		{ 
			if( (pmem+cnt1)->height > (pmem+cnt2)->height)
			{ 
				temp = *(pmem+cnt1);
				*(pmem+cnt1) = *(pmem+cnt2);
				*(pmem+cnt2) = temp;
			}
		}
	}
}


void display_data(const Person *pmem,int max_cnt)
{
	int cnt;      /* 個人情報件数カウンタ */

	printf("\n********Name***********Hi*****We***(L) Eye (R)**\n");	
	for(cnt = 0 ; cnt < max_cnt ; cnt++)
	{
		printf("%-*s %6.1f %6.1f %6.3f %6.3f\n", NAME_MAX,       /* データ表示 */
			        &(pmem+cnt)->name[0],(pmem+cnt)->height,(pmem+cnt)->weight,
			        (pmem+cnt)->eye.l_eye, (pmem+cnt)->eye.r_eye);
	}
	return;
	
}

以上です。
宜しくお願いします。

Re:mallocなどを使わずにすませる方法

Posted: 2008年2月24日(日) 11:33
by box
input_data関数の中の変数bufを
動的に確保するのではなく、
char型の配列で確保すればよいと思います。

Re:mallocなどを使わずにすませる方法

Posted: 2008年2月24日(日) 11:33
by tk-xleader
これならばfreeを全て消して、mallocで用意しているバッファを全て配列にしてしまえばいいと思います。
int input_data(Person *mem)
{
	int i = 0,cnt = 0;
	char buf[BUF];

	while( i < DATA_MAX )
        {
        /*以下元ソース*/
		/*
		buf = (char *)malloc( BUF * sizeof( char ) );
		if( buf )
                  {
			printf("\n");
			printf("Name   : ");
			scanf("%255s", buf);
		}
		*/
		/*新ソース*/
		printf("\n");
		printf("Name   : ");
		scanf("%255s", buf);

		if( !strcmp(buf,"END") && cnt == 0 )
                  {
			printf("\n Input data is nothing! \n");
			exit(0);
		}
		
		if( !strcmp(buf,"END") )
                  {
			return cnt;
		}

		if ( strlen(buf) > NAME_MAX )
                  { 
			printf("\n Sorry. Input less than %d characters. \n",NAME_MAX + 1);
			continue;
		}
		else
                  {
			strcpy( (mem+i)->name , buf );
			/*free(buf);*//*このfree()も取っ払う(コメント化)*/
		}

		printf("Height : ");
		scanf("%lf", &((mem+i)->height));

		printf("Weight : "); 
		scanf("%lf", &((mem+i)->weight));

		printf("Eye(L) : ");
		scanf("%lf", &((mem+i)->eye.l_eye)); 

		printf("   (R) : "); 
		scanf("%lf", &((mem+i)->eye.r_eye));
		
		i++;
		cnt++;
	}
	
	return cnt;
}
こんな感じです。元のソースはコメントとして残してあります。

Re:mallocなどを使わずにすませる方法

Posted: 2008年2月24日(日) 11:46
by box
input_data関数の中の変数iとcntの違いはどこにありますか?
もし、違いがないのであれば、一つにまとめる方がよいと思います。

ありがとうございました

Posted: 2008年2月24日(日) 12:24
by 黒猫
boxさん、tkmakwins15さん、ありがとうございました。
こんなに早くアドバイスを頂けるとは思っていなかったのでちょっと感動しています。
大袈裟ですみません。

mallocというのが、一時領域を確保してくれるというのはなんとなく分かったのですが、書き換え方が分からず・・・
大変勉強になりました。
配列での確保についてまだ勉強不足ということですよね。
もっと勉強します。


boxさんへ

> input_data関数の中の変数iとcntの違いはどこにありますか?
> もし、違いがないのであれば、一つにまとめる方がよいと思います。

ご指摘ありがとうございました。
おっしゃる通りです・・・同じ働きなので、一つにまとめる事にします。
他にも関数ごとに*pmemと*memとしているので、統一したほうが良いですよね。
もっと、どこが何をしているのかちゃんと考えながら作れるようにしようと思います。

お二人の方、本当にありがとうございました。