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

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

ただいまの
回答率

90.23%

コンパイルは通るけど実行過程でエラーが出て終了する

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 1,681

sanchu52

score 163

コンパイルは通るのですがコードretryのところで
0 か 1を選んでも表示がでなくて1を押すと
エンター2回押しで再実行できるのですが
0を押すとエラー表示がでて終了
します。エンターキー1回押しで実行したいのですが
教えてください。MinGWで実行しています。

>C:\Users\username\chap09\kadai\kadai9-2>gcc -I. -o lacknum3 lackn
um3.c pdcurses.a

>C:\Users\username\chap09\kadai\kadai9-2>lackn
um3
欠けている数字を入力してください。
スペースキーで開始します。
 3 4 6 9 5 1 7 :8
 2 1 9 5 3 7 8 :6
 7 2 9 6 4 5 1 :8
1.2秒かかりました。
素早いですね。
最高得点(所要時間)を更新しました!!
もう一度しますか … (0)いいえ (1)はい:エラー発生!!

/* ラックナンバーサーチ・トレーニング(その3:前回の日時・最高得点を表示)*/

#include <time.h>
#include <float.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include "getputch.h"

#define MAX_STAGE    3
#define swap(type, x, y)    do { type t = x; x = y; y = t; } while (0)//この処理は常に1回しか実行されずしかも内容がない。

char dtfile[] = "LACKNUM.DAT";                /* ファイル名 */

/*--- 前回のトレーニング情報を取得・表示して最高得点を返す ---*/
double get_data(void)
{
    FILE *fp;
    double best;        // 最高得点 

    if ((fp = fopen(dtfile, "r")) == NULL) {
        printf("本プログラムを実行するのは初めてですね。\n\n");
        best = DBL_MAX;  /* float.hに定義されている。double型で表現できる最大値を表すマクロDBL_MAX */
    } else {
        int    year, month, day, h, m, s;

        fscanf(fp, "%d%d%d%d%d%d", &year, &month, &day, &h, &m, &s);
        fscanf(fp, "%lf", &best);   // stream(fp)が指すストリームから&bestに読み込む 
                                    //fscanf 関数は format が指す書式文字列に従って 
                                    //stream(fp) が指すストリームからデータを読込み,
                                    //format(&year, &month, &day, &h, &m, &s) に続く引数の指すオブジェクトに代入します.
        printf("前回の終了は%d年%d月%d日%d時%d分%d秒でした。\n\n",
                                            year, month, day, h, m, s);    

        printf("これまでの最高得点(最短所要時間)は%.1f秒です。\n\n", best);

        // 画面が一瞬で消えてしまうのを防止 
        // 一瞬で画面が消えてしまう場合には、
        // 以下の文を入力します。
        //fflush(stdout); 
        fclose(fp);
    }

    return (best);
}

