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

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

ただいまの
回答率

90.47%

  • C

    4661questions

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

ダブルナンバーリサーチでベストテンが順番に表示されない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 531

sanchu52

score 164

/* ダブルナンバーサーチ・トレーニング(最近の10回の日時とベストテンの表示)
   curses.hを使うにはhttp://bd.tank.jp/d/20071208.htmlにゃかもとの日記参を参照する
  ダブルナンバーリサーチの表示がbestten3は表示はされるのですが
   順番になっていない。どこが悪いのかいろいろやったのですが
   どうしてもうまくいきません。とにかく正しい表示になるようにしたいです。
*/


#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[] = "LACKNUM3.DAT";
char dtfile2[] = "LACKNUM4.DAT";/* 最高記録用のファイル */

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;
}
// ----------------------------------------------------

//1回実行したとき進むポイントの大きさを求める

int kaime_p(fpos_t* kaime_p1)
{
    FILE *fp;
    struct tm local;
    double best;

    fp = fopen(dtfile, "rb");
    fread(&local, sizeof(struct tm), 1, fp);

    fread(&best, sizeof(double), 1, fp);

    //ファイルポインタの位置を取得
    fgetpos(fp,kaime_p1);   //ファイルfpの現在のファイル位置を取得して
                            // kaime_p1の示す場所に格納します。
    printf("ファイルポインタの位置kaime_p1は「%d」です。\n",*kaime_p1);

    fclose(fp);

    return *kaime_p1;
}

//local のデータを新しい順にならべる。
void new_local_data(fpos_t ft,int k)
{
    FILE *fp;        // これまでの履歴を指すポインタ 
    FILE *fp2;        // これまでの最短所要時間を指すポインタ 
    double best;    //これまでの履歴の所要時間
    double best2;   //これまでの最短所要時間のベストテンも保存しておく
    int i;   
              //構造体変数 localの大きさ
    struct tm local;

    if ((fp = fopen(dtfile, "rb")) == NULL) {
        printf("ファイルを作成します。\n\n");
        best = DBL_MAX;  /* float.hに定義されている。double型で表現できる最大値を表すマクロDBL_MAX */
    } else {
        printf("最近の10回の点数とそれらの実行日時は\n\n");
        for(i=ft-k; i>=ft-10*k; i -= k){ //構造体変数 localの大きさkaime_p1で44
            //ファイルポインタを先頭からiまで移動
            fseek(fp,i,SEEK_SET);

            fread(&local, sizeof(struct tm), 1, fp);
            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(&best, sizeof(double), 1, fp);
            printf("得点(所要時間)は%.1f秒\n\n", best);  
        } 
        printf("enterキーで開始します。\n");
        fflush(stdin);
        getchar();     
    }
    fclose(fp); 

}
/*--- 過去のトレーニング情報を取得・表示して最高得点を返す ---*/
double get_data(int *count)
{
    FILE *fp;        /* これまでの履歴を指すポインタ */
    FILE *fp2;        /* これまでの最短所要時間を指すポインタ */
    double best;            //これまでの履歴の所要時間
    double best2;           //これまでの最短所要時間
    int i,j=0;
    BEST_TEN best_ten[100]={0};

    if ((fp = fopen(dtfile, "rb")) == NULL) {
        printf("ファイルを作成します。\n\n");
        best = 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(&best, sizeof(double), 1, fp);
             printf("得点(所要時間)は%.1f秒\n\n", best);

            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].best=best;
             j++;
             (*count)++;
        }
       printf("count1は%d\n\n", *count);  
    } 
    BEST_TEN *plst[*count];
    for( i = 0; i < *count; i++ ) plst[i] = &best_ten[i];

    qsort( plst, *count, sizeof(BEST_TEN*), cmpptr );


        printf("\n過去のbestten3\n-------------------------- \n");    
    // 並べ替え後の内容を表示
    for(i=0;i<10;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);
    }
    best=plst[0]->best;

    fflush(stdin);
    fclose(fp);      
    printf("count2は%d\n\n", *count);  
    return best;
}
/*--- 今回のトレーニング情報を書き込む ---*/
void  put_data(double best, double best2)
{
    FILE *fp;    //fpはfopenされたdtfileを指すポインタ
    FILE *fp2;  //fp2はfopenされたdtfile2を指すポインタ、最短時間が格納されている
    time_t    t = time(NULL);
    struct tm *local = localtime(&t);

    time(&t);
    local = localtime(&t);
    if ((fp = fopen(dtfile, "ab")) == NULL){
         printf("ファイルがあーりません");
         fflush(stdout);
    }else {
        fwrite(local, sizeof(struct tm), 1, fp); //fpに書き込む
        fwrite(&best, sizeof(double), 1, fp);    //fpに書き込む
        fclose(fp);
    }
    if(best <= best2){
        if((fp2 = fopen(dtfile2, "wb")) ==NULL){
             printf("ファイルがあーりません");
             fflush(stdout);
        }else{
        //point配列にbestをいれ、best2をベスト2にいれる。dtfile[0]にbest1,dtfile[1]にbest2.....dtfile[9]にbest10
             fwrite(local, sizeof(struct tm), 1, fp2);
             fwrite(&best2, sizeof(double), 1, fp2);
             fclose(fp2);
        }
    }
}

