EX24 - 3.04 Editorial /

Time Limit: 2 sec / Memory Limit: 256 MB

説明ページに戻る

問題文

構造体の練習として、24時間表記の時計を表す構造体を実装してみましょう。

以下のプログラムの雛形のコメントに従って構造体を実装してください。

プログラムの雛形

#include <bits/stdc++.h>
using namespace std;

// 以下に、24時間表記の時計構造体 Clock を定義する

// Clock構造体のメンバ変数を書く
//   int hour    時間を表す (0~23の値をとる)
//   int minute  分を表す   (0~59の値をとる)
//   int second  秒を表す   (0~59の値をとる)

// メンバ関数 set の定義を書く
//   関数名: set
//   引数: int h, int m, int s (それぞれ時、分、秒を表す)
//   返り値: なし
//   関数の説明:
//     時・分・秒を表す3つの引数を受け取り、
//     それぞれ、メンバ変数 hour, minute, second に代入する

// メンバ関数 to_str の定義を書く
//   関数名: to_str
//   引数: なし
//   返り値: string型
//   関数の仕様:
//     メンバ変数が表す時刻の文字列を返す
//     時刻の文字列は次のフォーマット
//     "HH:MM:SS"
//     HH、MM、SSはそれぞれ時間、分、秒を2桁で表した文字列

// メンバ関数 shift の定義を書く
//   関数名: shift
//   引数: int diff_second
//   返り値: なし
//   関数の仕様:
//     diff_second 秒だけメンバ変数が表す時刻を変更する(ただし、日付やうるう秒は考えない)
//     diff_second の値が負の場合、時刻を戻す
//     diff_second の値が正の場合、時刻を進める
//     diff_second の値は -86400 ~ 86400 の範囲を取とりうる


// -------------------
// ここから先は変更しない
// -------------------

int main() {
  // 入力を受け取る
  int hour, minute, second;
  cin >> hour >> minute >> second;
  int diff_second;
  cin >> diff_second;

  // Clock構造体のオブジェクトを宣言
  Clock clock;

  // set関数を呼び出して時刻を設定する
  clock.set(hour, minute, second);

  // 時刻を出力
  cout << clock.to_str() << endl;

  // 時計を進める(戻す)
  clock.shift(diff_second);

  // 変更後の時刻を出力
  cout << clock.to_str() << endl;
}

制約

  • 0 \leq \mathrm{hour} \leq 23
  • 0 \leq \mathrm{minute} \leq 59
  • 0 \leq \mathrm{second} \leq 59
  • -86400 \leq \mathrm{diff\_second} \leq 86400

入力

入力は次の形式で標準入力から与えられます。

\mathrm{hour} \mathrm{minute} \mathrm{second}
\mathrm{diff\_second}

出力

HH1:MM1:SS1
HH2:MM2:SS2
  • HH1:MM1:SS1は入力で与えられた時刻を表す文字列です。
  • HH2:MM2:SS2\mathrm{diff\_second}秒だけ時刻を変更した後の時刻を表す文字列です。

ジャッジでは以下の入力例以外のケースに関してもテストされることに注意。

入力例1

0 0 0
90

出力例1

00:00:00
00:01:30

「0時0分0秒」の90秒後(1分30秒後)なので、変更後の時刻は「0時1分30秒」です。 値が1桁の場合でも、出力は2桁に揃える必要がある点に注意してください。

入力例2

0 0 0
-5

出力例2

00:00:00
23:59:55

「0時0分0秒」の5秒前なので、変更後の時刻は「23時59分55秒」です。

入力例3

23 59 30
30

出力例3

23:59:30
00:00:00

入力例4

6 57 9
-4195

出力例4

06:57:09
05:47:14

ヒント

クリックでヒントを開く

  • 構造体は次のように定義します。
struct 構造体名 {
  型1 メンバ変数名1
  型2 メンバ変数名2
  型3 メンバ変数名3
  ...(必要な分だけ書く)

  返り値の型 メンバ関数名(型1 引数1, 型2 引数2, ...) {
    // メンバ関数の内容
  }
  ...(必要な分だけ書く)
};  // ← セミコロンが必要
  • 時刻の処理は、繰り上げや繰り下げを考慮する必要があるので、注意して実装しましょう。
  • 秒→分→時の順で処理するとよいでしょう。


