C言語で2つの時間・時刻の差を求めるプログラムの書き方

学校の課題などで、C言語で2つの時間の差を求めるプログラムを書かなければいけなくなった方もいるでしょう。

そういう方向けに時刻の差を求めるサンプルコードと解説を用意しましたので、プログラミング初心者で悩んでいる方は、参考にしてみてください。

目次から探す

2つの時刻の差をC言語で求める方法

先にサンプルコードを見ておきましょう。以下のコードをベースに、なぜこのプログラムで時刻の差を計算できるのか解説を進めていきます。

#include<stdio.h>
struct TimeData {
	int h; //時
	int m; //分
	int s; //秒
};

TimeData TimeDiff(TimeData data1, TimeData data2) {
	int sec1 = data1.h * 3600 + data1.m * 60 + data1.s;
	int sec2 = data2.h * 3600 + data2.m * 60 + data2.s;
	int secdiff = sec2 - sec1;
	TimeData result;
	result.h = secdiff / 3600;
	result.m = (secdiff % 3600) / 60;
	result.s = secdiff % 60;

	return result;
}

int main() {
	TimeData data1 = { 12,24,35 };//12時24分35秒
	TimeData data2 = { 15,36,45 };//15時36分45秒
	TimeData result = TimeDiff(data1, data2);
	printf("時刻の差は%d時間%d分%d秒です",result.h, result.m, result.s);

	return 0;
}

まずは2行目のstruct TimeDataにて時刻データとなる構造体を定義しています。

8行目に時刻の差を求めるTimeDiff関数を定義していますが、このTimeDiff関数で時刻の差の計算をすべて行っています。

TimeData TimeDiff(TimeData data1, TimeData data2) {
	int sec1 = data1.h * 3600 + data1.m * 60 + data1.s;
	int sec2 = data2.h * 3600 + data2.m * 60 + data2.s;
	int secdiff = sec2 - sec1;
	TimeData result;
	result.h = secdiff / 3600;
	result.m = (secdiff % 3600) / 60;
	result.s = secdiff % 60;

	return result;
}

引数には時刻データを2つ受け取るためにTimeData構造体を2つ受け取るようにしています。

TimeDiff関数の最初に、2つの時刻を秒数に変換します。

int sec1 = data1.h * 3600 + data1.m * 60 + data1.s;
int sec2 = data2.h * 3600 + data2.m * 60 + data2.s;

秒数に直すと計算が難しいように見えますが、それは人間が暗算する場合の話。プログラムにとっては異なる3つの時間データを一つにまとめたほうが計算しやすいのです。

1時間は3600秒、1分は60秒なので、それぞれに3600と60をかけたものを足していけば秒数に変換できます。

次に秒数に直した2つの時刻データの差を計算し、secdiff変数に代入します。

int secdiff = sec2 - sec1;

これで秒数の差を計算できました。このsecdiffを時分秒に直せば時刻の差を計算できます。

秒数データから時分秒それぞれを取り出す計算式は下記の通り。

  • 時間:秒数 ÷ 3600(小数点以下切り捨て)
  • 分:(秒数 ÷ 3600の余り) /60(小数点以下切り捨て)
  • 秒:秒数 ÷ 3600の余り

これをプログラムにすると以下のようになります。

TimeData result; //secdiffは先程計算した秒数データの差
result.h = secdiff / 3600;
result.m = (secdiff % 3600) / 60;
result.s = secdiff % 60;

TimeData構造体のh,m,s変数はそれぞれint型なので、自動的に小数点以下が切り捨てられます。

これにより、正確な時刻の差を時分秒に直した上で計算できるのです。

最後に時刻の差のデータが入ったresult変数を返してTimeDiff関数の完成です。

あとは時刻の差を求めたい箇所でTimeDiff関数を呼び出して完成です。

int main() {
	TimeData data1 = { 12,24,35 };//12時24分35秒
	TimeData data2 = { 15,36,45 };//15時36分45秒
	TimeData result = TimeDiff(data1, data2); //data2 - data1
	printf("時刻の差は%d時間%d分%d秒です",result.h, result.m, result.s);

	return 0;
}

