アフィリエイト広告を利用しています

広告

posted by fanblog

2017年11月05日

《その106》 静的データメンバ,静的メンバ関数,演算子関数(p.473演習13-1)


 次のプログラムは、新版明解C++入門編 p.469 〜 p.472 にある日付に関するプログラムです。

静的データメンバ static int dmax[];
静的メンバ関数  static int days_of_month(int y, int m);
static bool leap_year(int year)

は、特定のオブジェクトではなくクラス全体に関わるデータ(各月の日数)または作業(各月の日数を調べる、閏年かどうかを調べる)です。
このようなデータや作業は、静的データメンバ・静的メンバ関数で実現するべきです。



------------------------------------------------
// Date.h
#ifndef ___Class_Date
#define ___Class_Date

#include <string>
#include <iostream>

class Date {
int y; // 西暦年
int m; // 月
int d; // 日
static int dmax[]; // 各月の日数(静的データメンバ)
static int days_of_month(int y, int m); // y年m月の日数(静的メンバ関数)

public:
Date(); // デフォルトコンストラクタ
Date(int yy, int mm = 1, int dd = 1); // コンストラクタ

static bool leap_year(int year) { // 閏年なら true を返却(静的メンバ関数)
return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
}

int year() const { return y; } // 年を返却
int month() const { return m; } // 月を返却
int day() const { return d; } // 日を返却
bool leap_year() const { // 閏年なら true を返却(非静的メンバ関数)
return leap_year(y);
}
Date preceding_day() const; // 前日の日付を返却
Date following_day() const; // 翌日の日付を返却
int day_of_year() const; // 年内の経過日数を返却
int day_of_week() const; // 曜日を返却

std::string to_string() const; // 文字列表現を返却
};

std::ostream& operator<<(std::ostream& s, const Date& x); // 挿入子の多重定義

#endif


// Date.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
#include <sstream>
#include <iostream>
#include "Date.h"

using namespace std;

