2014年4月17日木曜日

開発環境

C++実践プログラミング (スティーブ オウアルライン (著)、Steve Oualline (原著)、Steve Oualline(原著)、望月 康司(翻訳)、クイープ(翻訳) 、オライリー・ジャパン)のⅣ部(高度なプログラミング概念)の18章(演算子のオーバーロード)、18.6(プログラミング実習)、実習 18-5.を解いてみる。

その他参考書籍

実習 18-5.

コード(BBEdit, Emacs)

my_date2.h

#ifndef __my_date2_h__
#define __my_date2_h__
#include <iostream>
#include <iomanip>

namespace my_date2 {
  const int DAYS_PER_MONTH[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  class date {
  private:
    int month;
    int day;
    int year;
    static bool is_leap (int year)
    {
      return (year % 400 == 0) || (year % 100 != 0 && year % 4 == 0) ? true:
        false;
    }
  public:
    date () {
      month = 1;
      day = 1;
      year = 0;
    }
    date (int m, int d, int y) {
      month = m;
      day = d;
      year = y;
    }
    // date (const date& old_date);
    // ~date ();
    // date operator = (const date& old_date);

    date operator += (const date& op2)
    {
      return (*this) + op2;
    }

    date operator -= (const date& op2)
    {
      return (*this) - op2;
    }

    friend date operator + (const date& op1, const date& op2);
    friend date operator - (const date& op1, const date& op2);
    friend std::ostream& operator << (std::ostream& out_file, const date& d);
    friend std::istream& operator >> (std::istream& in_file, date& d);
  };

  inline std::ostream& operator << (std::ostream& out_file, const date& d)
  {
    out_file << std::setw(2) << std::setfill('0') << d.month << '/' <<
      std::setw(2) << std::setfill('0') << d.day << '/' <<
      std::setw(2) << std::setfill('0') << d.year;
    return (out_file);
  }

  extern date operator + (const date& op1, const date& op2);
  extern date operator - (const date& op1, const date& op2);
  extern std::istream& operator >> (std::istream& in_file, date&d);
}
#endif /*__my_date2_h__*/

my_date2.cpp

#include <iostream>

#include "my_date2.h"

namespace my_date2 {
  date operator + (const date& op1, const date& op2)
  {
    int month = op1.month + op2.month;
    int day = op1.day + op2.day;
    int year = op1.year + op2.year;

    while (month > 12 || day > DAYS_PER_MONTH[month - 1]) {
      if (month > 12) {
        month -= 12;
        ++year;
      }
      else {
        if (month == 2 && date::is_leap(year)) {
          if (day == 29) break;
          day -= 29;
        }
        else
          day -= DAYS_PER_MONTH[month - 1];
        ++month;
      }
    }
    return date(month, day, year);
  }

  date operator - (const date& op1, const date& op2)
  {
    int year = op1.year - op2.year;
    int month = op1.month - op2.month;
    int day = op1.day - op2.day;

    if (month < 1) {
      month += 12;
      --year;
    }
    while (!(day > 0 && day <= DAYS_PER_MONTH[month - 1])) {
      if (date::is_leap(year)) {
        if (!(day > 0)) {
          if (month == 3)
            day += 29;
          else
            day += DAYS_PER_MONTH[month - 2];

          --month;
        }
        else {
          if (month == 2) {
            if (day == 29) break;

            day -= 29;
          }
          else
            day -= DAYS_PER_MONTH[month - 1];
          
          ++month;
        }
      }
      else {
        if (!(day > 0)) {
          day += DAYS_PER_MONTH[month - 2];
          --month;
        }
        else {
          day -= DAYS_PER_MONTH[month - 1];
          ++month;
        }
      }
      if (month < 1) {
        month += 12;
        --year;
      }
    }
    return date(month, day, year);
  }