これで時刻の差を求めることができます。関数化することで簡単に時刻の差を計算できるので、基本的には関数化しておきましょう。

構造体を使わない場合

構造体を習っていない・知らない方は、構造体を使わない方法も知っておくといいでしょう。ただし、引数がかなり多くなってわかりづらくなります。

#include<stdio.h>
int TimeDiff(int h1,int m1,int s1, int h2, int m2, int s2, int *hh, int *mm, int *ss) {
	int sec1 = h1 * 3600 + m1 * 60 + s1;
	int sec2 = h2 * 3600 + m2 * 60 + s2;
	int secdiff = sec2 - sec1;
	*hh = secdiff / 3600;
	*mm = (secdiff % 3600) / 60;
	*ss = secdiff % 60;

	return 0;
}

int main() {
	//12時24分35秒
	int h1 = 12;
	int m1 = 24;
	int s1 = 35;

	////15時36分45秒
	int h2 = 15;
	int m2 = 36;
	int s2 = 45;

	//時刻差受け取り用
	int hh;
	int mm;
	int ss;

	TimeDiff(h1,m1,s1,h2,m2,s2,&hh,&mm,&ss);
	printf("時刻の差は%d時間%d分%d秒です",hh,mm,ss);

	return 0;
}

return文で返せる値は一つだけなので、ポインタを用いて時刻の差を受け取るようにしています。

見て分かる通り、この書き方をするくらいなら100%構造体を使ったほうがいいでしょう。

構造体もポインタも使わない場合

先に行っておきますが、非推奨コードです。非常に見づらく、これを覚えるべきではありません。見なかったことにしたほうがいいレベルの劣悪コードです。一応方法はあるのでサンプルコードを載せておきます。

#include<stdio.h>
//時間差を返す
int TimeDiffHour(int h1,int m1,int s1, int h2, int m2, int s2) {
	int sec1 = h1 * 3600 + m1 * 60 + s1;
	int sec2 = h2 * 3600 + m2 * 60 + s2;
	int secdiff = sec2 - sec1;
	return secdiff / 3600;	
}

//分数の差を返す
int TimeDiffMinute(int h1, int m1, int s1, int h2, int m2, int s2) {
	int sec1 = h1 * 3600 + m1 * 60 + s1;
	int sec2 = h2 * 3600 + m2 * 60 + s2;
	int secdiff = sec2 - sec1;
	return (secdiff % 3600) / 60;
}

//秒数の差を返す
int TimeDiffSecond(int h1, int m1, int s1, int h2, int m2, int s2) {
	int sec1 = h1 * 3600 + m1 * 60 + s1;
	int sec2 = h2 * 3600 + m2 * 60 + s2;
	int secdiff = sec2 - sec1;
	return secdiff % 60;
}

int main() {
	//12時24分35秒
	int h1 = 12;
	int m1 = 24;
	int s1 = 35;

	////15時36分45秒
	int h2 = 15;
	int m2 = 36;
	int s2 = 45;

	//時刻差計算
	int hh = TimeDiffHour(h1, m1, s1, h2, m2, s2);
	int mm = TimeDiffMinute(h1, m1, s1, h2, m2, s2);;
	int ss = TimeDiffSecond(h1, m1, s1, h2, m2, s2);;

	printf("時刻の差は%d時間%d分%d秒です",hh,mm,ss);

	return 0;
}

どう考えても使うべきではない書き方なので、あえて解説しません。

ですが、構造体を使えばこのようなムダが多すぎるコードをかなり簡略化しつつ見やすくできるということがよく分かると思います。

構造体の便利さを知るいい機会

構造体を使わずに時刻の差を求めるサンプルコードを見るとわかりますが、引数の数がすごく多いですし、何より見づらいです。

構造体を使えばコードが短くなる上にかなり短くなるので、今まで構造体を知っていたけど使っていなかった、知らなかったという方は構造体を使いこなせるよう頑張るといいでしょう。

目次から探す