質問: &best_ten[i]; } qsort( plst, count, sizeof(BEST_TEN*), cmpptr ); printf("\n過去のbestten\n-------------------------- \n"); // 並べ替え後の内容を表示 for(i=0;itm_year+1900, plst[i]->tm_mon+1, plst[i]->tm_mday, plst[i]->tm_hour,plst[i]->tm_min,plst[i]->tm_sec ); printf("得点(所要時間)は %.1f秒です。\n\n", plst[i]->best); } fflush(stdin); getchar(); fclose(lstfp); return 0; } /*実行結果 ....@naka ~/qsort/struct_sort $ gcc -o qsort4 qsort4.c -lpdcursesw ....@naka ~/qsort/struct_sort $ qsort4 過去の履歴のコピー -------------------------- 2015年 10月 27日 19時 9分 59秒 得点(所要時間)は 11.0秒です。 2016年 1月 4日 19時 15分 11秒 得点(所要時間)は 8.0秒です。 2016年 1月 4日 19時 16分 8秒 得点(所要時間)は 9.0秒です。 2016年 1月 4日 19時 16分 39秒 得点(所要時間)は 10.0秒です。 2016年 1月 4日 19時 19分 7秒 得点(所要時間)は 10.0秒です。 2016年 1月 4日 19時 21分 11秒 得点(所要時間)は 10.0秒です。 2016年 1月 4日 19時 21分 44秒 得点(所要時間)は 8.0秒です。 2016年 1月 4日 19時 22分 55秒 得点(所要時間)は 13.0秒です。 2016年 1月 5日 21時 31分 52秒 得点(所要時間)は 12.0秒です。 2016年 1月 5日 21時 33分 29秒 得点(所要時間)は 10.0秒です。 過去のbestten -------------------------- 2016年 1月 4日 19時 15分 11秒 0秒 得点(所要時間)は 8.0秒です。 2016年 1月 4日 19時 21分 44秒 0秒 得点(所要時間)は 8.0秒です。 2016年 1月 4日 19時 16分 8秒 0秒 得点(所要時間)は 9.0秒です。 2016年 1月 4日 19時 19分 7秒 0秒 得点(所要時間)は 10.0秒です。 2016年 1月 5日 21時 33分 29秒 0秒 得点(所要時間)は 10.0秒です。 2016年 1月 4日 19時 16分 39秒 0秒 得点(所要時間)は 10.0秒です。 2016年 1月 4日 19時 21分 11秒 0秒 得点(所要時間)は 10.0秒です。 2015年 10月 27日 19時 9分 59秒 0秒 得点(所要時間)は 11.0秒です。 2016年 1月 5日 21時 31分 52秒 0秒 得点(所要時間)は 12.0秒です。 2016年 1月 4日 19時 22分 55秒 0秒 得点(所要時間)は 13.0秒です。 */ ```
回答: こんにちは。 長くなるのでこちらから。 > > 関数を作ってすっきりしたいにですが、うまくいかないので教えてください > > NDATAを定義しているのですがbest_tenをmallocで確保して、countの代わりに使いたいのですが。 > > > 「関数を作ってすっきりしたい」のでしょうか? それとも、「best_tenをmallocで確保して」可変個のデータに対応されたいのでしょうか? もし、両方ともでしたら、両方を同時に進めるのはちょっと骨と思います。 後者→前者の順で行うことをお勧めします。 【追記:mallocで最大記録数を可変対応する方法】 一番問題になるのは、ファイルに記録されているデータの数をどうやって取得するか?です。 1既に実装されている仕組みを流用し、countで計算されているデータの数を使う 2ファイルのサイズを獲得して、データ1つのサイズで割ることでデータの数を計算する プログラムの修正量は2の方が少ないので2の方法で提案します。 **1.下記2つが必要な記憶領域ですが、これをmallocで獲得できるようにします。** ``` BEST_TEN best_ten[100]; ↓ BEST_TEN *best_ten; ``` ``` BEST_TEN *plst[NDATA]; ↓ BEST_TEN **plst; ``` **2.次にデータ数を求めます** C言語のファイル操作機能には、下記があります。 (1)ファイルからデータを読みだす位置を示すファイル位置表示子 (2)ファイル位置表示子を指定位置へ移動する(fseek) (3)ファイル位置表示子のファイル先頭からのバイト数を求める(fgetpos) これらを使い下記方法にてファイルに記録されているデータのバイト数を調べることができます。 a.ファイル位置表示子を最後尾へ移動する(SEEK_END) b.ファイル位置表示子のファイル先頭からのバイト数を求める c.ファイル位置表示子を最後尾へ移動する(SEEK_SET) データ1つのバイト数は、`sizeof(struct tm)+sizeof(double)`で計算できますので、b.で求めた値をこの値で割ればデータの数になります。 この処理は、`printf("\n過去の履歴のコピー\n-------------------------- \n");`文の直前が良いです。 **3.次にmallocでメモリを獲得します** 下記イメージです。 ``` #define SIZE (sizeof(struct tm)+sizeof(double)) //A best_ten = (BEST_TEN *)malloc(データ数*SIZE); //B plst= (BEST_TEN **)malloc(データ数*sizeof(BEST_TEN *));//C ``` A, B, Cは適切な位置へ置いて下さい。 AはNDATAを#defineしている付近が良いです。 Bは2.で`データ数`を求めた直後に置く必要があります。 Cは`BEST_TEN *plst[NDATA];`→`BEST_TEN **plst;`の直後に置く必要があります。 以上で基本的な処理は終わりです。 既に作られている部分は上記の提案部分以外は修正不要な筈です。 **4.後始末** malloc等で獲得したメモリは解放する必要が有ります。 そのために、main()の最後に下記を記述して下さい。 ``` free(best_ten ); free(plst); ``` **5.エラー処理** mallocでデータを獲得できなかった時は、NULLが返ってきます。この時、獲得したかったメモリを使おうとするとプログラムが落ちます。ですので、そのエラー処理を書いておくことが推奨されますが、趣味のプログラムでしたら不要です。できることは、プログラムを終了させることしかありませんので。