ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
naoji
記事: 15
登録日時: 10年前

ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

#1

投稿記事 by naoji » 10年前

柴田望洋の新・明解C言語中級編のラックナンバーサーチを作成しました。

プログラムは起動するのですが、
実行してみると、
「本プログラムを実行するのは初めてですね。
前回の終了は%d年%d月%d日%d時%d分%d秒でした。
これまでの最高得点 (最短所要時間)は%.1f秒です」
が表示されずにいきなり計算部分から始まります。
また、
計算終了後、
%.1f秒かかりました。・・・もう一度しますか ・・・ (0)いいえ (1)はい :
の部分が表示されずに、計算終了後、即プログラム自体が終了してしまいます。

コードのどの部分を修正すれば、
全て上手く表示されるのでしょうか??

教えてください。
よろしくお願いします。

コード:

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

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

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

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

/*--- 前回のトレーニング情報を取得・表示して最高得点を返す ---*/
double get_data(void)
{
	FILE *fp;
	double best;		/*最高得点*/
	
	if ( (fp = fopen(dtfile , "r") ) == NULL){
		printf("本プログラムを実行するのは初めてですね。\n\n");
		best = 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);
		printf("前回の終了は%d年%d月%d日%d時%d分%d秒でした。\n",
												year , month , day , h , m , s);
		
		printf("これまでの最高得点 (最短所要時間)は%.1f秒です。\n\n" , best);
		fclose(fp);
	}
	
	return best;
}

/*--- 今回のトレーニング情報を書き込む ---*/
void put_data(double best)
{
	FILE *fp;
	time_t t = time(NULL);
	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;		/*開始時刻・終了時刻*/
	
	printf("欠けている数字を入力してください。\n");
	printf("スペースキーで開始します。\n");
	while (getch() != ' ')
		;
	
	start=clock();
	
	for (stage=0 ; stage<MAX_STAGE ; stage++){
		int x = rand() % 9;			/*0〜8の乱数を生成*/
		int no;					/*読み込んだ値*/
		
		i  = j = 0;
		while (i<9){				/*dgt[x]を飛ばしてコピー*/
			if (i != x)
				a[j++] = dgt[i];
			i++;
		}
	
		for (i=7 ; i>0 ; i--){				/*配列aをシャッフル*/
			int j = rand() % (i+1);
			if ( 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");		/*改行*/
				fflush(stdout);
			}
		}while (no != dgt[x] + '0');
	}
	
	end =clock();
	
	jikan = (double)(end - start)/CLOCKS_PER_SEC;
	
	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();			/*トレーニング実行*/
		
		if (score < best){
			printf("最高得点 (所要時間) を更新しました!!\n");
			best = score;		/*最高得点更新*/
		}
		
		printf("もう一度しますか ・・・ (0)いいえ (1)はい : ");
		scanf("%d" , &retry);
	}while (retry == 1);
	
	put_data(best);			/*今回の日付・時刻・得点を書き込む*/
	
	term_getputch();
	
	return 0;
}
ちなみにgetputch.hのコードはこです。

コード:

/*getch/putch用の共通ヘッダ"getputch.h"*/

#ifndef __GETPUTCH

	#define __GETPUTCH
	
	#if defined  (_MSC_VER) || (__TURBOC__)  || (LSI_C)
	
		/*MS-Windows/MS-DOS(Visual C++ , Borland C++ , LSI-C 86 etc... ) */
	
		#include <conio.h>
		
		static void init_getputch(void) { /* 空 */ }
		
		static void term_getputch(void) { /* 空 */ }
	
	#else
	
		/*Cursesライブラリが提供されるUNIX/Linux/OS X */
	
		#include <curses.h>
	
		#undef putchar
		#undef puts
		#undef printf
		static char __buf[4096];
	
		/*--- putchar : putchar関数と同等 ( 改行を[改行+復帰]で出力) ---*/
		static int __putchar(int ch)
		{
			if ( ch == '\n')
				putchar('\r');
			return putchar(ch);
		}
	
		/*--- putch : 1文字表示してバッファを掃き出す ---*/
		static int putch(int ch)
		{
			int result = putchar(ch);
		
			fflush(stdout);
			return result;
		}
	
		/*--- __printf : printf関数と同等(改行を[改行+復帰]で出力) ---*/
		static int __printf( const char *format , ...)
		{
			va_list ap;
			int		count;
			
			va_start (ap , format);
			vsprintf (__buf , format , ap);
			va_end (ap);
			
			for ( count=0 ; __buf[count] ; count++){
				putchar (__buf[count] );
				if (__buf[count] == '\n' )
					putchar ('\r');
			}
			return count;
		}
	
		/*--- __puts: puts関数と同等 ( 改行を[改行+復帰]で出力) ---*/
		static int __puts(const char *s)
		{
			int i , j;
			
			for (i=0 , j=0 ; s[i] ; i++){
				__buf[j++] = s[i];
				if (s[i] == '\n')
					__buf[j++] = '\r';
			}
			return puts(__buf);
		}
		
		/*--- ライブラリ初期処理 ---*/
		static void init_getputch(void)
		{
			initscr();
			cbreak();
			noecho();
			refresh();
		}
		
		/*---  ライブラリ終了処理 ---*/
		static void term_getputch(void)
		{
			endwin();
		}
		
		#define putchar __putchar
		#define printf __printf
		#define puts __puts
	
	#endif

