• 締切済み

C言語 ファイル処理に関する事

テキストエディタで打ち込んだファイル 【hw.dat】 Akiba 160 59.3 Kurata 162 51.6 Masaki 182 76.5 Tanaka 170 60.7 Tsuji 175 83.9 Washio 175 72.5 名前・身長・体重のデータです。 <問>   「hw.dat」から読み込んだデータを身長順にソートした上で   表示するプログラムを作成せよ。 下記のプログラムでは実行結果が何も出てきません。 入門レベルのスキルしかありません。何処が良くないのでしょうか。 教えて下さい。 [プログラム]   #include <stdio.h>   #include <string.h>   void swap_double(double *x, double *y)   {   int temp = *x;   *x = *y;   *y = temp;   }   void swap_name(char *sx, char *sy)   {   char *temp;    strcpy(temp, sx);   strcpy(sx, sy);   strcpy(sy, temp);   }   void sort(double *he, double *we, int n)   {   int i, j;    for(i = 0; i < n - 1; i++){   if(*(he - 1) > *he ){ swap_double((he - 1), he); swap_double((we - 1), we); } } }   void sort_name(double *he, char *na, int n)   {    int i, j;    for(i = 0; i < n - 1; i++){   if(*(he - 1) > *he ){ swap_name((na - 1), na); } } }  int main(void)   {    FILE *fp;    int ninzu = 0;    char *name[100];    double height, weight;    double hsum = 0.0;    double wsum = 0.0;    int i;    char *na[i];    double he[6];    double we[6];    if ((fp = fopen("hw.dat", "r")) == NULL)    printf("\aファイルをオープンできません。\n");    else{   for(i = 0; i < 6; i++){   while (fscanf(fp, "%s%lf%lf", name , &height , &weight) != EOF ){ *na = *name; he[i] = height; we[i] = weight; ninzu++; hsum += he[i]; wsum += we[i];   printf("%-10s %5.1f %5.1f\n", na, height, weight);   }   }   printf("------------------------\n");   printf("平均 %5.1f %5.1f\n", hsum / ninzu, wsum / ninzu);   }   puts("\n身長順にソートしました。");   for(i = 0; i < 6; i++){ *na = *name; he[i] = height; we[i] = weight; ninzu++; hsum += he[i]; wsum += we[i]; }   for(i = 0; i < 6; i++){   sort(he, we, 6);   sort_name(he, *na, 6);   printf("%-10s %5.1f %5.1f\n", *(na + i) , *(he + i), *(we + i));   }   printf("------------------------\n");   printf("平均 %5.1f %5.1f\n", hsum / ninzu, wsum / ninzu);  fclose(fp);   return 0;  }   

みんなの回答

回答No.4