  std::istream& operator >> (std::istream& in_file, date& d)
  {
    int month;
    int day;
    int year;
    char ch;

    month = 1;
    day = 1;
    year = 0;

    std::istream::sentry the_sentry(in_file, true);

    if (the_sentry) {
      if (in_file.fail()) return (in_file);

      in_file >>  month;
      if (in_file.fail()) return (in_file);

      in_file >> ch;
      if (in_file.fail()) return (in_file);

      if (ch != '/') {
        in_file.setstate(std::ios::failbit);
        return (in_file);
      }

      in_file >> day;
      if (in_file.fail()) return (in_file);

      in_file >> ch;
      if (in_file.fail()) return (in_file);

      if (ch != '/') {
        in_file.setstate(std::ios::failbit);
        return (in_file);
      }

      in_file >> year;
      if (in_file.fail()) return (in_file);

      d.month = month;
      d.day = day;
      d.year = year;
    }
    else
      in_file.setstate(std::ios::failbit);

    return (in_file);
  }
}

test_my_date2.cpp

#include <iostream>

#include "my_date2.h"

int main(int argc, char *argv[])
{
  my_date2::date d0;
  my_date2::date d1(4, 1, 0);
  my_date2::date d2(12, 31, 0);
  my_date2::date d3;

  std::cout << d0 << "(01/01/00)\n";
  std::cout << d1 << "(04/01/00)\n";
  std::cout << d2 << "(12/31/00)\n";

  std::cout << "日付を入力(MM/DD/YY) >> ";
  std::cin >> d3;
  std::cout << d3 << '\n';

  std::cout << d0 << " + " << d1 << " = " << d0 + d1 << std::endl;
  std::cout << d1 << " + " << d0 << " = " << d1 + d0 << std::endl;
  std::cout << d1 << " + " << d2 << " = " << d1 + d2 << std::endl;
  std::cout << d2 << " + " << d1 << " = " << d2 + d1 << std::endl;
  std::cout << d2 << " + " << d3 << " = " << d2 + d3 << std::endl;
  std::cout << d3 << " + " << d2 << " = " << d3 + d2 << std::endl;

  std::cout << d0 << " - " << d1 << " = " << d0 - d1 << std::endl;
  std::cout << d1 << " - " << d0 << " = " << d1 - d0 << std::endl;
  std::cout << d1 << " - " << d2 << " = " << d1 - d2 << std::endl;
  std::cout << d2 << " - " << d1 << " = " << d2 - d1 << std::endl;
  std::cout << d2 << " - " << d3 << " = " << d2 - d3 << std::endl;
  std::cout << d3 << " - " << d2 << " = " << d3 - d2 << std::endl;

  return (0);
}

Makefile

CC=g++
CFLAGS=-g -Wall
all: test_my_date2

test_my_date2: test_my_date2.cpp my_date2.o
 ${CC} ${CFLAGS} -o test_my_date2 test_my_date2.cpp my_date2.o

my_date2.o: my_date2.cpp my_date2.h
 ${CC} -c -o my_date2.o my_date2.cpp

clean:
 rm test_my_date2

入出力結果(Terminal)

$ make && ./test_my_date2
make && ./test_my_date2
g++ -c -o my_date2.o my_date2.cpp
g++ -g -Wall -o test_my_date2 test_my_date2.cpp my_date2.o
01/01/00(01/01/00)
04/01/00(04/01/00)
12/31/00(12/31/00)
日付を入力(MM/DD/YY) >> 1/29/3
1/29/3
01/29/03
01/01/00 + 04/01/00 = 05/02/00
04/01/00 + 01/01/00 = 05/02/00
04/01/00 + 12/31/00 = 05/02/01
12/31/00 + 04/01/00 = 05/02/01
12/31/00 + 01/29/03 = 02/29/04
01/29/03 + 12/31/00 = 02/29/04
01/01/00 - 04/01/00 = 08/31/-1
04/01/00 - 01/01/00 = 02/29/00
04/01/00 - 12/31/00 = 03/01/-1
12/31/00 - 04/01/00 = 08/30/00
12/31/00 - 01/29/03 = 11/02/-3
01/29/03 - 12/31/00 = 12/30/01
$

0 コメント:

コメントを投稿