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

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

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

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

Q&A

解決済

2回答

262閲覧

配列を使っているところをmalloc使って動的にメモリを確保したい

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

0グッド

0クリップ

投稿2017/10/03 05:46

下のコードでどこを、どのようにしたらいいか見当がつきません。 動けばいいんじゃないのという人もいると思いますが、今mallocの使い方を勉強しています。直しようがないというのであれば、教えていただきたいのです。 コードの書き方で直したほうがいいところがあれば、それも教えてください。 よろしくおねがいいたします。 コード // ラックナンバーサーチ・トレーニング 正常動作 #include <stdio.h> #include <time.h> #include <float.h> #include <stdlib.h> #define MAXCNT 100 char dtfile[]="LACKNUM.DAT"; char dtfile2[]="LACKNUM2.DAT";// 最高記録用のファイル typedef struct{ int tm_year; int tm_mon; int tm_mday; int tm_hour; int tm_min; int tm_sec; double score; }TIME_DATA; //--- 前回までのトレーニング情報の最高得点を返す --- void get_data2(int *count) { FILE *fp; FILE *fp2; int i; int year, mon, mday, hour, min, sec; double score; double bestscore; // 最高得点 TIME_DATA stars[MAXCNT]; // 構造体配列の宣言 if ((fp=fopen(dtfile,"rb"))==NULL){ printf("本プログラムを実行するのは初めてですね。\n\n"); bestscore = DBL_MAX; /* float.hに定義されている。double型で表現できる最大値を表すマクロDBL_MAX */ exit(1); } else { for(i=0; i<MAXCNT; i++){ if(fscanf(fp, "%d %d %d %d %d %d %lf\n" , // 構造体配列への読み込み &stars[i].tm_year,&stars[i].tm_mon,&stars[i].tm_mday, &stars[i].tm_hour,&stars[i].tm_min,&stars[i].tm_sec,&stars[i].score)!=7) break; (*count)++; } printf("\ncount01:%d\n\n",*count); printf("前回の終了は%d年 %d月 %d日 %d時 %d分 %d秒 で\n\n", // 構造体配列への読み出し stars[*count-1].tm_year,stars[*count-1].tm_mon,stars[*count-1].tm_mday,stars[*count-1].tm_hour, stars[*count-1].tm_min,stars[*count-1].tm_sec,stars[*count-1].score); fflush(stdout); fclose(fp); } if ((fp2=fopen(dtfile2,"rb"))==NULL) { printf("本プログラムを実行するのは初めてですね。\n\n"); bestscore=DBL_MAX; /* float.hに定義されている。double型で表現できる最大値を表すマクロDBL_MAX */ exit(1); } else { fscanf(fp2, "%d%d%d%d%d%d", &year, &mon, &mday, &hour, &min, &sec); fscanf(fp2, "%lf", &bestscore); // stream(fp)が指すストリームから&bestに読み込む //fscanf 関数は format が指す書式文字列に従って //stream(fp) が指すストリームからデータを読込み, //format(&year, &month, &day, &h, &m, &s) に続く引数の指すオブジェクトに代入します. printf("前回までの最高得点(最短所要時間)は%d年%d月%d日%d時%d分%d秒で\n", year, mon, mday, hour, min, sec); fflush(stdout); printf("これまでの最高得点(最短所要時間)は%.1f秒です。\n\n", bestscore); // 画面が一瞬で消えてしまうのを防止 // 一瞬で画面が消えてしまう場合には、//getchar(); // 以下の文を入力します。 fflush(stdout); fclose(fp2); } } //■過去の履歴は. double kako_rireki(int* count,double* p,double* q) { FILE *fp; int i; TIME_DATA stars[MAXCNT]; // 構造体配列の宣言 if((fp=fopen(dtfile, "rb"))==NULL){ printf( "ファイルがオープンできません\n" ); exit( 1 ); } for(i=0; i<MAXCNT; i++){ if(fscanf(fp, "%d %d %d %d %d %d %lf\n" // 構造体配列への読み込み , &stars[i].tm_year,& stars[i].tm_mon, &stars[i].tm_mday, &stars[i].tm_hour, &stars[i].tm_min,&stars[i].tm_sec,&stars[i].score)!=7) break; } printf("\ncount0:%d\n\n",*count); printf("\n■過去の履歴は................\n\n"); for(i=0; i<*count; i++){ printf( "%d年 %d月 %d日 %d時 %d分 %d秒 \n所要時間(score)は%.1f\n\n", // 構造体配列への読み出し stars[i].tm_year,stars[i].tm_mon,stars[i].tm_mday,stars[i].tm_hour, stars[i].tm_min,stars[i].tm_sec,stars[i].score); } fflush(stdout); fclose(fp); printf("count1は%d\n\n", *count); return *count; } int main(void) { int count=0; int retry; double score; // 今回の所要時間 double bestscore; double* p; double* q; get_data2(&count); kako_rireki(&count,p,q); printf("count3:%d\n", count); return (0); } /* 実行結果 C:\MinGW\users\chap09\kadai>gcc -I. -o kadai9-1c kadai9-1c.c pdcurses.a C:\MinGW\users\chap09\kadai> kadai9-1c count01:29 前回の終了は2017年 10月 2日 17時 59分 31秒 で 前回までの最高得点(最短所要時間)は2017年9月14日10時21分18秒で これまでの最高得点(最短所要時間)は6.0秒です。 count0:29 ■過去の履歴は................ 2015年 12月 7日 19時 9分 59秒 所要時間(score)は8.0 2016年 1月 4日 1時 9分 11秒 所要時間(score)は7.5 以下省略 C:\MinGW\users\chap09\kadai> */

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

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

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

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

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