// 各月の日数(閏年でない年)
int Date::dmax[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

// y年m月の日数
int Date::days_of_month(int y, int m) {
return dmax[m - 1] + (leap_year(y) && m == 2);
}


// デフォルトコンストラクタ(今日の日付で作成)
Date::Date() {
time_t current = time(NULL); // 現在の暦時刻を取得
struct tm* local = localtime(&current); // 要素別の時刻に変換

y = local->tm_year + 1900; // 年:tm_yearは西暦年-1900
m = local->tm_mon + 1; // 月:tm_monは0〜11
d = local->tm_mday;
}

// コンストラクタ(指定した年月日で作成)
Date::Date(int yy, int mm, int dd) {
y = yy;
m = mm;
d = dd;
}

// 年内の経過日数
int Date::day_of_year() const {
int days = d;
for (int i = 1; i < m; i++)
days += days_of_month(y, i);
return days;
}

// 前日の日付
Date Date::preceding_day() const {
Date temp = *this;

if (temp.d > 1)
temp.d--;
else {
if (--temp.m < 1) {
temp.y--;
temp.m = 12;
}
temp.d = days_of_month(temp.y, temp.m);
}
return temp;
}

// 翌日の日付
Date Date::following_day() const {
Date temp = *this;

if (temp.d < days_of_month(temp.y, temp.m))
temp.d++;
else {
if (++temp.m > 12) {
temp.y++;
temp.m = 1;
}
temp.d = 1;
}
return temp;
}

// 曜日(日曜〜土曜が0〜6に対応)
int Date::day_of_week() const {
int yy = y;
int mm = m;
if (mm == 1 || mm == 2) {
yy--;
mm += 12;
}
return (yy + yy / 4 - yy / 100 + yy / 400 + (13 * mm + 8) / 5 + d) % 7;
}

// 文字列表現を返却
string Date::to_string() const {
ostringstream s;
s << y << "年" << m << "月" << d << "日";
return s.str();
}

// 挿入子の多重定義
ostream& operator<<(ostream& s, const Date& x) {
return s << x.to_string();
}


// DateTest.cpp
#include <iostream>
#include "Date.h"
using namespace std;

int main() {
Date today; // 今日の日付

cout << "今 日の日付:" << today << '\n';

cout << "昨 日の日付:" << today.preceding_day() << '\n';
cout << "一昨日の日付:" << today.preceding_day().preceding_day() << '\n';

cout << "明 日の日付:" << today.following_day() << '\n';
cout << "明後日の日付:" << today.following_day().following_day() << '\n';

cout << "元旦から" << today.day_of_year() << "日経過しています。\n";

cout << "今年は閏年"
<< (today.leap_year() ? "です。" : "ではありません。") << '\n';

int y, m, d;

cout << "西暦年:"; cin >> y;

cout << "その年は閏年"
<< (Date::leap_year(y) ? "です。" : "ではありません。") << '\n';
}

------------------------------------------------

c13_0002.png



新版明解C++入門編 p.473 演習13-1
 上記の日付クラス Date.h に対して、以下の演算子関数を追加した日付クラスを作成せよ。
 ● 二つの日付が等しいかどうかを判定する等価演算子==
 ● 二つの日付が等しくないかどうかを判定する等価演算子!=
 ● 二つの日付の大小関係を判定する関係演算子>, >=, <, <=
   ※ より新しい日付のほうを大きいと判定すること。
 ● 二つの日付の減算を行う(何日離れているかを求める)減算演算子−
   ※ 左オペランドから右オペランドを引くこと(日付差を正負の値で示す)。
 ● 日付を翌日の日付に更新する前置および後置の増分演算子++
 ● 日付を前日の日付に更新する前置および後置の増分演算子−−
 ● 日付を n 日進めた日付に更新する複合代入演算子+=
 ● 日付を n 日戻した日付に更新する複合代入演算子−=
 ● 日付の n 日後の日付を求める加算演算子+
 ● 日付の n 日前の日付を求める減算演算子−

// Date.h
#ifndef ___Class_Date
#define ___Class_Date

#include <string>
#include <iostream>

class Date {
int y; // 西暦年
int m; // 月
int d; // 日
static int dmax[]; // 各月の日数(静的データメンバ)

static int days_of_month(int y, int m); // y年m月の日数(静的メンバ関数)
static int day_of_year(int y, int m, int d); // y年1月1日〜y年m月d日までの日数(静的メンバ関数)

public:
Date(); // デフォルトコンストラクタ
Date(int yy, int mm = 1, int dd = 1); // コンストラクタ

static bool leap_year(int year) { // 閏年なら true を返却(静的メンバ関数)
return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
}

int year() const { return y; } // 年を返却
int month() const { return m; } // 月を返却
int day() const { return d; } // 日を返却
bool leap_year() const { // 閏年なら true を返却(非静的メンバ関数)
return leap_year(y);
}
Date preceding_day() const; // 前日の日付を返却
Date following_day() const; // 翌日の日付を返却
int day_of_year() const; // 年内の経過日数を返却
int day_of_week() const; // 曜日を返却

friend bool operator==(const Date& p, const Date& q);
friend bool operator!=(const Date& p, const Date& q);
friend bool operator <(const Date& p, const Date& q);
friend bool operator<=(const Date& p, const Date& q);
friend bool operator >(const Date& p, const Date& q);
friend bool operator>=(const Date& p, const Date& q);

friend int operator-(const Date& p, const Date& q);

Date& operator++();
Date operator++(int);
Date& operator--();
Date operator--(int);

Date& operator+=(int n);
Date& operator-=(int n);
Date operator+(int n);
Date operator-(int n);

std::string to_string() const;
};

std::ostream& operator<<(std::ostream& s, const Date& x);

#endif

// Date.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
#include <sstream>
#include <iomanip>
#include <iostream>
#include "Date.h"

using namespace std;

int Date::dmax[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

int Date::days_of_month(int y, int m) {
return dmax[m - 1] + (leap_year(y) && m == 2);
}

int Date::day_of_year(int y, int m, int d) {
int days = d;
for (int i = 1; i < m; i++)
days += days_of_month(y, i);
return days;
}


Date::Date() {
time_t current = time(NULL);
struct tm* local = localtime(&current);

y = local->tm_year + 1900;
m = local->tm_mon + 1;
d = local->tm_mday;
}

Date::Date(int yy, int mm, int dd) {
y = yy;
m = mm;
d = dd;
}

int Date::day_of_year() const {
return day_of_year(y, m, d);
}

Date Date::preceding_day() const {
Date temp = *this;

if (temp.d > 1)
temp.d--;
else {
if (--temp.m < 1) {
temp.y--;
temp.m = 12;
}
temp.d = days_of_month(temp.y, temp.m);
}
return temp;
}

Date Date::following_day() const {
Date temp = *this;

if (temp.d < days_of_month(temp.y, temp.m))
temp.d++;
else {
if (++temp.m > 12) {
temp.y++;
temp.m = 1;
}
temp.d = 1;
}
return temp;
}

int Date::day_of_week() const {
int yy = y;
int mm = m;
if (mm == 1 || mm == 2) {
yy--;
mm += 12;
}
return (yy + yy / 4 - yy / 100 + yy / 400 + (13 * mm + 8) / 5 + d) % 7;
}

bool operator== (const Date& p, const Date& q) {
return p.y == q.y && p.m == q.m && p.d == q.d;
}
bool operator!=(const Date& p, const Date& q) {
return !(p == q);
}
bool operator<(const Date& p, const Date& q) {
if (p.y == q.y)
return p.day_of_year() < q.day_of_year();
else
return p.y < q.y;
}
bool operator<=(const Date& p, const Date& q) {
return p < q || p == q;
}
bool operator>(const Date& p, const Date& q) {
return !(p <= q);
}
bool operator>=(const Date& p, const Date& q) {
return !(p < q);
}

int operator-(const Date& p, const Date& q) {
int delta_d = p.day_of_year() - q.day_of_year();
if (p.y > q.y) {
for (int i = q.y; i < p.y; i++)
delta_d += (365 + Date::leap_year(i));
}
if (p.y < q.y) {
for (int i = p.y; i < q.y; i++)
delta_d -= (365 + Date::leap_year(i));
}
return delta_d;
}

Date& Date::operator++() {
*this = following_day();
return *this;
}
Date Date::operator++(int) {
Date temp = *this;
*this = following_day();
return temp;
}
Date& Date::operator--() {
*this = preceding_day();
return *this;
}
Date Date::operator--(int) {
Date temp = *this;
*this = preceding_day();
return temp;
}

Date& Date::operator+=(int n) {
for (int i = 0; i < n; i++)
++*this;
return *this;
}
Date& Date::operator-=(int n) {
for (int i = 0; i < n; i++)
--*this;
return *this;
}
Date Date::operator+(int n) {
Date temp = *this;
for (int i = 0; i < n; i++)
++temp;
return temp;
}
Date Date::operator-(int n) {
Date temp = *this;
for (int i = 0; i < n; i++)
--temp;
return temp;
}


string Date::to_string() const {
ostringstream s;
s << y << "年" << setw(2) << m << "月" << setw(2) << d << "日";
return s.str();
}

ostream& operator<<(ostream& s, const Date& x) {
return s << x.to_string();
}

// DateTest.cpp
#include <iomanip>
#include <iostream>
#include "Date.h"
using namespace std;

int main()
{
/*
Date today;
cout << "今 日の日付:" << today << '\n';
cout << "昨 日の日付:" << today.preceding_day() << '\n';
cout << "一昨日の日付:" << today.preceding_day().preceding_day() << '\n';
cout << "明 日の日付:" << today.following_day() << '\n';
cout << "明後日の日付:" << today.following_day().following_day() << '\n';
cout << "元旦から" << today.day_of_year() << "日経過しています。\n";
cout << "今年は閏年"
<< (today.leap_year() ? "です。" : "ではありません。") << '\n';
int y, m, d;
cout << "西暦年:"; cin >> y;
cout << "その年は閏年"
<< (Date::leap_year(y) ? "です。" : "ではありません。") << '\n';
*/

Date d0; cout << "d0 … " << d0 << '\n';
Date d1(2017, 11, 5); cout << "d1 … " << d1 << '\n';
Date d2(2016, 11, 4); cout << "d2 … " << d2 << '\n';
Date d3(2016, 11, 6); cout << "d3 … " << d3 << '\n';
Date d4(2017, 11, 5); cout << "d4 … " << d4 << '\n';
Date d5(2015, 11, 4); cout << "d5 … " << d5 << '\n';
Date d6(2015, 11, 6); cout << "d6 … " << d6 << '\n';

cout << boolalpha;
cout << "d0 == d1 … " << (d0 == d1) << '\n';
cout << "d0 != d1 … " << (d0 != d1) << '\n';
cout << "d0 == d2 … " << (d0 == d2) << '\n';
cout << "d0 != d2 … " << (d0 != d2) << '\n';
cout << "d0 < d1 … " << (d0 < d1) << '\n';
cout << "d0 <= d1 … " << (d0 <= d1) << '\n';
cout << "d0 > d1 … " << (d0 > d1) << '\n';
cout << "d0 >= d1 … " << (d0 >= d1) << '\n';
cout << "d0 < d2 … " << (d0 < d2) << '\n';
cout << "d0 <= d2 … " << (d0 <= d2) << '\n';
cout << "d0 > d2 … " << (d0 > d2) << '\n';
cout << "d0 >= d2 … " << (d0 >= d2) << '\n';
cout << "d1 - d2 … " << setw(4) << (d1 - d2) << '\n';
cout << "d2 - d1 … " << setw(4) << (d2 - d1) << '\n';
cout << "d1 - d3 … " << setw(4) << (d1 - d3) << '\n';
cout << "d3 - d1 … " << setw(4) << (d3 - d1) << '\n';
cout << "d1 - d5 … " << setw(4) << (d1 - d5) << '\n';
cout << "d5 - d1 … " << setw(4) << (d5 - d1) << '\n';
cout << "d1 - d6 … " << setw(4) << (d1 - d6) << '\n';
cout << "d6 - d1 … " << setw(4) << (d6 - d1) << '\n';
cout << "++d5 … " << ++d5 << '\n';
cout << "d5 … " << d5 << '\n';
cout << "d6++ … " << d6++ << '\n';
cout << "d6 … " << d6 << '\n';
cout << "--d5 … " << --d5 << '\n';
cout << "d5 … " << d5 << '\n';
cout << "d6-- … " << d6-- << '\n';
cout << "d6 … " << d6 << '\n';
cout << "d5 += 60 … " << (d5 += 60) << '\n';
cout << "d5 … " << d5 << '\n';
cout << "d5 -= 60 … " << (d5 -= 60) << '\n';
cout << "d5 … " << d5 << '\n';
cout << "d5 + 60 … " << (d5 + 60) << '\n';
cout << "d5 … " << d5 << '\n';
cout << "d5 - 60 … " << (d5 - 60) << '\n';
cout << "d5 … " << d5 << '\n';
}

c13_01.png


新版 明解C 入門編 (明解シリーズ)

新品価格
¥2,916から
(2017/8/30 21:02時点)









--
この記事へのコメント
コメントを書く

お名前:

メールアドレス:


ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバックURL
https://fanblogs.jp/tb/6936462
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック

 たまに、クリック お願いします m(_ _)m

 AA にほんブログ村 IT技術ブログ C/C++へ

こうすけ:メール kousuke_cpp@outlook.jp

【1】★★C++ 記事目次★★ ← 利用可能です。
・新版明解C++入門編 / 新版明解C++中級編
・その他 C++ 関連記事

【2】★★こうすけ@C#★★
・C# の初歩的な記事


検索
<< 2018年08月 >>
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
プロフィール
こうすけさんの画像
こうすけ

 たまに、クリック お願いします m(_ _)m

 AA にほんブログ村 IT技術ブログ C/C++へ

こうすけ:メール kousuke_cpp@outlook.jp

【1】★★C++ 記事目次★★ ← 利用可能です。
・新版明解C++入門編 / 新版明解C++中級編
・その他 C++ 関連記事

【2】★★こうすけ@C#★★
・C# の初歩的な記事


×

この広告は30日以上新しい記事の更新がないブログに表示されております。