#endif

Aozora0630
記事: 85
登録日時: 10年前
住所: 日本
連絡を取る:

Re: ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

#2

投稿記事 by Aozora0630 » 10年前

計算部分から始まると言うことは、出力が以下の様になるということでしょうか?

欠けている数字を入力してください。
スペースキーで開始します。

詳細な出力内容も公開してください。

naoji
記事: 15
登録日時: 10年前

Re: ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

#3

投稿記事 by naoji » 10年前

そうです!
本来なら、
本プログラムを実行するのは初めてですね。
前回の終了は%d年%d月%d日%d時%d分%d秒でした。
これまでの最高得点 (最短所要時間)は%.1f秒です。
欠けている数字を入力してください。
スペースキーで開始します。
と表示されるはずなのですが、
プログラムを起動すると何も表示されません。
スペースキーを押しますと、
「本プログラムを実行するのは初めてですね。
前回の終了は%d年%d月%d日%d時%d分%d秒でした。
これまでの最高得点 (最短所要時間)は%.1f秒です。」
は表示されず、
欠けている数字を入力してください。
スペースキーで開始します。が表示され、
実際の計算が開始されます。

また、
計算終了後、
本来なら、
%.1f秒かかりました。・・・もう一度しますか ・・・ (0)いいえ (1)はい :
の部分が表示さるはずなのですが、
実際は、
計算終了後、
何も表示されずにプログラムが終了してしまいます。

どこが問題で、
どの部分を修正したら直るのでしょうか?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

#4

投稿記事 by みけCAT » 10年前

135行目のinit_getputch();を132行目に移動し、

・35行目
・55行目
・68行目
・123行目
・146行目
の直後にfflush(stdout);を追加したところ、動作が改善しました。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

#5

投稿記事 by みけCAT » 10年前

naoji さんが書きました:どこが問題で
・cursesによって画面が切り替わる前の画面に出力している
・バッファに入った内容がすぐに出力されない
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

naoji
記事: 15
登録日時: 10年前

Re: ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

#6

投稿記事 by naoji » 10年前

みけCATさんありがとうございます!
改善されました!

ですが、
146行目の部分にfflush(stdout);を導入しました。
それがこれです。

コード:

if (score < best){
            printf("最高得点 (所要時間) を更新しました!!\n");
            best = score;       /*最高得点更新*/
        }
        fflush(stdout)
        printf("もう一度しますか ・・・ (0)いいえ (1)はい : ");
        scanf("%d" , &retry);
    }while (retry == 1);
もう一度しますか ・・・ (0)いいえ (1)はい :
と表示されるのですが、
scanf関数が上手く動作しません(^^;)
fflush(stdout)の場所が間違っていますか??

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

#7

投稿記事 by みけCAT » 10年前

naoji さんが書きました:もう一度しますか ・・・ (0)いいえ (1)はい :
と表示されるのですが、
scanf関数が上手く動作しません(^^;)
本当ですか?きちんとテストしましたか?
ちなみに、scanf関数に「入力をエコーする」という機能は無いはずです。
naoji さんが書きました:fflush(stdout)の場所が間違っていますか??
はい。146行目の直前ではなく、直後に挿入してください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

naoji
記事: 15
登録日時: 10年前

Re: ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

#8

投稿記事 by naoji » 10年前

きちんとテストしてみました!
もう一度しますか ・・・ (0)いいえ (1)はい :
までは表示されるのですが、
数字を入力しても表示されず、
もう一度 トレーニングがスタートされませんでした(^^;)
そして、
半角数字以外を押すと強制的にプログラムが終了してしまいました。

もう一度確かめてテストしてみます(^^;)

ここまで丁寧に教えてくださって、
本当にありがとうございます。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

#9

投稿記事 by みけCAT » 10年前