t_obara

2017/10/03 06:10

構造体配列と記載の部分を必要に応じて動的に拡張したいという意図でしょうか? その通りであれば、「リスト構造」というキーワードを調べてみるとよろしいかと思います。
退会済みユーザー

退会済みユーザー

2017/10/03 06:18

ありがとうございます。TIME_DATA stars[MAXCNT]のところで、MAXCNTを100に設定しています。これをmallocを使って、コードを書き直せますか。 &stars[i].tm_hour, &stars[i].tm_min,&stars[i].tm_sec,&stars[i].score)!=7) break;を使えば使う必要はないですか。ここではmllocは使う意味がないですか?
guest

回答2

0

依頼があったので回答を書いていたのですが、LouiS0616さんが既に回答されてますので、ちょこっと違うコメントをしてみます。

mallocを使って、コードを書き直せますか

とのことですが、このプログラムは配列を用いているので、

(A1) TIME_DATAとして実際に必要なデータ数が1個であっても無条件に100個メモリーが確保される
(A2) 101個以上必要だったとしてもこのコードのままではMAX_CNTを書き直してコンパイルしなおさない限り対応不能

上記に対して

(L1) 実際に必要な分だけメモリーを確保(1個なら1個分だけ、10個なら10個だけ)
(L2) プログラムの変更なしにかなり大きな個数まで(計算機のメモリーがある限り)柔軟に対応できる

ようにするためには配列ではなくリスト構造を用いるのが常とう手段です。リスト構造を用いると、必要になった時点で要素一つ分の領域を動的に確保することができ、その際にmallocを使うことになります。

より詳細には'C言語 データ構造 リスト'といったキーワードを指定してまずは検索するなり参考書を参照するなりすべきと思いました。つまり自分が申し上げたいことはt_obaraさんと同じです。

検索すると解説がいろいろとみつかります。例えばこんなページとか。こういった解説ページをご覧になれば、teratailの回答欄では書ききれないような丁寧な説明を読むことができます。

質問が「動的確保したい」といった漠然としたものであるうちはまずは手法について自分なりに知識を吸収し、その上で実際にコードを書くといった進め方がいいのではないでしょうか。手法を把握した上で書いたコードについての具体的質問をするというのがQ&Aサイトの典型的な活用法と思います。

投稿2017/10/03 08:10

KSwordOfHaste

総合スコア18392

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

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

退会済みユーザー

退会済みユーザー

2017/10/03 08:17

ご回答ありがとうございます。t_obaraさんのおっしゃる通り構造体のリストに関するネットを収集していました。これからリストを勉強して戻ってきます。
guest

0

ベストアンサー

回答依頼ありがとうございます。

コードの書き方で直したほうがいいところがあれば、それも教えてください。

C

1typedef struct{ 2 int tm_year; int tm_mon; int tm_mday; 3 int tm_hour; int tm_min; int tm_sec; 4 double score; 5} TIME_DATUM; 6 7int print_time_datum(const TIME_DATA *datum) { 8 return print_time_datum_w_format("%d年 %d月 %d日 %d時 %d分 %d秒: %f", datum); 9} 10int print_time_datum_w_format(const char *format, const TIME_DATUM *datum) { 11 return printf(format, 12 datum->tm_year, datum->tm_mon, datum->tm_mday, 13 datum->tm_hour, datum->tm_min, datum->tm_sec, datum->score 14 ); 15} 16 17int fscan_time_datum(FILE *fp, TIME_DATUM *datum) { 18 return fscanf(fp, "%d %d %d %d %d %d %lf\n", 19 &datum->tm_year, &datum->tm_mon, &datum->tm_mday, 20 &datum->tm_hour, &datum->tm_min, &datum->tm_sec, &datum->score 21 ); 22}

前々から言っているように、機能を抽象化することをお勧めします。
これはオブジェクト指向言語を学び始める際にも役立つことでしょう。

また、細かい話で恐縮なのですが...
『data』は複数形です。構造体のタグ名には単数形の『datum』を使いましょう。

追記
いまちょっと調べてみたら、dataを単数形として使うネイティブもいるようです。
ですので、必ずdatumを使わねばならないというわけではありませんが...

C

1SCORE_DATUM data[HOGE]; 2for(int i = 0; i < HOGE; i++) { 3 SCORE_DATUM datum = data[i]; 4}

こんな風に書けるので、けっこう便利です。この例だとコピーコストが生じますが。


malloc使って動的にメモリを確保したい

一応使い方としては、こんな感じです。
しばらく使ってないのでデバッグなしだとちょっと自信がないです。

C

1TIME_DATA *stars; 2stars = (TIME_DATA *)malloc(sizeof(TIME_DATA) * MAXCNT)); 3if(stars == NULL) { 4 exit(1); 5} 6 7... 8 9free(stars);

上記では面倒なのでMAXCNT個だけ要素を持てる領域を確保しています。
が。これなら静的配列で充分です。

動的確保の享受を得たいのなら、ランキング入りしている分だけ確保すればよいでしょう。
例えば、DATファイルのヘッダにランカー数を書くとか。


DATファイルをこちらで用意するのは面倒なので、動作確認はしていません。
適宜エラー等を潰しながら試してみてください。

投稿2017/10/03 07:33

編集2017/10/03 08:51
LouiS0616

総合スコア35658

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

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

退会済みユーザー

退会済みユーザー

2017/10/03 08:22

LouiS0616さんいつもありがとうございます。リストを勉強してから、またでなおしします。細かい指摘で助かります。来週中までかかりそうです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問