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

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

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

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

Q&A

1回答

1387閲覧

過去のbestten を表示したいが表示はされるが完全な順序になっていない。

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

0グッド

1クリップ

投稿2017/09/08 00:57

編集2017/09/12 12:16

実行結果が時間の短い順になっていない。大体は時間順になっています。
どこを直せばいいでしょうか。c言語でかいています。
構造体の定義や、名前のわかりにくさがありますが、とりあえずこれで正常に
うごくようにしてから、コードの修正をかんがえています。
もう何回も挑戦してここまでプログラムをつくりました。
前回作って正常に動くと思っていたのですが、ちゃんと動いていないことがわかり
苦戦しています(1か月くらい)。よろしくお願いします。

c言語 /* ラックナンバーサーチ・トレーニング(過去の履歴と最短時間の表示)*/ #include <stdio.h> #include <time.h> #include <float.h> #include <ctype.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include "getputch.h" #define MAX_STAGE 3 #define swap(type, x, y) do { type t = x; x = y; y = t; } while (0) #define MAX_NUM 10 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; } BEST_TEN; // --------------- 比較用の関数 cmp ------------------- int cmpptr( const void *p, const void *q ) { return (*(BEST_TEN**)p)->score - (*(BEST_TEN**)q)->score; } // ---------------------------------------------------- /*--- 過去のトレーニング情報を取得・表示して最高得点を返す ---*/ double get_data(int *count) { FILE *fp; // これまでの履歴を指すポインタ FILE *fp2; // これまでの最短所要時間を指すポインタ double score; //これまでの履歴の所要時間 double bestscore; //これまでの最短所要時間 int i,j=0; BEST_TEN best_ten[100]={0}; if ((fp = fopen(dtfile, "rb")) == NULL) { printf("ファイルを作成します。\n\n"); bestscore = DBL_MAX; /* float.hに定義されている。double型で表現できる最大値を表すマクロDBL_MAX */ } else { struct tm local; double line[256]; printf("\n過去の履歴\n-------------------------- \n"); while((i = fread(&local, sizeof(struct tm), 1, fp)) > 0 ){ printf("%d年 %d月 %d日 %d時 %d分 %d秒\n", local.tm_year + 1900, local.tm_mon + 1, local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec); fread(&score, sizeof(double), 1, fp); printf("得点(所要時間)は%.1f秒\n\n", score); best_ten[j].tm_year=local.tm_year; best_ten[j].tm_mon=local.tm_mon; best_ten[j].tm_mday=local.tm_mday; best_ten[j].tm_hour=local.tm_hour; best_ten[j].tm_min=local.tm_min; best_ten[j].tm_sec=local.tm_sec; best_ten[j].score=score; j++; (*count)++; } printf("count1は%d\n\n", *count); } BEST_TEN *plst[*count]; for( i = 0; i < *count; i++ ) plst[i] = &best_ten[i]; //qsort(配列名, 配列の数, 配列一つのバイト数, 比較関数) qsort( plst, *count, sizeof(BEST_TEN*), cmpptr ); printf("\n過去のbestten\n-------------------------- \n"); // 並べ替え後の内容を表示 for(i=0;i<10;i++){ printf( "%d年 %d月 %d日 %d時 %d分 %d秒 \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]->score); } bestscore=plst[0]->score; fflush(stdout); fclose(fp); printf("count2は%d\n\n", *count); return bestscore; } int main(void) { int count=0; // double score; // 今回の所要時間 double bestscore; // 最短所要時間 double jikan; // 時間 FILE *fp; struct tm local ; int k; int i, j, x, stage; bestscore= get_data(&count); // get_data()で前回までの最短所要時間を // ファイルから読み込んでbestscoreに代入する。 printf("bestscoreは%.1f\n\n", bestscore); printf("count3は%d\n\n", count); return 0; }