/*--- 今回のトレーニング情報を書き込む ---*/
void put_data(double best)
{
    FILE *fp;
    time_t t = time(NULL);  //時間を取得する関数は time_t time(time_t *) と clock_t clock(NULL) があります。
                            //time() の戻り値は time_t 型、 clock() の戻り値は clock_t 型です。
                            //これらの型は time.h の中で定義されています。 普通は long 型として定義されていますが、
                            //これらの型はそれぞれの時間を表しきれる精度を持った型という意味
                            //time(time_t *) は精度は低いですがプロセスの切り替えに影響されず実時間を取得できます。 
                            //time() で時間を取得するときは(変数 t に入れるとする)time(&t);
                            //t=time(NULL);
                            //time(&t);
    struct tm *local = localtime(&t);

    if ((fp = fopen(dtfile, "w")) == NULL)
        printf("エラー発生!!");
    else {
        fprintf(fp, "%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);

        fprintf(fp, "%f\n", best);
        fclose(fp);
    }
}

//--- トレーニングに要した所要時間を返す ---
double go(void)
{
    int        i, j, stage;
    int        dgt[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int        a[8];
    double    jikan;        // 時間 
    clock_t    start, end;    // 開始時刻・終了時刻 
                        // clock() の精度は機種に依存しますが
                        // 大体 1ms 単位程度の精度があるようです
                        // clock() の戻り値は、秒以下の単位まで整数型で表せるように
                        // 適当な整数が掛けられています。 その適当な整数とは 
                        // time.h の中で CLOCKS_PER_SEC という定数として定義されています。 
                        // ですから、 clock() で得られた値を CLOCKS_PER_SEC で割ると秒数が求まります。
                        // clock() で求まる時間はそのプロセスが消費したプロセッサ時間になります。 
                        // 一方、time(time_t *) で求まる時間は歴時間です。

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

    start = clock();    // clock() の戻り値は、秒以下の単位まで整数型で表せるように
                        // 適当な整数が掛けられています。 その適当な整数とは 
                        // time.h の中で CLOCKS_PER_SEC という定数として定義されています。

                        // ですから、 clock() で得られた値を CLOCKS_PER_SEC で割ると秒数が求まります。
                        // clock() で求まる時間はそのプロセスが消費したプロセッサ時間になります。 

    for (stage = 0; stage < MAX_STAGE; stage++) {
        int x = rand() % 9;        // 0~8の乱数を発生 ,1から9までのうち8文字を表示するための数字 
        int    no;                    // 読み込んだ値 ,キーボードから打ち込んだ数字 

        i = j = 0;
        while (i < 9) {            // dgt[x]を飛ばしてコピー 
            if (i != x)
                a[j++] = dgt[i];// dgt[x]は1から9までの数字が入っている配列 
            i++;
        }

        for (i = 7; i > 0; i--) {        // 配列aをシャッフル、配列の添字は0から7までの8個である 
            int j = rand() % (i + 1);    // 配列aの添字は0から7までの8個である。jは1から7まで変化する 
            if (i != j)                    // jは1から7まで変化する。iとjの添字でシャッフルする。 
                swap(int, a[i], a[j]);
        }

        for (i = 0; i < 8; 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 = clock();

    jikan = (double)(end - start) / CLOCKS_PER_SEC; 
            // clock() で得られた値を CLOCKS_PER_SEC で割ると秒数が求まります。
            // clock() で求まる時間はそのプロセスが消費したプロセッサ時間になります。 

    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");

    return (jikan);
}

int main(void)
{
    int       retry;        // もう一度? 
    double score;        // 今回のトレーニングの所要時間 
    double best;        // これまでのトレーニングの最短所要時間 

    best = get_data();            // 前回までの最短所要時間を得る 

    init_getputch();
    srand(time(NULL));            // 乱数の種を初期化 

    do {
        score = go();            // トレーニング実行で帰ってくる値は score=double jikan;である。    

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

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

    put_data(best);                // 今回の日付・時刻・得点を書き込む 

    term_getputch();

    return (0);
}

```

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

checkベストアンサー

0

「エラー発生!!」と表示されるのはファイル保存できなかった時のようなので
パーミッション等を確認されては如何でしょうか。
もしくは保存先のパス(動作中のカレントディレクトリ)が期待通りか表示するなど
して確認してみるといいかもしれません。
エンター2回押しの件については

scanf("%d\n",&retry);

としてみたら改善されたりしませんかね?
ダメそうならいっそ他同様に getch で入力した方が良いかもしれません。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/03/16 17:39

    アリガトウございます変数間違いと文字と数字の勘違いでした

    キャンセル

0

scanf()で数値だけを取ると、数値の後に続く改行コードが行末に残ってしまいます。これを適当な方法で読み捨てるか、fgetsで1行取得してから数値をsscanfで取るなど、何かしらの対策が必要となります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/03/16 14:24

    ありごとうございます具体的にscanf()のコードのあとにどんなコードを書けばいいのでしょうか?
    こういうretryのコードがほかにもあるのですが、以前は通っていたコードで正常に0,1が表示されていました、プログラムをいじっていてどこかが変わったのだと思うのですがよろしくお願いします

    キャンセル

0

こんにちは。

cursesを持っていないので、getch()→getchar()、putch()→putchar()に置き換え、init_getputch()とterm_getputch()を外して、MinGW 5.2.0でやってみました。
入力する度に1回Enterを押す必要はありますが、正常に動作しているようです。
Enterを押す必要があるのは、Windowsの仕様です。
cursesが提供するgetch()等に何か問題があるのかも知れません。

標準入出力のバッファリングを解除できれば、恐らく意図されている通りの動作になると思うのですが、分かりません。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

scanf("%d",&retry);
を以下のように変更しました
retry=getch()-'0';
printf("%d",retry);

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

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