はじめに
C言語でタイマーを作ることは、初心者にとっても大変有用な経験となります。
タイマー機能は、ゲーム開発からシステム開発まで幅広く活用されており、特にC言語ではその基本的な理解と活用が求められます。
本記事では、C言語でタイマーを作るための具体的な5つのステップと、10個のサンプルコードを解説します。
最後まで読んでいただければ、あなたもタイマー作成の達人に一歩近づけるでしょう。
●C言語とは?
C言語は、1970年代初頭にAT&Tベル研究所のデニス・リッチーによって開発された汎用プログラミング言語です。
システムソフトウェア開発を主目的として設計され、その効率の良さと強力な機能性から、現在でもOSや組み込みシステムの開発に広く利用されています。
○C言語の基本構造
C言語の基本構造は「プリプロセッサ命令」「グローバル宣言部」「main関数」の3つで構成されます。
プリプロセッサ命令では、プログラムのコンパイル前に行われる処理を記述します。
例えば、#include という記述は、標準入出力関数を使えるようにするためのものです。
グローバル宣言部では、プログラム全体で使う変数や関数の宣言を行います。
main関数はプログラムの実行を司ります。
この関数の中に、具体的な処理を記述します。
●タイマーとは?
タイマーは一定の時間経過を測るための機能です。
一定時間ごとに特定の処理を行うためのトリガーとして、または時間を計測するためのツールとして広く使われています。
○タイマーの役割と活用例
タイマーの主な役割は、一定の時間経過を計測し、特定のイベントを発生させることです。
例えば、ゲームでは一定時間ごとに敵キャラクターを生成したり、リアルタイム処理のための基準として使われます。
また、システム開発では、一定時間ごとにデータを更新したり、バックアップを取るなどの処理に使われます。
●C言語でタイマーを作るためのステップ
C言語でタイマーを作るためには、次の5つのステップが必要です。
それぞれのステップで必要なサンプルコードとその解説を行います。
○サンプルコード1:タイマーの初期設定
まず、タイマーの初期設定を行います。
#include <stdio.h>
#include <time.h>
int main() {
clock_t start_time;
start_time = clock();
}
このコードでは、タイマーの開始時間を取得しています。
clock_t
はtime.h
ライブラリに定義されている時間を表す型で、clock()
関数によって現在のプロセッサ時間を取得します。
これがタイマーの開始時間となります。
○サンプルコード2:タイマーのスタート
次に、タイマーのスタートを行います。
#include <stdio.h>
#include <time.h>
int main() {
clock_t start_time, current_time;
start_time = clock();
while(1) {
current_time = clock();
if((current_time - start_time) / CLOCKS_PER_SEC >= 1) {
printf("1秒経過\n");
start_time = current_time;
}
}
}
このコードでは、無限ループを使ってタイマーを動かしています。
clock()
関数で現在のプロセッサ時間を取得し、それが開始時間から1秒以上経過していれば、「1秒経過」と表示します。
そして、開始時間を更新します。
これにより、1秒ごとに何かの処理を行うタイマーを作ることができます。
○サンプルコード3:タイマーの一時停止
C言語でタイマーを一時停止するためには、条件分岐と関数を活用します。
#include <stdio.h>
#include <time.h>
int main() {
time_t start_time, current_time;
int pause_flag = 0;
double elapsed_time;
printf("タイマーをスタートします。\\n");
start_time = time(NULL);
while(1) {
if(pause_flag == 0){
current_time = time(NULL);
elapsed_time = difftime(current_time, start_time);
printf("経過時間: %.2f 秒\\n", elapsed_time);
}
if(elapsed_time > 5){
pause_flag = 1;
printf("タイマーを一時停止します。\\n");
break;
}
}
return 0;
}
このコードではtime関数を使ってタイマーのスタート時点と現在時刻を取得し、difftime関数でその差分を計算しています。
タイマーが5秒以上経過したら、pause_flagを1に設定してwhileループを終了させ、タイマーを一時停止させています。
このコードを実行すると、まず「タイマーをスタートします。」と表示され、次に経過時間が表示されます。
経過時間が5秒以上になると、「タイマーを一時停止します。」と表示され、タイマーは一時停止します。
このサンプルコードは基本的な一時停止の操作を表していますが、ユーザーからの入力を受けてタイマーを一時停止させるような機能も可能です。
その際は、getchar関数やscanf関数を用いてユーザーの入力を受け取ることになるでしょう。
○サンプルコード4:タイマーのリスタート
次に、一時停止したタイマーを再開させるための方法を見てみましょう。
ここでも同様に条件分岐と関数を活用します。
#include <stdio.h>
#include <time.h>
int main() {
time_t start_time, current_time, pause_time;
int pause_flag = 0;
double elapsed_time;
printf("タイマーをスタートします。\\n");
start_time = time(NULL);
while(1) {
if(pause_flag == 0){
current_time = time(NULL);
elapsed_time = difftime(current_time, start_time);
printf("経過時間: %.2f 秒\\n", elapsed_time);
}
if(elapsed_time > 5){
pause_flag = 1;
pause_time = current_time;
printf("タイマーを一時停止します。\\n");
break;
}
}
printf("タイマーを再開します。\\n");
pause_flag = 0;
start_time += difftime(time(NULL), pause_time);
while(1) {
if(pause_flag == 0){
current_time = time(NULL);
elapsed_time = difftime(current_time, start_time);
printf("経過時間: %.2f 秒\\n", elapsed_time);
}
if(elapsed_time > 10){
printf("タイマーを停止します。\\n");
break;
}
}
return 0;
}
このコードでは一時停止したタイマーを再開するため、pause_flagを0に戻し、一時停止期間をスタート時間に加算しています。
これにより、経過時間が一時停止期間を考慮した時間となります。
このコードを実行すると、タイマーが再開され、「タイマーを再開します。」と表示されます。
その後、経過時間が表示され、経過時間が10秒以上になると、「タイマーを停止します。」と表示され、タイマーは停止します。
○サンプルコード5:タイマーの停止
ここまでで、タイマーの初期設定、スタート、一時停止、リスタートの方法について紹介してきました。
次に、タイマーを完全に停止する方法について説明します。
次のサンプルコードを見てみましょう。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
volatile int timer_fired = 0;
void timer_handler(int signum) {
timer_fired = 1;
}
void stop_timer(timer_t timerid) {
timer_delete(timerid);
}
int main() {
struct sigaction sa;
struct sigevent sev;
struct itimerspec its;
timer_t timerid;
// タイマーのハンドラを設定
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = timer_handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGRTMIN, &sa, NULL) == -1) {
printf("sigaction failed\n");
exit(EXIT_FAILURE);
}
// タイマーの設定
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGRTMIN;
sev.sigev_value.sival_ptr = &timerid;
if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) {
printf("timer_create failed\n");
exit(EXIT_FAILURE);
}
// タイマーの開始
its.it_value.tv_sec = 10;
its.it_value.tv_nsec = 0;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
if (timer_settime(timerid, 0, &its, NULL) == -1) {
printf("timer_settime failed\n");
exit(EXIT_FAILURE);
}
// タイマーの停止
stop_timer(timerid);
exit(EXIT_SUCCESS);
}
このコードでは、関数stop_timerを使ってタイマーを停止しています。
この関数は、タイマーのIDを引数として受け取り、timer_delete関数を呼び出してタイマーを削除します。
こうすることで、指定したタイマーが完全に停止します。
また、上記のmain関数では、最初にタイマーの設定と開始を行い、その後すぐにタイマーの停止を行っています。
このため、このコードを実行すると、タイマーはすぐに停止するので、タイマーのハンドラが実行されることはありません。
●タイマー作成の応用例
基本的なタイマーの作り方を学んだところで、これからは少し応用的な例を見てみましょう。
下記の各サンプルコードでは、基本的なタイマーの制御を拡張し、より具体的な応用例を見ていきます。
○サンプルコード6:複数のタイマーの管理
複数のタイマーを同時に管理するためのコードを見てみましょう。
ここでは、タイマーを複数作成し、それぞれを個別に制御することが可能です。
この例では、二つのタイマーを並行して動かす例を紹介します。
#include <stdio.h>
#include <unistd.h>
int main() {
// タイマーの初期設定
int timer1 = 0, timer2 = 0;
// タイマーが動作しているかどうかを管理するフラグ
int timer1Running = 0, timer2Running = 0;
// タイマー1の開始
timer1Running = 1;
// 1秒ごとに繰り返し処理
for (int i = 0; i < 10; i++) {
if (timer1Running) {
timer1++;
printf("タイマー1: %d秒経過\n", timer1);
}
// タイマー2は3秒後に開始
if (i == 2) {
timer2Running = 1;
}
if (timer2Running) {
timer2++;
printf("タイマー2: %d秒経過\n", timer2);
}
sleep(1);
}
return 0;
}
このコードを実行すると、まずタイマー1がスタートします。
そして3秒後にタイマー2がスタートし、それぞれが独立して時間を計測します。
この方法で、複数のタイマーを同時に制御することが可能です。
○サンプルコード7:倒数タイマーの作成
タイマーを使う場面の一つに、ある一定時間が経過するまでのカウントダウンがあります。
このような倒数タイマーを作成するためのコードを見てみましょう。
この例では、10秒間の倒数タイマーを作成しています。
#include <stdio.h>
#include <unistd.h>
int main() {
// タイマーの初期設定(10からスタート)
int timer = 10;
// 1秒ごとに繰り返し処理
while (timer > 0) {
printf("残り%d秒\n", timer);
timer--;
sleep(1);
}
printf("時間切れです!\n");
return 0;
}
このコードを実行すると、まず”残り10秒”と表示され、その後1秒ごとにカウントダウンが進みます。
そして、カウントが0になった時点で”時間切れです!”と表示されます。
○サンプルコード8:タイマーにアラーム機能を付ける
タイマーが終了した際に何らかのアラームを鳴らす機能を追加するためのコードを見てみましょう。
ここではシンプルに、タイマーの時間が経過した際にメッセージを表示する機能を追加します。
この例では、5秒間のタイマーを設定し、時間が経過した際にアラームの代わりにメッセージを表示します。
#include <stdio.h>
#include <unistd.h>
void alarm() {
printf("アラーム:時間です!\n");
}
int main() {
// タイマーの初期設定
int timer = 5;
// タイマーが動作している間
while (timer > 0) {
printf("残り%d秒\n", timer);
timer--;
sleep(1);
}
// アラームを鳴らす
alarm();
return 0;
}
このコードを実行すると、”残り5秒”からカウントダウンが始まり、カウントが0になった時点でアラームのメッセージ”アラーム:時間です!”が表示されます。
○サンプルコード9:タイマーを用いた簡単なゲームの作成
この例では、タイマーを用いて簡単なゲームを作成します。
タイマーの逆数を点数とする「タイムアタック」型のゲームです。
下記のコードは、タイマーが始まってからユーザーが特定のキーを押すまでの時間を測定し、その時間がそのままスコアとなる仕組みになっています。
#include <stdio.h>
#include <time.h>
int main() {
time_t start, end;
double elapsed;
char c;
printf("Enter any key to start the game: ");
scanf("%c", &c);
start = time(NULL);
printf("Game started. Press any key to stop: ");
scanf("%c", &c);
end = time(NULL);
elapsed = difftime(end, start);
printf("You took %.2f seconds. This is your score.\n", elapsed);
return 0;
}
このコードはまず、「Enter any key to start the game:」というプロンプトを表示します。
ユーザーがキーを押すと、ゲームが開始し、その時点の時間が変数startに保存されます。
次に、「Game started. Press any key to stop:」というメッセージが表示され、再度ユーザーがキーを押すと、その時点の時間が変数endに保存されます。
最後に、変数endとstartの差(difftime関数を用いて計算)が表示され、それがユーザーのスコアとなります。
このコードを実行すると次のような出力が得られます。
Enter any key to start the game:
Game started. Press any key to stop:
You took 2.00 seconds. This is your score.
この例では、ユーザーがゲームを開始してから停止するまでに2.00秒かかったので、スコアは2.00となります。
これは非常に基本的なゲームですが、このようにタイマーを用いれば、短時間で簡単なゲームを作成することが可能です。
例えば、このゲームをさらに発展させるなら、複数のユーザーが参加できるようにしたり、ユーザーが特定のタスクを完成させるまでの時間を測定したり、ランダムなタイミングでゲームを停止させるなど、工夫を凝らすことが可能です。
○サンプルコード10:タイマーを用いたプロジェクト管理ツールの作成
次に、タイマーを用いてプロジェクト管理ツールを作成します。
この例では、各タスクの開始から終了までの時間を記録し、それを基に作業時間の管理を行うプログラムを作成します。
#include <stdio.h>
#include <time.h>
struct Task {
char name[50];
time_t start;
time_t end;
};
void startTask(struct Task *task, const char *name) {
strcpy(task->name, name);
task->start = time(NULL);
printf("Started task: %s\n", task->name);
}
void endTask(struct Task *task) {
task->end = time(NULL);
printf("Ended task: %s\n", task->name);
}
void showTaskTime(const struct Task *task) {
double elapsed = difftime(task->end, task->start);
printf("Task %s took %.2f seconds.\n", task->name, elapsed);
}
int main() {
struct Task task;
startTask(&task, "Project A");
sleep(5);
endTask(&task);
showTaskTime(&task);
return 0;
}
このコードでは、まずTaskという構造体を定義しています。
この構造体は、タスクの名前(name)、開始時間(start)、終了時間(end)を持ちます。
startTask関数は、タスクの名前を設定し、開始時間を記録します。
endTask関数は、タスクの終了時間を記録します。
showTaskTime関数は、タスクの名前と、開始から終了までの経過時間(秒単位)を表示します。
このコードを実行すると、次のような出力が得られます。
Started task: Project A
Ended task: Project A
Task Project A took 5.00 seconds.
この例では、”Project A”という名前のタスクが開始され、5秒後に終了しました。
その結果、タスクの実行時間は5.00秒と表示されました。
このようなプログラムを使うことで、プロジェクトの各タスクがどれだけの時間を要しているかを把握し、効率的なプロジェクト管理を実現することが可能です。
●C言語でタイマーを作る際の注意点
それでは、C言語でタイマーを作る際の注意点について詳しく解説していきます。プログラミングの世界では、細かいところにも注意を払うことが重要です。
タイマーを作る過程でも、それは例外ではありません。
最初の注意点として、タイマーの精度を確保することがあります。
タイマーの精度は、そのタイマーがどれだけ正確に時間を計測できるかを表すもので、この精度が低いと計測したい時間と実際の時間との間にズレが生じる可能性があります。
C言語でタイマーを作る際には、適切な関数やライブラリを選ぶことで、この精度を確保することが可能です。
また、タイマーの動作を制御する際にも注意が必要です。
特に、タイマーのスタート、一時停止、再スタート、停止といった基本的な操作を正しく行うことが重要です。
これらの操作がうまく機能しないと、タイマーは正しく動作しません。
さらに、タイマーを作る際には、タイマーが動作する環境にも注意を払う必要があります。
例えば、タイマーが動作するハードウェアやオペレーティングシステム、さらにはその他のソフトウェアとの互換性を確認することが重要です。
これらの注意点を押さえつつ、さまざまなタイマーの作成に挑戦してみてください。
理解と経験を積むことで、あなた自身のプログラミングスキルが向上することでしょう。
まとめ
以上が、C言語でタイマーを作る方法についての解説となります。
タイマーの役割と基本操作から、応用的な使用方法、さらには注意点まで、幅広く解説しました。
サンプルコードを通じて、実際のコードがどのように動作するのか、またそれがどのように応用されるのかを理解できたことでしょう。
C言語でタイマーを作成するスキルは、多くのプログラミング環境やアプリケーションで役立つものです。
この記事を参考に、自身でタイマーを作成してみることで、C言語によるプログラミングの理解を深めるとともに、より実践的なスキルを身につけることができます。
プログラミングは絶えず学び続けることが求められる分野です。
今後も新たな知識や技術を習得し、それらを自身のプログラミングスキルに組み込んでいくことをお勧めします。
これからもあなたのプログラミング学習が進むことを願っています。