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

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

ただいまの
回答率

87.48%

2つの同じようなコードを簡素化したい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,132
退会済みユーザー

退会済みユーザー

2つの同じような関数のコードを簡素化できますか?比較用の関数 cmp3 と比較用の関数 cmpは似ているんですが、
まとめられますか。 関数get_dataと関数get_data2はにているけどこれもできるでしょうか?
ご教授をおねがいたします。

コード
#include <stdio.h>
#include <time.h>
#include <float.h>
#include <ctype.h>
#include <stdlib.h>



#define MAX_STAGE    3
#define swap(type, x, y)    do { type t = x; x = y; y = t; } while (0)
#define MAX_NUM         10
#define MAXCNT 100

char dtfile[] = "LACKNUM.DAT";
char dtfile2[]= "LACKNUM2.DAT";// ラックナンバーサーチ最短時間用のファイル 
char dtfile3[]= "LACKNUM3.DAT";
char dtfile4[]= "LACKNUM4.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;

// --------------- 比較用の関数 cmp -------------------
int cmp(const void *p, const void *q)
{
    double p_score=((TIME_DATA*)p)->score;
    double q_score=((TIME_DATA*)q)->score;

    if     (p_score > q_score) return  1;
    else if(p_score < q_score) return -1;
    else                       return  0;
}
// --------------- 比較用の関数 cmp3 -------------------
int cmp3(const void *p3, const void *q3)
{
    double p3_score=((TIME_DATA*)p3)->score;
    double q3_score=((TIME_DATA*)q3)->score;

    if     (p3_score > q3_score) return  1;
    else if(p3_score < q3_score) return -1;
    else                         return  0;
}
//ラックナンバーリサーチトレーニング情報を取得・表示して最高得点を返す 
double get_data(int *count)
{
    FILE *fp;        // これまでの履歴を指すポインタ 
    FILE *fp2;        // これまでの最短所要時間を指すポインタ 
    double score;    //これまでの最短所要時間
    double bestscore;   //これまでの最短所要時間
    int i;
    int    year, mon, mday, hour, min, sec;

    TIME_DATA stars[MAXCNT];

    if ((fp = fopen(dtfile, "rb")) == NULL) {
        printf("ファイルを作成します。\n\n");
        bestscore = DBL_MAX;  /* float.hに定義されている。double型で表現できる最大値を表すマクロDBL_MAX */
    } 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 get_data2(int *count3)
{
    FILE *fp3;        /* これまでの履歴を指すポインタ */
    FILE *fp4;        /* これまでの最短所要時間を指すポインタ */
    double score3;            //これまでの履歴の所要時間
    double bestscore2;           //これまでの最短所要時間
    int i;
    int    year, mon, mday, hour, min, sec;


    TIME_DATA stars3[MAXCNT];  // 構造体配列の宣言

    if ((fp3 = fopen(dtfile3, "rb")) == NULL) {
        printf("本プログラムを実行するのは初めてですね。\n\n");
        bestscore2=DBL_MAX; // float.hに定義されている。double型で
                             //表現できる最大値を表すマクロDBL_MAX 
        exit(1);
    } else {
        for(i=0; i<MAXCNT; i++){
            if(fscanf(fp3, "%d %d %d %d %d %d %lf\n" ,             // 構造体配列への読み込み
                 &stars3[i].tm_year,&stars3[i].tm_mon,&stars3[i].tm_mday, 
                &stars3[i].tm_hour,&stars3[i].tm_min,&stars3[i].tm_sec,&stars3[i].score)!=7) break;

            (*count3)++;
        }
        printf("\ncount01:%d\n\n",*count3);

           printf("前回の終了は%d年 %d月 %d日 %d時 %d分 %d秒 で\n\n",            // 構造体配列への読み出し
            stars3[*count3-1].tm_year,stars3[*count3-1].tm_mon,stars3[*count3-1].tm_mday,stars3[*count3-1].tm_hour,
            stars3[*count3-1].tm_min,stars3[*count3-1].tm_sec,stars3[*count3-1].score);           

    fflush(stdout); 
    fclose(fp3);
    }

    if ((fp4=fopen(dtfile4,"rb"))==NULL) {
        printf("本プログラムを実行するのは初めてですね。\n\n");
        bestscore2=DBL_MAX;  /* float.hに定義されている。double型で表現できる最大値を表すマクロDBL_MAX */
        exit(1);
    } else {
        fscanf(fp3, "%d%d%d%d%d%d", &year, &mon, &mday, &hour, &min, &sec);
        fscanf(fp3, "%lf", &bestscore2);   // 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", bestscore2);

        // 画面が一瞬で消えてしまうのを防止 
        // 一瞬で画面が消えてしまう場合には、//getchar();
        // 以下の文を入力します。
        fflush(stdout); 
        fclose(fp3);
    }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

比較用の関数 cmp3 と比較用の関数 cmpは似ているんですが、まとめられますか。 

似ているもなんも、仮引数の名前が違うだけじゃないですか。
まとめられる/られない以前にこれは同じです。

関数get_dataと関数get_data2はにているけどこれもできるでしょうか?

ファイルのオープンに失敗したときの対応が違うだけですね。
そこ以降はまとめて大丈夫ですが... 対応を統一すればよいのでは?

どちらかというと、前々から言っているとおりに、構造体の入出力を関数にした方がいいです。
毎度毎度%d%d%d... と打つのは非効率的ですし、コードも汚れてバグの原因となります。

コメントを受けて

こんな感じでしょうか。
前も同じようなコードをお見せした覚えがありますが...

typedef struct {
    int tm_year; int tm_mon; int tm_mday;        
    int tm_hour; int tm_min; int tm_sec; 
    double score;   
} SCORE_DATUM;

int print_score_datum(const SCORE_DATUM *src) {
    return print_score_datum_w_format(
        "%d年 %d月 %d日 %d時 %d分 %d秒: %f\n", src
    );
}
int print_score_datum_w_format(const char *format, const SCORE_DATUM *src) {
    return printf(format,
        src->tm_year, src->tm_mon, src->tm_mday,
        src->tm_hour, src->tm_min, src->tm_sec,
        src->score
    );    
}

int fscanf_score_datum(FILE *fp, SCORE_DATUM *dst) {
    return fscanf_score_datum_w_format(
        fp, "%d%d%d%d%d%d%lf\n", dst
    );
}
int fscanf_score_datum_w_format(FILE *fp, const char *format, SCORE_DATUM *dst) {
    return fscanf(fp, format,
        &src->tm_year, &src->tm_mon, &src->tm_mday,
        &src->tm_hour, &src->tm_min, &src->tm_sec,
        &src->score        
    );
}

int cmp_score_datum(const void *p, const void *q) {
    double p_score=((SCORE_DATUM *)p)->score;
    double q_score=((SCORE_DATUM *)q)->score;

    if     (p_score > q_score) return  1;
    else if(p_score < q_score) return -1;
    else                       return  0;
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/12 19:29

    ありがとうございます。恥ずかしい話ですが、構造体の入出力を関数にする方法を具体例で
    示してもらえませんか。やってみます。

    キャンセル

  • 2017/10/17 20:16

    ここまでやってもらって、上手く書き換えることができなかたので、つぎにいきます。また同じようなコードが出てくると思いますが、その時また教えてください。

    キャンセル

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

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

関連した質問

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