naoji さんが書きました:きちんとテストしてみました!
もう一度しますか ・・・ (0)いいえ (1)はい :
までは表示されるのですが、
数字を入力しても表示されず、
もう一度 トレーニングがスタートされませんでした(^^;)
そして、
半角数字以外を押すと強制的にプログラムが終了してしまいました。
こっちでテストした時は、きちんと1→Enterの順で押したらもう一度スタートしました。
scanfに頼らず、getchとputchを用いた実装に切り替えるのもいいかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

naoji
記事: 15
登録日時: 10年前

Re: ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

#10

投稿記事 by naoji » 10年前

テストしてみました!
もう一度しますか ・・・ (0)いいえ (1)はい :
上手くもう一回計算トレーニングが作動しました!
ありがとうございます。

ただ、
もう一度しますか ・・・ (0)いいえ (1)はい :
が表示されたときに、
1以外の数字を間違って入力した際に、
もう一度1を再度入力してスペースキーを押しても、
プログラムは強制終了してしまいます。

それを直したいのですが、
コードのどの部分を修正すれば、
間違った数字を入力した際でも、
再度1を入力してスペースキーを押したら、
プログラムがもう一度行えるようになりますか??

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

#11

投稿記事 by みけCAT » 10年前

naoji さんが書きました:ただ、
もう一度しますか ・・・ (0)いいえ (1)はい :
が表示されたときに、
1以外の数字を間違って入力した際に、
もう一度1を再度入力してスペースキーを押しても、
プログラムは強制終了してしまいます。
間違って入力した後、十分な回数Backspaceキー(もしくはそれに相当するキー)を押してから1を入力してもダメですか?
naoji さんが書きました:それを直したいのですが、
コードのどの部分を修正すれば、
間違った数字を入力した際でも、
再度1を入力してスペースキーを押したら、
プログラムがもう一度行えるようになりますか??
147行目で、scanfを用いずに、getchやputchを用いて自前で入力を管理するのがいいと思います。
そうすれば入力をエコーして確認させることができますし、エンターキーではなくスペースキーで確定させることも可能になるはずです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

naoji
記事: 15
登録日時: 10年前

Re: ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

#12

投稿記事 by naoji » 10年前

一回バックスペースキーを押しても終了してしまいます。(^^;)

今、

コード:

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

コード:

 printf("もう一度しますか ・・・ (0)いいえ (1)はい : ");
 do{
       scanf("%d" , &retry);
}while ( retry >1);
にしたら、
間違えて入力した際は、
1を二回入力すれば、
またプログラムができるようになりました!

getchを用いたのですが、
自分のコードが下手なせいか
一回の入力ミスで終了してしまいました(^^;)

コード:

printf("もう一度しますか ・・・ (0)いいえ (1)はい : ");
        retry = getch();
また、
このようにしてみましたら、

コード:

 printf("もう一度しますか ・・・ (0)いいえ (1)はい : ");
 do{
       retry=getch();
}while ( retry >1);
もう一度しますか ・・・ (0)いいえ (1)はい :
この先いくら数字を入力したり、
スペースキーを押しても反応せず、
もう一度しますか ・・・ (0)いいえ (1)はい :
この表示のままでした。

間違えた際に、
1を一回入力してスペースきーを押せば、
プログラムがもう一度起動するようにしたいのですが、
アドバイスもらえないでしょうか??
お願いします。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

#13

投稿記事 by みけCAT » 10年前

naoji さんが書きました:間違えた際に、
1を一回入力してスペースきーを押せば、
プログラムがもう一度起動するようにしたいのですが、
アドバイスもらえないでしょうか??
お願いします。
こんな感じでしょうか?

コード:

	do{
		int input = -1;
		score = go();			/*トレーニング実行*/
		
		if (score < best){
			printf("最高得点 (所要時間) を更新しました!!\n");
			best = score;		/*最高得点更新*/
		}
		
		printf("もう一度しますか ・・・ (0)いいえ (1)はい : ");
		for(;;){
			int next_input=getch();
			if(next_input==' '){
				if(input=='0'){
					retry=0;
					break;
				}else if(input=='1') {
					retry=1;
					break;
				}
			}else{
				if(input>=0)printf("\b \b");
				putch(next_input);
				fflush(stdout);
				input=next_input;
			}
		}
	}while (retry == 1);
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

naoji
記事: 15
登録日時: 10年前

Re: ラックナンバーサーチを作成しましたが、一部表示されません。どこが原因でしょうか?

#14

投稿記事 by naoji » 10年前

みけCATさんありがとうございます!
みけCATさんのコードに修正したら、
間違えても1回入力するだけで、
またプログラムを行えるようになりました!!

本当にありがとうございました。
また、
わからないことがあった際は、
お手数おかけしますが、
よろしくお願いします。

閉鎖

“C言語何でも質問掲示板” へ戻る