以下の部分、   void swap_name(char *sx, char *sy)   {   char *temp;    strcpy(temp, sx); で、tempは「どこのメモリも差してない」です。というか「不特定の場所を差している」状態です。 tempが不特定なポインタなのに、strcpyでコピー先に指定しているので、実行すると、パソコン内の不定なメモリにsxの文字列をコピーします。 実行すると、パソコンがクラッシュしますので、非常に危険です。いきなりOS(Windows)が吹っ飛んで起動しなくなる可能性もあります。 こういうミスは「ちゃんと動く、ちゃんと動かない、以前の問題」なので、気を付けて下さい。 以下のように「実体を確保」して、実体がある場所にコピーして下さい。 void swap_name(char *sx, char *sy) { char temp[256]; //256バイトの実体を定義 strcpy(temp, sx); //sxが指す位置の文字列をtemp配列にコピー strcpy(sx, sy); //syをsxにコピー strcpy(sy, temp); //temp(元のsx)をsyにコピー } それと、以下の char *name[100]; は変です。これは「charへのポインタ(アドレス)が100個ある配列」であって、ここに文字列は格納できません。 char name[100]; であれは「99文字分+EOS1文字分」の領域が確保され、文字列を格納できます。 同様に char *na[i]; も変です。これは「charへのポインタ(アドレス)がi個ある配列」であって、ここに文字列は格納できません。しかも、この時点で「iは不定」なので、何が何個確保されるか判りません。 char na[6][100]; と定義すれば「99文字分+EOS1文字分の領域が、6人分」確保されます。 質問者さんのプログラムは、不定なポインタにガンガンと文字列をコピーしまくる、つまり、不定なメモリにガンガンとデータを書き込む「システム破壊プログラム」なので、メモリプロテクトがきちんと行われている動作環境(インテル32ビットCPUならある程度安全)で実行して下さい。 それと for(i = 0; i < 6; i++){ while (fscanf(fp, "%s%lf%lf", name , &height , &weight) != EOF ){ という2重ループでは、1番目に格納し続けて2番目以降には何も格納してません。 しかも *na = *name; は、「nameが指してるアドレスにある1文字を、naが指してるアドレスに書き込む」だけなので、文字列を保存出来てないし、そもそもnaの指す場所に文字列を格納するメモリはありません。 これらから察するに「文字列の扱い方をまったく理解できておらず、意味も解らず適当に代入文を書いてみただけ」のようです。 「charへのポインタ」と「文字列の扱い」は、C言語の「最大の難関」なので苦労するでしょうけど、これが理解できない限り「何も作れない」ので、頑張って下さい。

回答No.3

ゴメン。 ウッカリ「体重データ」を整数として処理しちまった。 正しいコードはコッチだ。 実装例: https://www.ideone.com/mTN8TA

回答No.2

実装例: https://www.ideone.com/teR1qL qsort(C標準ライブラリ内のクイックソート関数): https://chaste.web.fc2.com/Reference.files/C_Standard.files/qsort.html stdlibは「C標準ライブラリ」の意で、 #include する事で使用可能となる。 これを使う事。 アルゴリズムの授業でもなければ、「ソーティング関数を自作しよう」とはしない事。それは全くの無駄だ。 ライブラリ内で「使える関数」を探して、使いこなす事の方が100万倍マシだ。

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.1

全部のコードを見てませんが、最も気になるのは >int i; >    char *na[i]; ここです。変数iの値が決まっていないのに、それを配列の要素数として 使うことはできませんよ。 あと、名前・身長・体重をなんでバラバラに管理しようとするのでしょうか。 1人分のデータを扱うための構造体(メンバーは名前、身長、体重)を定義して、 人数分の配列を定義する方がよほど楽だと思います。 また、名前でソートする必要は本当にあるんですか? 仕様には、 >身長順にソートした上で と書いてあり、名前でソートせよとはどこにも書いてません。

t-tanaka102
質問者

補足

構造体にしたプログラムにしましたが、身長順にソートした結果を出す事が出来ません。 ソート前の名前・身長・体重は出る様になりました。 構造体はつい最近学んだところです。入門レベルという事でポインタについてもよく分かってないところがあると思います。 名前をソートしたのは、構造体ではなくバラバラで 管理していたので身長によって名前・体重もソートしないといけなかった為です。 プログラムをいじっているうちに不備があちらこちらに出る事があります。 下記、構造体にしたプログラムを送付します。 [構造体にしたプログラム]   #include <stdio.h>   typedef struct{   char *name[100];   double height, weight;   } kojin;   void swap_double(kojin *x, kojin *y)  {  kojin temp = *x;   *x = *y;   *y = temp;  }  void sort(kojin a[], int n)  {   int i, j;    for(i = 0; i < n - 1; i++){   for (j = n - 1; j > i; j--){   if(a[j - 1].height > a[j].height )    swap_double(&a[j - 1], &a[j]); } } }   int main(void)  {   FILE *fp;  int ninzu = 0;   double hsum = 0.0;  double wsum = 0.0;  int i;  kojin pa;   kojin *pb;   if ((fp = fopen("hw.dat", "r")) == NULL)   printf("\aファイルをオープンできません。\n");   else{   for(i = 0; i < 6; i++){   while (fscanf(fp, "%s%lf%lf", pa.name , &pa.height ,   &pa.weight) != EOF ){ ninzu++; hsum += pa.height; wsum += pa.weight; printf("%-10s %5.1f %5.1f\n", pa .name, pa .height,   pa .weight); } } printf("------------------------\n"); printf("平均 %5.1f %5.1f\n", hsum / ninzu, wsum / ninzu); } puts("\n身長順にソートしました。"); for(i = 0; i < 6; i++){ ninzu++; hsum += pa.height; wsum += pa.weight; sort(pb, 6); printf("%-10s %5.1f %5.1f\n", (pb + i) -> name , (pb + i) -> height, (pb + i) -> weight); } printf("------------------------\n"); printf("平均 %5.1f %5.1f\n", hsum / ninzu, wsum / ninzu); fclose(fp); return 0; }

関連するQ&A