/*

C:\MinGW\users\chap09\kadai>gcc -I. -o kadai9-1-6 kadai9-1-6.c pdcurs
es.a

C:\MinGW\users\chap09\kadai>kadai9-1-5

過去の履歴

2015年 10月 27日 19時 9分 59秒
得点(所要時間)は11.0秒

2016年 1月 4日 19時 15分 11秒
得点(所要時間)は8.0秒

2016年 1月 4日 19時 16分 8秒
得点(所要時間)は9.0秒

省略

count1は66

過去のbestten

2017年 8月 14日 20時 57分 40秒
得点(所要時間)は 6.0秒です。

2017年 9月 9日 12時 14分 36秒
得点(所要時間)は 6.2秒です。

2016年 5月 2日 17時 0分 48秒
得点(所要時間)は 7.0秒です。

2017年 9月 9日 12時 3分 5秒
得点(所要時間)は 6.1秒です。//ここがおかしい

2016年 1月 4日 19時 15分 11秒
得点(所要時間)は 8.0秒です。

2016年 1月 4日 19時 21分 44秒
得点(所要時間)は 8.0秒です。

2017年 9月 9日 12時 4分 2秒
得点(所要時間)は 7.5秒です。//ここがおかしい

2017年 9月 9日 12時 38分 12秒
得点(所要時間)は 8.0秒です。

2016年 1月 31日 21時 12分 13秒
得点(所要時間)は 8.0秒です。

2017年 9月 9日 11時 28分 59秒
得点(所要時間)は 8.0秒です。

count2は66

bestscoreは6.0

count3は66

C:\MinGW\users\chap09\kadai>
*/

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

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

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

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

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

LouiS0616

2017/09/08 07:31

実際にどのように変な文字が出力されるのか、スクショを貼ると回答が付きやすいかと思います。
PineMatsu

2017/09/08 08:03

fpos_tは処理系によって構造体だったり整数として扱えたりします。処理系やOSなども明記して下さい。
退会済みユーザー

退会済みユーザー

2017/09/08 12:20

説明文のように端末実行画面の”欠けている数字を入力してください。 スペースキーで開始します。(点滅中で待機)”のしたのほうに、句読点。、改行の後にチ(いまは貼り付け出来ない1文字)、改行で同じ文字、その下に1が表示されています。実行結果にはあまり影響はないのですが。句読点は関数new_local_dataの修正で消えました。ラックナンバリサーチをラックナンバリサに変更すると消えます。その下の1は消し方がわかりません。MinGWでgccを実行しています。windows10です。よろしくおねがいいたします。
showkit

2017/09/11 05:32

質問とソースコードは分けて記述してほしいですね。ヘルプで記述方法を確認してください。それと文字コードには何を使用しているか自覚していますか?
退会済みユーザー

退会済みユーザー

2017/09/11 07:11

ご指摘ありがとうございます。コードの上は私が使っている言語を書くのでしょうか?質問文はどこに書くのでしょうか?ヘルプを探したのですがよくわかりませんでした。ご迷惑かけてすみません。
PineMatsu

2017/09/11 08:20

コードは```~```の間に書きます。質問はその外側に書けばOKです。
退会済みユーザー

退会済みユーザー

2017/09/12 11:52

へんじありがとございます。説明文とコードを書く場所、使っている言語を書くところなど2年使っていてやっとわかりました。
guest

回答1

0

すみません、これは直接的な回答ではないのですが...
修正依頼欄では伝えきれないので、こちらに書かせていただきます。

他人が書いたコードを読むのには、かなりの労力が要ります。
なるべく読みやすいコードを心掛けてください。後から読み返すときにも有用です。


例えば、これ。何回も使ってますよね。

C

1typedef struct { 2 int tm_year; 3 int tm_mon; 4 int tm_mday; 5 int tm_hour; 6 int tm_min; 7 int tm_sec; 8 double score; 9} BEST_TEN;

次のように書き換えたり、専用の関数を充実させると、かなり読みやすくなります。

C

