/* 構造体 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; }