ページ 11

タイミング合わせとは

Posted: 2007年4月05日(木) 00:06
by たのもー
先日はありがとうございました。とても勉強になりました。
今回の質問の内容は以下のものです。
C言語のDOS用のゲームをダウンロードしてソースをよんでいると
疑問が出てきました。

① タイミング合わせとは何か。

② 10~18行目までの/*~/*に意味があるのか。

③ return 0; はなくてもよいのか。
というものです。
今回もよろしくお願いします。 


   ↓↓  ソースです(一部省略)  ↓↓
#include <stdio.h>

void main()
{
	int ans,ti,wron;
	/*wronは不正解回数ansは回答*/
	wron=0;
	printf("<<E n g l i s h   T e s t>>\n\n");//タイトル表示
	
	/*
	printf("[/url]\n\n");
	printf("( ).\n");
	printf("1: 2: 3: 4:\n");
	scanf("%d",&ans);
	if(ans==2){printf("正解 \n\n");}
	if(ans==1||ans==3||ans==4){printf("× 正解は \n\n\a");wron++;}
	for(ti=1;ti<300000000;ti++){} //タイミング合わせ
	*/
	
	printf("「何してるの?」\n「今コンピュータでゲームをやってるんだ。」\n\n");
	printf("What are you doing?\nI'm ( ) PC game.\n");
	printf("1:play 2:playing 3:plaing 4:praying\n");
	scanf("%d",&ans);
	if(ans==2){printf("正解 play gameでゲームをする\n\n");}
	if(ans==1||ans==3||ans==4){printf("× 正解は2 play gameでゲームをする\n\n\a");wron++;}
	for(ti=1;ti<300000000;ti++){} //タイミング合わせ
	
	printf("[その植民地は本国から独立した。]\n\n");
	printf("The colony became independent( )the mother country.\n");
	printf("1:from 2:of 3:on 4:to\n");
	scanf("%d",&ans);
	if(ans==2){printf("正解 become independent of~で~から独立する\n\n");}
	if(ans==1||ans==3||ans==4){printf("× 正解は2 become independent of~で~から独立する\n\n\a");wron++;}
	for(ti=1;ti<300000000;ti++){} //タイミング合わせ
}
 
 

Re:タイミング合わせとは

Posted: 2007年4月05日(木) 00:28
by Justy
 たのもーさん、とてもいい質問ですね。


① タイミング合わせとは何か
 時間調整です。
 無駄に forループを走らせることで、CPUに意味もなく負荷をかけて、
次の処理の実行を遅らせます。

 ただ、マシンによって待ち時間が変わってしまうという問題と
最適化をかけてコンパイルすると、この処理は無駄と判断されて
消えてしまうかもしれないので、現在では使用されることはない手法です。


② 10~18行目までの/*~/*に意味があるのか
 特に意味はないと思います。
 一連の処理を実行したくないとき、コメント化する(コメントアウトと呼ばれています)ことで
コンパイル対象からその部分を外す為の手法です。
 きっと、この作者はこのプログラムにとっては不要だけれども、一応念の為に
とっておこうと思ったのではないでしょうか。


 ただ、/*~*/は
[color=#d0d0ff" face="monospace]/*
    printf("[/url]\n\n");		/* 表示 */
    printf("( ).\n");
*/[/color]
 のようにネストが出来ません。

 通常、複数行を纏めてコメントアウトしたい場合は(C99準拠 or C++なら)
[color=#d0d0ff" face="monospace]//   printf("[/url]\n\n");		/* 表示 */
//   printf("( ).\n");
[/color]
 のように // を使うか
[color=#d0d0ff" face="monospace]#if 0
    printf("[/url]\n\n");		/* 表示 */
    printf("( ).\n");
#endif[/color]
 のように #if を使用します。


③ return 0; はなくてもよいのか
 原則としては必要です。main関数の戻り値は int型ですから。
 対象の処理系が認めていれば必要ないことがありますが、滅多に認めていません。

Re:タイミング合わせとは

Posted: 2007年4月05日(木) 01:44
by たのもー
早い解答ありがとうございます。
一読しただけで理解できるほどわかりやすかったです^^。
さすが比類無きプログラマーだなと思いました。
また質問にくると思いますがそのときはよろしくお願いします。

Re:タイミング合わせとは

Posted: 2007年4月05日(木) 02:31
by Justy
早い解答ありがとうございます。
 いえ、どういたしまして。

また質問にくると思いますがそのときはよろしくお願いします
 はーい、こちらこそよろしくお願いします。

Re:タイミング合わせとは

Posted: 2007年4月05日(木) 03:19
by 管理人
必要ないかもしれないですけど、タイミング合わせについて、補足します。

上記のやりかたでは一定時間待つことが出来ませんでしたね。
そこを解決する方法を書きます。

この方法は色々あるのですが、一番お手軽なのが「Sleep関数」を使う事です。
引数にした時間だけ処理を止めてくれる関数です。
これを使用するときは、プログラムの最初にwindows.hをインクルードしましょう。
#include <stdio.h>
#include <windows.h>

int main(void){
	printf("エンターを押すとタイマー(3秒)スタート\n");

	while(getchar()!='\n');		//エンターが押されるまで意味のないループ

	printf("タイマースタート!\n\n");

	Sleep(3000);

	printf("3秒経ちました。\n");

	return 0;
}

実行結果

エンターを押すとタイマー(3秒)スタート

タイマースタート!

3秒経ちました。
 
 
しかしSleep関数は処理を止めてしまう関数なので、その間に何かしたくても出来ません。
そういう意味で、常に現在の時間を取得して計算する方法がより有効です。

#include <stdio.h>
#include <time.h>

int main(void){
	clock_t t;

	printf("エンターを押すとタイマー(3秒)スタート\n");

	while(getchar()!='\n');		//エンターが押されるまで意味のないループ

	printf("タイマースタート!\n\n");

	t=clock();					//今の時間を取得

	while(clock()-t<3000);		//3000ミリ秒経つまで意味のないループ

	printf("3秒経ちました。\n");

	return 0;
}

実行結果

エンターを押すとタイマー(3秒)スタート

タイマースタート!

3秒経ちました。
 
 
 
このclock()関数の返り値は特有のclock_t型なので注意してください。
深くしりたければこの関数について検索かければ沢山出てきます。
この関数はパソコンの電源をつけてから経過した時間で、「ミリ秒(1/1000秒)」で返されます。
ですからこのような計算ができるわけですね。

これを利用してストップウォッチなんかが作れます。
#include <stdio.h>
#include <time.h>


int main(void){
	clock_t t;
	printf("エンターを押すと計測スタート\n");
	while(getchar()!='\n');		//エンターが押されるまで意味のないループ
	printf("計測スタート!\n");
	t=clock();					//今の時間を取得
	while(getchar()!='\n');		//エンターが押されるまで意味のないループ
	printf("計測時間 %.3f秒\n",(clock()-t)/1000.0);
	return 0;
}

実行結果

エンターを押すと計測スタート

計測スタート!

計測時間 4.468秒
 
 
 
これはSleep関数では出来なかった事ですね。このようにclock関数を使うと時間を計測しながら、常にユーザーの動きをチェックしたり他の処理を行ったり出来ます。

参考までに。

p.s.
clock_t型は 
typedef long clock_t;
で定義されているので(システムによって違う場合があります)、普通は普通のint型だと思っていいと思います。

Re:タイミング合わせとは

Posted: 2007年4月05日(木) 22:37
by たのもー
返事遅れてすみませんm(_ _)m
いや~実に詳しい解説ありがとうございます。
参考書の内容を超えていましたよ。
本当にありがとうございました。