1typedef struct tm TIME_DATA; 2 3typedef struct { 4 TIME_DATA time; 5 double score; 6} SCORE_DATA; 7 8size_t fread_score_data(SCORE_DATA *score_data, FILE *fp) { 9 return fread(&score_data->time, sizeof(TIME_DATA), 1, fp) 10 && fread(&score_data->score, sizeof(double), 1, fp); 11} 12void print_score_data(SCORE_DATA *score_data) { 13 printf( "%d年 %d月 %d日 %d時 %d分 %d秒 \n", 14 score_data->time.tm_year + 1900, 15 score_data->time.tm_month + 1, 16 score_data->time.tm_day, 17 score_data->time.tm_hour, 18 score_data->time.tm_min, 19 score_data->time.tm_sec 20 ); 21 printf("得点(所要時間)は %.1f秒です。\n\n", 22 score_data->score 23 ); 24} 25double get_score(SCORE_DATA *score_data) { 26 return score_data->score; 27}

書き換えた理由

  • BEST_TENって名前は不適。これを10個集めて初めてベスト10になるはず。
  • せっかくtime.hをインクルードしているんだから、使えるものは使う。

私は詳しく知りませんが、使えそうな関数もあるかもしれません。

  • とにかく抽象化。同じコードを二回書いたら関数化を検討しましょう。

C

1while((i = fread(&local, sizeof(struct tm), 1, fp)) > 0 ){ 2 ... 3 j++; 4}

こんな感じにも書けます。

C

1for(j = 0; fread(&local, sizeof(struct tm), 1, fp) > 0; j++) { 2 ... 3}

書き換えた理由

  • jが毎ループ増えていくイメージが掴みやすいです。

あとは、変数の名前がわかりづらいです。

C

1BEST_TEN *plst[*count];

...plst? なんの略称でしょうか。


他にもいろいろありそうですが、読みやすいコードを書くことを意識してください。
質問の際もすんなり伝わるようになりますし、バグも減ります。

あとは... 再現できるような情報をください。
xxxxx.datファイルを用いていることはわかりますが、その内部の構造がわかりません。
そのまま使えるものを提示してもらえるのが一番早いです。

投稿2017/09/11 14:41

LouiS0616

総合スコア35660

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

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

退会済みユーザー

退会済みユーザー

2017/09/12 05:57

色々教えていただきありがとうございます。コードをご指南のとおり修正して試してみます。 そのあとまたおねがいいたします。
退会済みユーザー

退会済みユーザー

2017/09/12 10:19

LouiS0616さん指摘を受けていろいろやってみたのですが、このコードで過去の履歴は正常に表示されます。このままで実行時間の短い順に10個表示したいのですが、どこか順番にならないところがあります。 これが正常に表示されてから、コードの修正をしたいと思っています。よろしくお願いします。
LouiS0616

2017/09/12 14:38

ここから、https://teratail.com/questions/92144に移っていくわけですね。 なんというか、難しく考えすぎな気がします。 私の書いたサンプルは、まあデバッグしてないので不具合があるかもわかりませんが、役割を絞ることを意識して作っています。 一度汎用的な関数を定義してしまえば、あたかも最初から存在する機能かのように使ってしまえばいいんです。
LouiS0616

2017/09/12 14:41

問題を段階に分けて考えてください。 ・まず、ファイルからスコアとその時刻データ(SCORE_DATA)を読み取る関数を作ってください。そして、問題がなくなるまでテストしてください。 ・次に、読み取った複数のSCORE_DATAを、目的に沿うような順にソートする関数を作ってください。そして、問題がなくなるまでテストしてください。 ・最後に、その中からベストテンを選び出し、情報を出力する機能を作ってください。そして、問題がなくなるまでテストしてください。 以上、完成です。
LouiS0616

2017/09/12 14:42

コードを全部書ききってからテストするのはやめましょう。 問題の所在が不明瞭になって、デバッグが困難になります。 まずはここまで、次はここまで、少しずつ機能を拡張してください。
退会済みユーザー

退会済みユーザー

2017/09/12 23:32

ありがとうございます。おっしゃる通りにやってみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問