2017年10月24日
《その91》 tm構造体,localtime関数(p.417演習11-7)
tm構造体
C++ では、構造体はクラスとほぼ同じものです。C++ でのキーワード struct は、キーワード class とほとんど同じ意味が与えられているので、クラス同様の宣言に使うことができます。
相違点としては、アクセス権を指定していないメンバが、struct の場合は公開メンバであることです。
次の tm構造体型の定義例を見ると、クラスと同じ造りになっているのがわかります。アクセス権を指定していないので、全て公開メンバです。
struct tm {
int tm_sec; // 秒
int tm_min; // 分
int tm_hour; // 時
int tm_mday; // 日
int tm_mon; // 月( 1月…0 〜 12月…11 )
int tm_year; // 1900年からの年数
int tm_wday; // 曜日( 日曜…0 〜 土曜…6 )
int tm_yday; // 1月1日からの日数( 0 〜 355 )
int tm_isdst; // 夏時間フラグ
};
tm構造体型の定義は、処理系により多少異なる場合があります。
localtime関数
前回《その90》チェックした time関数で、time_t型の暦時刻を取得できました。
その暦時刻を元にして tm構造体を生成してくれるのが localtime関数です。tm構造体は、年・月・日・時・分・秒・曜日 といった要素別の値を保持しているので、それを取り出して利用することができます。
time_t current = time(NULL);
struct tm* timer = localtime(&current);
char* wday_name[] = {"日", "月", "火", "水", "木", "金", "土"};
cout << "現在の日付・時刻"
<< timer->tm_year + 1900 << "年"
<< timer->tm_mon + 1 << "月"
<< timer->tm_mday << "日("
<< wday_name[timer->tm_wday] << ")"
<< timer->tm_hour << "時"
<< timer->tm_min << "分"
<< timer->tm_sec << "秒\n";
※ struct tm* timer はポインタなので、例えば、構造体のデータメンバ tm_sec にアクセスする場合は
◆ (*timer).tm_sec
◆ timer->tm_sec
のように記述します。
新版明解C++入門編 p.417 演習11-7
演習10-2(このブログの《その79》)で作成した自動車クラス Car に、購入年月日を格納するデータメンバと、その値を返却するメンバ関数を追加せよ。
4つのファイル Date.h
Date.cpp
Car.h
CarTest.cpp
を順に記述します。
// Date.h
#ifndef ___Class_Date
#define ___Class_Date
#include <string>
#include <iostream>
class Date {
int y;
int m;
int d;
public:
Date();
Date(int yy, int mm = 1, int dd = 1);
int year() const { return y; }
int month() const { return m; }
int day() const { return d; }
std::string day_of_week() const;
Date preceding_day() const;
std::string to_string() const;
};
std::ostream& operator<<(std::ostream& s, const Date& x);
std::istream& operator>>(std::istream& s, Date& x);
#endif
// Date.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <iomanip>
#include <ctime>
#include <sstream>
#include <iostream>
#include "Date.h"
using namespace std;
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;
}
string Date::day_of_week() const {
string dw[] = { "日" ,"月", "火", "水", "木", "金", "土" };
int yy = y; int mm = m;
if (mm == 1 || mm == 2) {
yy--;
mm += 12;
}
return dw[(yy + yy / 4 - yy / 100 + yy / 400 + (13 * mm + 8) / 5 + d) % 7];
}
Date Date::preceding_day() const {
int dmax[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
Date temp = *this;
if (temp.d > 1)
temp.d--;
else {
if (--temp.m < 1) {
temp.y--;
temp.m = 12;
}
temp.d = dmax[temp.m - 1];
}
return temp;
}
string Date::to_string() const {
ostringstream s;
s << setfill('0') << y << "年"
<< setw(2) << m << "月"
<< setw(2) << d << "日"
<< "(" << day_of_week() << ")";
return s.str();
}
ostream& operator<<(ostream& s, const Date& x) {
return s << x.to_string();
}
istream& operator>>(istream& s, Date& x) {
int y, m, d; char c;
s >> y >> c >> m >> c >> d;
x = Date(y, m, d);
return s;
}
// Car.h
#ifndef ___Class_Car
#define ___Class_Car
#include <cmath>
#include <string>
#include <iostream>
#include "Date.h"
class Car {
std::string name, number;
int width, length, height;
double tank_capa, km_p_L;
double fuel_level;
double xp, yp;
Date purchase_d;
public:
Car(std::string num, std::string nam, int w, int l, int h,
double t, double km, const Date& d)
: name(nam), number(num), width(w), length(l), height(h),
tank_capa(t), km_p_L(km), purchase_d(d)
{
fuel_level = 0.0; xp = yp = 0.0;
}
void print_spec() const {
std::cout << "【スペック】" << '\n';
std::cout << "------------" << '\n';
std::cout << "名前:" << name << '\n';
std::cout << "車幅:" << width << "mm\n";
std::cout << "車長:" << length << "mm\n";
std::cout << "車高:" << height << "mm\n";
std::cout << "タンク容量:" << tank_capa << "L\n";
std::cout << "燃費:" << km_p_L << "km/L\n";
std::cout << "------------" << '\n';
std::cout << " " << number << '\n';
std::cout << " " << purchase_date() << "購入\n\n";
}
Date purchase_date() const { return purchase_d; }
bool refueling(double gas) {
if (fuel_level + gas > tank_capa) {
fuel_level = tank_capa;
return false;
}
else {
fuel_level += gas;
return true;
}
}
void print_situation() const {
std::cout << "・現在地 x:" << xp << "km y:" << yp << "km\n";
std::cout << "・燃料残量:" << fuel_level << "L" << '\n';
}
bool move(double dx, double dy) {
double dist = sqrt(dx * dx + dy * dy);
if (dist > fuel_level * km_p_L)
return false;
else {
fuel_level -= dist / km_p_L;
xp += dx;
yp += dy;
return true;
}
}
};
#endif
// CarTest.cpp
#include <iostream>
#include "Car.h"
using namespace std;
int main()
{
Car myCar("横浜012-3456", "ランドクルーザー", 1980, 4950, 1870,
90, 6.6, Date(2017,10,25));
myCar.print_spec();
while (true) {
myCar.print_situation();
cout << '\n';
int move;
cout << "[ 0…到着 /1…移動 /2…給油 ]:"; cin >> move;
if (move == 0) break;
if (move == 2) {
double gas;
do {
cout << "給油量[L]:"; cin >> gas;
} while (gas < 0);
if (!myCar.refueling(gas))
cout << "\a燃料が多過ぎます!\n満タンまで入れました。\n";
}
else {
double dx, dy;
cout << "X方向の移動距離[km]:"; cin >> dx;
cout << "Y方向の移動距離[km]:"; cin >> dy;
if (!myCar.move(dx, dy)) {
cout << "\a燃料が不足!\n";
}
}
}
}
--
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
https://fanblogs.jp/tb/6892932
※ブログオーナーが承認したトラックバックのみ表示されます。
この記事へのトラックバック