仕様
時刻または時間の時・分・秒を整数配列で保持することとする。 例えば、 2 時 34 分 56 秒という時刻であれば、以下のように長さ 3 の整数型の要素を持つ配列を用意するものとする。 ここで、HH、MM、SS などを定数で定義しているのは後で日付などが追加されることなどを考慮したためである。 0, 1, 2 のような意味づけした数値(Magic Number) を使うのではなく、定数にすることにより、データ構造が変化した場合にも柔軟に対応することが可能となる。
#define N 3 #define HH 0 #define MM 1 #define SS 2 (中略) int jikoku[N]; jikoku[HH] = 2; jikoku[MM] = 34; jikoku[SS] = 56;
作成する関数
関数のポンチ絵を記述するので、プロトタイプ宣言を記述すること。
h:m:s の 0:00:00 からの秒数を得る
0:00:00 からの秒数を時刻から得る
0:00:00 からの秒数から時刻を得る
時刻・時間のセット (結果の分・秒は範囲内に設定されていること。ただし、入力の m, s は 0 か ら 59 までの範囲に入っていない場合もあることを考えること。例 62 分→ 1 時間 2 分に変換でき るように)
時刻の前後関係を返す (t1p が t2p より未来なら 1、過去なら −1、等しければ 0)
時刻に時間を加算した時刻を得る (結果の分・秒は範囲内に設定されていること)
時間を n 倍した時間を得る (分・秒は範囲内に設定されていること)
時間を n 等分した時間を得る (端数秒は切り捨て。結果の分・秒は範囲内に設定されていること)
時間(t1p)を時間(t2p)で割り、何等分できるかを得る(端数は切り捨て)
二つの時刻の間の時間を得る(正の値が必要なので未来から過去を引くこと。結果の分・秒は範囲内に設定されていること)
ファイルの準備
時刻・時間の関数を作成する前に、それをテストするためのプログラム(testMyTime.c)を書く。まずは,もっとも簡単な時刻から秒数を得るプログラムのテストを作成する。先週の base フォルダを用いて関係するファイルを用意すること。以下手順を示す。
- base.zip をダウンロードし、展開する。
- base という名前を myTime に変更する。
- このフォルダで iTerm2 または PowerShell を開く。
code .
として Visual Studio Code を開く。- ファイル名を以下のように変更する。
- _gitignore → .gitignore
- fact.c → myTime.c
- fact.h → myTime.h
- factMain.c → myTimeMain.c
- testFact.c → testMyTime.c
- Makefile を開き、上と同じ修正を行う
- fact.h → myTime.h
- fact.o → myTime.o
- factMain → myTimeMain
- testFact → testMyTime
- ファイルの準備ができたので、chokidar でファイルを監視する。
chokidar *.c *.h Makefile -c "make test"
テストの作成
testMyTime.c を以下のように記述する。まず最初に getSeconds のテストを記述する。##########
の部分は自分で考えること。
#include <stdio.h> #include "myTime.h" #include "testCommon.h" void testGetSeconds() { int ans; testStart("getSeconds"); ans = getSeconds(2, 34, 56); assertEqualsInt(ans, ##########); ans = getSeconds(11, 59, 59); assertEqualsInt(ans, ##########); } int main() { testGetSeconds(); testErrorCheck(); return 0; }
- 実装の雛形まで作成し,コンパイルできることを確認する。以下のことに気をつけること。
- 実装は当初中身は適当な return 文のみを書き、コンパイルが通ることだけを確認すること
- テストは複数個記述すること。 一つだけでは偶然一致してしま うかもしれないからである。
- テストに失敗することを確認する
- テストが通過するように実装を記述する
- 一つの工程が終わったら source をコミットすること
テストの追加 (getSecondsFromTime)
- getSeconds が通ったら、次の関数 (getSecondsFromTime) をテストする。
// testGetSeconds() の下に記述する void testGetSecondsFromTime() { int jikoku1[N] = {2, 34, 56}, jikoku2[N] = {11, 59, 59}; int ans; testStart("getSecondsFromTime"); ans = getSecondsFromTime(jikoku1); assertEqualsInt(ans, ##########); ans = getSecondsFromTime(jikoku2); assertEqualsInt(ans, ##########); } int main() { testGetSeconds(); testGetSecondsFromTime(); // ここを増やす testErrorCheck(); return 0; }
- 実装の雛形まで作成し,コンパイルできることを確認する
- テストに失敗することを確認する
- テストが通過するように実装を記述する
更なるテストの追加 (makeTimeFromSeconds)
- getSecondsFromTime が通ったら、次の関数(makeTimeFromSeconds)をテストする。
// testGetSecondsFromTime() の下に記述する void testMakeTimeFromSeconds() { int jikoku[N]; testStart("makeTimeFromSeconds"); makeTimeFromSeconds(jikoku, 2 * 3600 + 34 * 60 + 56); assertEqualsInt(jikoku[HH], ###); assertEqualsInt(jikoku[MM], ###); assertEqualsInt(jikoku[SS], ###); makeTimeFromSeconds(jikoku, 12 * 3600 - 1); assertEqualsInt(jikoku[HH], ###); assertEqualsInt(jikoku[MM], ###); assertEqualsInt(jikoku[SS], ###); } int main() { testGetSeconds(); testGetSecondsFromTime(); testMakeTimeFromSeconds(); // ここを増やす testErrorCheck(); return 0; }
- 実装の雛形まで作成し,コンパイルできることを確認する
- テストに失敗することを確認する
- テストが通過するように実装を記述する