テスト入出力

書いたプログラムがACにならず、原因がどうしてもわからないときだけ見てください。

クリックでテスト入出力を見る

テスト入力1
0 0 0
0
テスト出力1
00:00:00
00:00:00

テスト入力2
0 0 0
-86400
テスト出力2
00:00:00
00:00:00

テスト入力3
10 25 44
14240
テスト出力3
10:25:44
14:23:04


解答例

必ず自分で問題に挑戦してみてから見てください。

クリックで解答例を見る

#include <bits/stdc++.h>
using namespace std;

// 以下に、24時間表記の時計構造体 Clock を定義する
struct Clock {
  // メンバ変数の宣言
  int hour;    // 時間を表す (0~23の値をとる)
  int minute;  // 分を表す   (0~59の値をとる)
  int second;  // 秒を表す   (0~59の値をとる)

  // メンバ関数 set の定義
  void set(int h, int m, int s) {
    hour   = h;
    minute = m;
    second = s;
  }

  // メンバ関数 to_str の定義
  string to_str() {
    string ret;

    // 必要ではないが、書いておくと誤りがある場合に気づきやすくなる
    if (!(0 <= hour && hour <= 23 &&
          0 <= minute && minute <= 59 &&
          0 <= second && second <= 59)) {
      return "error";
    }

    if (hour < 10) ret += "0";
    ret += to_string(hour);

    ret += ":";

    if (minute < 10) ret += "0";
    ret += to_string(minute);

    ret += ":";

    if (second < 10) ret += "0";
    ret += to_string(second);

    return ret;
  }

  // メンバ関数 shift の定義
  void shift(int diff_second) {
    int diff_hour = diff_second / 3600;
    diff_second %= 3600;
    int diff_minute = diff_second / 60;
    diff_second %= 60;

    second += diff_second;
    if (second >= 60) {
      // 分へ繰り上げ
      minute += 1;
      second -= 60;
    } else if (second < 0) {
      // 分から繰り下げ
      minute -= 1;
      second += 60;
    }

    minute += diff_minute;
    if (minute >= 60) {
      // 時へ繰り上げ
      hour += 1;
      minute -= 60;
    } else if (minute < 0) {
      // 時から繰り下げ
      hour -= 1;
      minute += 60;
    }

    hour += diff_hour;
    if (hour >= 24) {
      hour -= 24;
    } else if (hour < 0) {
      hour += 24;
    }
  }
};

// -------------------
// ここから先は変更しない
// -------------------

int main() {
  // 入力を受け取る
  int hour, minute, second;
  cin >> hour >> minute >> second;
  int diff_second;
  cin >> diff_second;

  // Clock構造体のオブジェクトを宣言
  Clock clock;

  // set関数を呼び出して時刻を設定する
  clock.set(hour, minute, second);

  // 時刻を出力
  cout << clock.to_str() << endl;

  // 時計を進める(戻す)
  clock.shift(diff_second);

  // 変更後の時刻を出力
  cout << clock.to_str() << endl;
}

shift関数は次のように書いてもよいでしょう。

  void shift(int diff_second) {
    while (diff_second > 0) {
      // diff_secondが正なら1秒進める

      second += 1;
      diff_second -= 1;

      if (second == 60) {
        second = 0;
        minute += 1;
      }
      if (minute == 60) {
        minute = 0;
        hour += 1;
      }
      if (hour == 24) {
        hour = 0;
      }
    }
    while (diff_second < 0) {
      // diff_secondが負なら1秒戻す

      second -= 1;
      diff_second += 1;

      if (second == -1) {
        second = 59;
        minute -= 1;
      }
      if (minute == -1) {
        minute = 59;
        hour -= 1;
      }
      if (hour == -1) {
        hour = 23;
      }
    }
  }

この問題では制約が小さいので、このように直接計算しても十分高速に答えが求まります。 ときには「効率的だが実装が煩雑になってしまうアルゴリズム」よりも、「もっと効率的な方法があることは分かっているが、実装がシンプルなアルゴリズム」を選択した方がよいこともあります。