/*--- トレーニングを実行して得点(所要時間)を返す ---*/
double go(void)
{
    int        i, j, x,no,stage;
    int        dgt[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int        a[10];
    double    jikan;                // 時間 
    clock_t    start, end;            // 開始時刻・終了時刻 

    printf("\n\nダブっている数字を入力してください。\n");
    printf("スペースキーで開始します。\n");
    while (getch() != ' ')
        ;
    start = time(NULL);

    for (stage = 0; stage < MAX_STAGE; stage++) {
         x = rand() % 9;        /* 0~8の乱数を発生 */


        i = j = 0;
        while (i < 9) {            /* dgt[x]をダブらせてコピー */
            a[j++] = dgt[i];
            if (i == x)
                a[j++] = dgt[i];
            i++;
        }

        for (i = 9; i > 0; i--) {    /* 配列aをシャッフル */
            int j = rand() % (i + 1);
            if (i != j)
                swap(int, a[i], a[j]);
        }

        for (i = 0; i < 10; i++)    /* 全要素を表示 */
            printf("%d ", a[i]);
        printf(":");
        fflush(stdout);

        do {
            no = getch();
            if (isprint(no)) {                /* 表示可能であれば */
                putch(no);                    /* 押されたキーを表示 */
                if (no != dgt[x] + '0')        /* 正解でなければ */
                    putch('\b');            /* カーソルを一つ戻す */
                else
                    printf("\n");            /* 改行 */
            }
        } while (no != dgt[x] + '0');
    }
    end = time(NULL);

    jikan = (double)difftime(end, start)

    printf("%.1f秒かかりました。\n", jikan);

    if (jikan > 25.0)
        printf("鈍すぎます。\n");
    else if (jikan > 20.0)
        printf("少し鈍いですね。\n");
    else if (jikan > 17.0)
        printf("まあまあですね。\n");
    else
        printf("素早いですね。\n");

    term_getputch();

    return (jikan);

}
int main(void)
{
    int       retry,count=0;    // もう一度? 
    double score;            // 今回の所要時間 
    double best;            // 最短所要時間 
    double    jikan;                // 時間
    FILE *fp;
    fpos_t ft;
    fpos_t kaime_p1;
    struct tm local ;
    int k;
    int     i, j, x, stage;
    best= get_data(&count);    // get_data()で前回までの最短所要時間を
                            // ファイルから読み込んでbestに代入する。 
    printf("bestは%.1f1\n\n", best); 
    printf("count3は%d\n\n", count);                         

    fp = fopen(dtfile, "rb");

    kaime_p(&kaime_p1);

    k=kaime_p1;
    //ファイルポインタの位置を取得
    printf("mainのkaime_p(&kaime_p1)後のkの値は「%d」です。\n\n",k);

    //ファイルポインタを末尾まで移動
    fseek(fp,0,SEEK_END);
    //ファイルポインタの位置を取得
    fgetpos(fp,&ft);        //ファイルfpの現在のファイル位置を取得して
                            // &ftの示す場所に格納します。

    new_local_data(ft,k);

    fgetpos(fp,&ft);

    //best = get_data(ft);
    // get_data()で前回までの最短所要時間を
    //ファイルから読み込んでbestに代入する。                         
    init_getputch(); //ライブラリの初期処理235p、initscr(),cbreak(),noecho(),refresh()
    srand(time(NULL));                // 乱数の種を初期化 
    do {
        score = go();    // トレーニング(go)で実行、返却された所要時間(jika)をscoreに代入する。 

        if (score < best) {
            printf("最短所要時間を更新しました!!\n");
            best = score;            /* 最高得点更新 */
        }

        printf("もう一度しますか … (0)いいえ (1)はい:");
        scanf("%d", &retry);
    } while (retry == 1);

    put_data(score,best);                /* 今回の日付・時刻・得点を書き込む */
    fflush(stdout);
    fclose(fp);

    term_getputch(); //ライブラリの初期処理235p,endwin()

    return 0;

}

/* 実行結果
C:\Users\username\chap09\kadai\kadai9-2>gcc -I. -o kad9_2_1b kad9_2_1b.c pdcurses.a

C:\Users\username\chap09\kadai\kadai9-2>kad9_2_1b

過去の履歴
--------------------------
2015年 10月 27日 19時 9分 59秒
得点(所要時間)は11.0秒

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

......省略......

count1は12


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

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

2016年 3月 19日 11時 43分 16秒 0秒
得点(所要時間)は 7.8秒です。

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

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

2016年 1月 4日 19時 19分 7秒 0秒
得点(所要時間)は 10.0秒です。

2016年 1月 5日 21時 33分 29秒 0秒
得点(所要時間)は 10.0秒です。

2016年 3月 19日 11時 41分 52秒 0秒
得点(所要時間)は 10.7秒です。

2016年 1月 4日 19時 16分 39秒 0秒
得点(所要時間)は 10.0秒です。

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

count2は12

bestは8.0

cunt3は12


ファイルポインタの位置kaime_p1は「44」です。
mainのkaime_p(&kaime_p1)後のkの値は「44」です。

最近の10回の点数とそれらの実行日時は

2016年 3月 19日 11時 43分 16秒
得点(所要時間)は7.8秒

2016年 3月 19日 11時 41分 52秒
得点(所要時間)は10.7秒

........省略........

enterキーで開始します


*/
コード
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

こんにちは。

ざっと見てみました。2~3問題に気が付きました。

①startとendを取得する関数が異なる。前者はtime(NULL)、後者はclock()
たぶん、統一しないと適正な結果にはならないのでは?
②go()関数が常に0を返却してます。
これをキーにしてソートしているのでソートされないのではないかと思います。

後、データがない時、起動すると落ちます。
167行目のfor(i=0;i<10;i++){for(i=0;i<*count;i++){へ変更してとりあえず落ちませんでした。
(cursesを入れるのは手間なので、普通の関数で代用しました。)

たぶん、いいところまでできていると思います。頑張って下さい。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/19 19:28

    いつもお世話になっています。
    おっしゃる通りで修正してとおりましたので
    全体のプログラムのかんせいです。去年からの自由課題9-1,9-2、9-3が完成します。
    ラックナンバーリサーチができていましたので、コピーしてやったつもりでしたが
    変更箇所にきずきませんでした。

    キャンセル

  • 2016/03/19 19:29

    ありがとうございました(^^)

    キャンセル

  • 2016/03/19 19:42

    頑張り凄いですね。お疲れ様でした!!

    キャンセル

  • 2016/03/19 22:21

    すみません1回成功したのですが、いろんなこののプログラムを
    整理している最中、成功したものがどこかにいってしまい。
    もとにもどってしまいました。いちおう教えていただいたとおりに
    修正してみたのですが、大体ちさい順になっているのですが
    順番がおかしいので、もう一度見ていただけませんか。
    今日朝からやっていて、くたくたなんで、
    あしたみなおすつもりですが、よろしくおねがいいたします

    キャンセル

  • 2016/03/20 00:23

    ちょっと見てみましたが、走らせるだけで一苦労です。

    sanchu52さんの学習のために何故に私が苦労してデバッグしなければならないのか?という疑問もありますし、もう少し絞り込んでから再度ご質問頂けたらと思います。

    キャンセル

  • 2016/03/20 08:50

    おしゃる通りでした。お忙しい方にお願いしてすみませんでした。
    デバッグを少し勉強したいと思います。
    これからの投稿には、ご返事は結構です。ありがとうございました。

    キャンセル

+1

発想の転換の回答です。
書籍であれば飛ばして次に行くのも手ですね、また戻ってくればいいですし。


おそらく以下書籍の問題に基づいて質問をされている可能性がありそうですね。
プロフィールで確認致しました。
・柴田望洋著 新版明解C言語 中級編、実践編

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/19 13:32

    おしゃるとおりです。今飛ばすと余計わからなくなるとおもいます。
    自由課題9-1,9-2,9-3をやっているところで
    90%から95%できています。もっと複雑なんですが
    おかしいところだけ切り取って質問しています
    600行ぐらいになっています。ありがとうございます
    ラックナンバーリサーチのベストテンは正常に表示になっているので
    ダブルナンバーも同じように書き直してやっているのですが、間、趣味ですので
    がんばってみます。
    どこかが間違っていると思うのですが

    キャンセル

  • 2016/03/20 00:04 編集

    発想の転換の理由は暗に答えをもとめるのではなく、以下のポイントから再考の余地ありと判断したからですね。
    ・頑張るのは構わないですが質問をした時点で相手の時間を奪うかもしれません。
    →一人で頑張るのは趣味の時間としていれば特に異論はありません。
    ・悩むのに1か月費やすのと1日費やすのをどっちを選ぶと聞かれたらどうしますか?
    ・時間をおいて、後で見直して気づくこともあります。(視点が客観的になるので)
    ただし非常におしい実装をしていたので、後で見直したら気づくかなーという考えもありました。

    キャンセル

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

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • C

    4661questions

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