質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

1回答

1911閲覧

プログラムを関数を作ってすっきりしたい

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2016/02/01 01:27

//【 構造体のポインタ配列を qsort するプログラム例 】 // 実行時間の短い順にならべるプログラムを関数を作って // すっきりしたいにですが、うまくいかないので教えてください // NDATAを定義しているのですがbest_tenをmallocで確保して、 // countの代わりに使いたいのですが。 #include <float.h> #include <time.h> #include <stdio.h> #include <stdlib.h> #define NDATA ((sizeof best_ten)/(sizeof(BEST_TEN))) typedef struct { int tm_year; int tm_mon; int tm_mday; int tm_hour; int tm_min; int tm_sec; double best; } BEST_TEN; // --------------- 比較用の関数 cmp ------------------- int cmpptr( const void *p, const void *q ) { return (*(BEST_TEN**)p)->best - (*(BEST_TEN**)q)->best; } // ---------------------------------------------------- char dtfile[] = "LACKNUM.DAT"; int main(void) { FILE *lstfp; double best; int i,j=0; BEST_TEN best_ten[100]={0}; int count=0; if((lstfp =fopen(dtfile, "rb")) == NULL){ printf("ファイルを作成します。 \n\n"); best = DBL_MAX; }else{ struct tm lst; printf("\n過去の履歴のコピー\n-------------------------- \n"); while((i = fread(&lst,sizeof(struct tm), 1, lstfp)) > 0 ){ printf("%d年 %d月 %d日 %d時 %d分 %d秒\n", lst.tm_year + 1900, lst.tm_mon + 1, lst.tm_mday, lst.tm_hour, lst.tm_min, lst.tm_sec); fread(&best, sizeof(double), 1, lstfp); printf("得点(所要時間)は %.1f秒です。\n\n", best); // 画面が一瞬で消えてしまうのを防止 // 一瞬で画面が消えてしまう場合には、以下の文を入力します。 best_ten[j].tm_year=lst.tm_year; best_ten[j].tm_mon=lst.tm_mon; best_ten[j].tm_mday=lst.tm_mday; best_ten[j].tm_hour=lst.tm_hour; best_ten[j].tm_min=lst.tm_min; best_ten[j].tm_sec=lst.tm_sec; best_ten[j].best=best; /*printf( "%d年 %d月 %d日 %d時 %d分 %d秒 %.lf秒\n\n" , best_ten[j].tm_year + 1900, best_ten[j].tm_mon + 1, best_ten[j].tm_mday, best_ten[j].tm_hour, best_ten[j].tm_min, best_ten[j].tm_sec,best_ten[j].best);*/ j++; count++; } printf("countは %dです。\n\n", count); } printf("count2は %dです。\n\n", count); printf("NDATAは %dです。\n\n", NDATA); BEST_TEN *plst[NDATA]; for( i = 0; i < count; i++ ) { plst[i] = &best_ten[i]; } qsort( plst, count, sizeof(BEST_TEN*), cmpptr ); printf("\n過去のbestten\n-------------------------- \n"); // 並べ替え後の内容を表示 for(i=0;i<count;i++){ printf( "%d年 %d月 %d日 %d時 %d分 %d秒 %.lf秒\n" ,plst[i]->tm_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秒です。 */ ```

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

coco_bauer

2016/02/01 04:30

履歴のファイルからデータを読み出す前に、そのデータを保存する領域をmallocする実装は可能でしょうが、そうしてmallocした領域へのポインタの配列を保持する事が必要なので、best_10のようなデータ配列を使う場合と大差ないコードになると思いますから、「すっきり」とはいかないと思います。過去履歴の件数が100件を超えても正常に動作するというメリットはあります。
退会済みユーザー

退会済みユーザー

2016/02/01 22:51

すみません。漠然としたお願いで申し訳ありませんでした。 私は一連の質問を依頼してこちらが何をしているか分かってもらっている人でしたら、分かっていただいたと思います。要は配列でも、可変のポインタ配列でもおなじということですね。勉強のためにmalloc使って、NDATAをうまく使えるようにしたかったのです。 すこしmallocを復習してからやってみます。
guest

回答1

0

こんにちは。

長くなるのでこちらから。

関数を作ってすっきりしたいにですが、うまくいかないので教えてください
NDATAを定義しているのですがbest_tenをmallocで確保して、countの代わりに使いたいのですが。

「関数を作ってすっきりしたい」のでしょうか?
それとも、「best_tenをmallocで確保して」可変個のデータに対応されたいのでしょうか?
もし、両方ともでしたら、両方を同時に進めるのはちょっと骨と思います。
後者→前者の順で行うことをお勧めします。


【追記:mallocで最大記録数を可変対応する方法】
一番問題になるのは、ファイルに記録されているデータの数をどうやって取得するか?です。
①既に実装されている仕組みを流用し、countで計算されているデータの数を使う
②ファイルのサイズを獲得して、データ1つのサイズで割ることでデータの数を計算する

プログラムの修正量は②の方が少ないので②の方法で提案します。

1.下記2つが必要な記憶領域ですが、これをmallocで獲得できるようにします。

C

1BEST_TEN best_ten[100]; 23BEST_TEN *best_ten;

C

1BEST_TEN *plst[NDATA]; 23BEST_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でメモリを獲得します
下記イメージです。

C

1#define SIZE (sizeof(struct tm)+sizeof(double)) //A 2best_ten = (BEST_TEN *)malloc(データ数*SIZE); //B 3plst= (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()の最後に下記を記述して下さい。

C

1free(best_ten ); 2free(plst);

5.エラー処理
mallocでデータを獲得できなかった時は、NULLが返ってきます。この時、獲得したかったメモリを使おうとするとプログラムが落ちます。ですので、そのエラー処理を書いておくことが推奨されますが、趣味のプログラムでしたら不要です。できることは、プログラムを終了させることしかありませんので。

投稿2016/02/01 09:24

編集2016/02/02 00:38
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/02/01 22:41

おはようございます。 「best_tenをmallocで確保して」可変個のデータに対応したいです。 カウントで何とか対応したのですが、NDATAというのがありましたので、 それをうまく使えるようにしたいです。 最初の定義で設定できていないので、countを使いましたが、ここにNDATAを つかいたいのですが。mallocをどこでつかい、 どうすればいいか教えてください。mallocは使ったことがあります。
Chironian

2016/02/01 23:48

なるほど。 現在の姿は、NDATAが処理できる最大のデータ数で、countが実際にLACKNUM.DATに記録されているデータの数になっています。 そして、NDATAを超える数を読みこませようとすると落ちますね。 この問題に対処する方法に、処理したいデータの数の記録領域をmallocで獲得する方法があります。 その方法を回答へ追記します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問