「C言語練習」 2-3.c   ・前へ   ・次へ
/* 構造体   2-3.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*  構造体(struct[=structure] 構造)は、幾つかのdataの集まりを一つの纏まりとして扱う
もので、struct 構造体名{変数1,変数2,,,}; の形でmain()の前に書いて定義する。例えば、

dataA1  dataB1  dataC1  dataD1
dataA2  dataB2  dataC2  dataD2
 ...     ...     ...     ...
 ...     ...     ...     ...

 と続く様なdataの場合、[dataA dataB dataC dataD]を一纏まりとして扱うのが便利である。
この時、dataA, B, C, D を構造体のmember(構成要素)と呼ぶ。
*/

struct st_hw
{
	char name[21];
	float h;
	float w;
};

main()
{
	int i,j,n;
	char dmy[101],fname[50];
	struct st_hw hw[500],temp;

/*  定義した構造体をmain()で扱う際の名前(変数名)を宣言する。文末には当然 ; を付ける。
ここでは、配列として500確保するとともに、同じ構造を持つtempも宣言した(並べ替えに必要)。
構造体本体の名(ここではst_hw)は標識[tag]であり、main()で扱う時は変数名(ここではhw,temp)
を使う。*/

	FILE *fin;

	printf("* 身長と体重 *\n\nFile名を入力:");
		gets(fname);
			putchar('\n');
	fin=fopen(fname,"r");	// 入力fileを開ける。
		if (fin==NULL) {printf("File がありません!\n\nEnd\n"); exit(1);}

/* fileには次の様な形でdataが納まっているとする。nameに空白も可とすると、fscanfでは
読めない。そこで、空白も読める fgets[=file get string]を使う事にする。
	name1
	h1  w1
	name2
	h2  w2
	 .....
*/
		i=0;
	while (! feof(fin)) {
		fgets(dmy,100,fin); dmy[strlen(dmy)-1]='\0'; 

/*  fgetsは改行も文字として取り込むので、終端一つ前の改行文字を終端記号に置換する。*/

			if (strlen(dmy)>20) dmy[20]='\0';

/*  入力文字列が指定した長さ以上の場合に切り詰める。いったんdmyで受ける理由。*/

			strcpy(hw[i].name,dmy); 

/*  その後で、読み込んだ文字列を用意したnameに納めている。構造体の各構成要素を指定する
  には、[構造体を扱う名前][.][構成要素名]とする。*/

		fscanf(fin,"%f %f",&hw[i].h,&hw[i].w);
		fgets(dmy,100,fin);

/*  fscanfは改行を取り込まず、fgetsは改行を文字として取り込む。両方を混ぜて使うと読み
込みが乱れるので、fscanfの後に残った改行文字をdmyで取り込んでおく。fscanfの後にfgetsで
文字列を読もうとする場合には必要。*/

		printf("%-20s  %.1f  %.1f\n",hw[i].name,hw[i].h,hw[i].w);
		i++;
		if (i%20==0) gets(dmy);	// data数が多い時の表示待ち
	}

	fclose(fin);	// 入力fileを閉じる。
		n=i;	// iで数えたdata数を nに代入。

	//-----------------
		printf("\n身長順に並べ替えます。(Enter Keyを押して下さい)\n");
	for (i=0;i<n-1;i++) {
		for (j=i+1;j<n;j++) 
			if (hw[i].h>hw[j].h)
			{temp=hw[i]; hw[i]=hw[j]; hw[j]=temp;}
	}

/*  dataの一単位が複数の構成要素からなっている場合(名前、身長、体重の様に)、ある構成要素
を並べ替えれば他の構成要素も並べ替えねばならない。構造体を用いれば、一単位を一変数の様に
扱えるので上の様にすっきりと書ける。*/

	for (i=0;i<n;i++) {
		if (i%20==0) gets(dmy);
		printf("%-20s  %.1f  %.1f\n",hw[i].name,hw[i].h,hw[i].w);
	}
	//-----並べ替えたものを表示-------------
		printf("\n体重順に並べ替えます。(Enter Keyを押して下さい)\n");
	for (i=0;i<n-1;i++) {
		for (j=i+1;j<n;j++) 
			if (hw[i].w>hw[j].w)
			{temp=hw[i]; hw[i]=hw[j]; hw[j]=temp;}
	}

	for (i=0;i<n;i++) {
		if (i%20==0) gets(dmy);
		printf("%-20s  %.1f  %.1f\n",hw[i].name,hw[i].h,hw[i].w);
	}
	//------------------
		printf("\n名前順に並べ替えます。(Enter Keyを押して下さい)\n");
	for (i=0;i<n-1;i++) {
		for (j=i+1;j<n;j++) 
			if (strcmp(hw[i].name,hw[j].name)>0)
			{temp=hw[i]; hw[i]=hw[j]; hw[j]=temp;}
	}

/*  strcmp[=string comparison, 文字列比較]は文字列の比較関数で、c=strcmp(a,b); の様に
書くと、cに関数値が入る。二つの文字列 a, bを先頭から一字ずつ比較対照して、aの方がalphabet
順で前にあれば(a<b)負の値、後にあれば(a>b)正の値を返す。0の場合、両者は同じ文字列(a=b)で
ある。上では、この関数値が正の時(即ち、bが小さい時)に交換している。*/

	for (i=0;i<n;i++) {
		if (i%20==0) gets(dmy);
		printf("%-20s  %.1f  %.1f\n",hw[i].name,hw[i].h,hw[i].w);
	}
	//------------------

printf("\nEnd\n");
return 0;
}


(前に戻る)   ・次へ