• 締切済み

C++で日付のプログラミング

前回も同じ質問をして、自分なりに直してみたのですが、どうもうまく動作しません。 長くなりますが、教えてください。 日付のエラー処理を完全にするというもので、 次のような仕様を満たすようにMyDateクラスを修正せよ。というものです。 1.月、日共に初期値は1とする。 2.月、日の状態を出力するメンバ関数print()を追加する。 3.changeDay関数において、monthに入っている値に対応して適切なエラー処理を行う。    4月の時は日は30まで、5月の時は31まで、みたいな感じです。 4.changeMonth関数において、変更しようとする月に対しdayに入っている値が大きすぎる場合、dayを変更後の最後の日に修正するようにする。例えば、5月31日に設定されている時に、changeMonth(2)が呼ばれた時、monthに2を、dayに28を代入する。 5.うるう年は考慮しなくていい。 #include <stdio.h> class MyDate{ private: int month, day; public: void Date(int, int); void changeMonth(int); //「月」変更用関数 void changeDay(int); //「日」変更用関数 void print(); }; void MyDate::Date(int argMonth,int argDay) { argMonth = 1; argDay = 1; } void MyDate::changeMonth(int argMonth)//メンバ関数(changeMonth)の定義 { if(argMonth >= 1 && argMonth <= 12){ //1~12のときだけ値を更新 month = argMonth; } } void MyDate::changeDay(int argDay)//メンバ関数(changeDay)の定義 { //1~31が入力された場合のみ値を更新 if(argDay >= 1 && argDay <= 31){ day = argDay; } if(month == 1,day > 31){ printf("DATE = %d/%d\n",1,31); }else if(month == 2,day > 28){ printf("DATE = %d/%d\n",2,28); }else if(month == 3,day > 31){ printf("DATE = %d/%d\n",3,31); }else if(month == 4,day > 30){ printf("DATE = %d/%d\n",4,30); }else if(month == 5,day > 31){ printf("DATE = %d/%d\n",5,31); }else if(month == 6,day > 30){ printf("DATE = %d/%d\n",6,30); }else if(month == 7,day > 31){ printf("DATE = %d/%d\n",7,31); }else if(month == 8,day > 31){ printf("DATE = %d/%d\n",8,31); }else if(month == 9,day > 30){ printf("DATE = %d/%d\n",9,30); }else if(month == 10,day > 31){ printf("DATE = %d/%d\n",10,31); }else if(month == 11,day > 30){ printf("DATE = %d/%d\n",11,30); }else if(month == 12,day > 31){ printf("DATE = %d/%d\n",12,31); }else{ printf("DATE = %d/%d\n",month,day); } } int main(int, char **){ MyDate today; today.changeMonth(12); today.changeDay(35); return 0; } それで、 初期化するコンストラクタなんですが、 void MyDate::Date~ のような感じでいいのでしょうか? argMonthとかargDayとかいらないですか?ただMonthとDayだけでいいでしょうか? print()のメンバ関数なんですが、条件式の中に組込むとメンバ関数がいらないんじゃないか、と思ってしまうのですが、条件式の最後のelse{~}の中身を入れればいいでしょうか? あと、today.changeMonth(12); today.changeDay(35); と入れると、12/-858993460とでてしまうのですが、 条件式が間違ってるんでしょうか? 質問が多くてすみません。 よろしければ、回答よろしくお願いします。

みんなの回答

回答No.5

> メンバ関数の中でメンバ関数を呼ぶにはどうしたらいいのでしょうか? > そのまま、changeDay(int argDay)を書いてもいいのでしょうか? 訊くまでもない。やってみりゃイッパツでわかる。

回答No.4

ダメダメです。 1. changeDay内でprintfするのに何の意味もない。 そこでやらにゃならんのはDayの調整。 2. changeMonth内でchangeDayを呼ばないと狂う。 # 5/31にchangeMonth(2)すると2/31になっちまう

CHAMPloock
質問者

補足

回答ありがとうございます。 メンバ関数の中でメンバ関数を呼ぶにはどうしたらいいのでしょうか? そのまま、changeDay(int argDay)を書いてもいいのでしょうか?

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

C++のコンストラクは ・クラス名と同じ名前 ・戻り値およびその型は「指定しない」。voidではありません です。 なので、プロトタイプは class MyDate { MyDate(); } です。 省略すれば、デフォルトのコンストラクタが用意されます。 コンストラクタの定義の中で明示的に呼び出さない限り、他のメソッドが使われるとはありません。 > void MyDate::Date(int argMonth,int argDay) > { > argMonth = 1; > argDay = 1; >} 仮引数 argMonth,argDayを通常のローカル変数として利用し、1を代入するだけのメソッドになっています。つまり「何もしない」と同じです。 > print()のメンバ関数なんですが、条件式の中に組込むとメンバ関数がいらないんじゃないか、と思ってしまうのですが、条件式の最後のelse{~}の中身を入れればいいでしょうか? 質問文から読みとれる仕様には 「changeDayで日付を表示する」 なんてものは含まれていません。現状で表示しているのは正しいのでしょうか? メンバ変数を(エラーチェックしつつ)設定するだけの仕様ではないですか? > //1~31が入力された場合のみ値を更新 > if(argDay >= 1 && argDay <= 31){ > day = argDay; >} 現状、 month=2の時でも changeDay(31)とすると、このifの条件は真になり、dayに31が設定されます。 これは条件3に違反しています。 その下のif文でひっかかりますが(カンマを修正したとして)、ただ表示するだけで、値は修正されません。 それから、条件4が実装されていません。 > if(month == 1,day > 31){ > printf("DATE = %d/%d\n",1,31); カンマが間違いなのは既出なのでおいとくとして。 自分で書いてて嫌にならなかったですか? changMonthに条件4を実装しようとすると、もう一回、ほぼ同じものをかかなければなりません。 こういうのは、同じ書き方でできる仕組みを考えるとずーっと楽になります。 例えば int lastDay(int month) メソッドとして、month月の最終日を返すものを用意すれば、このifの羅列が if ( day > lastDay(month) ) { エラー処理 } だけ済みます。また、changeMonthへの条件4の追加も、このメソッドで簡単にできます。

CHAMPloock
質問者

補足

わかりやすい回答ありがとうございます。 自分でも面倒だな、とは思ってたんですが、他の方法が思いつかなくって…^_^; それで、 int lastDay(int month) メソッドを参考にしたいのですが、 lastDayというのは、配列を使ったらいいでしょうか?

  • TT414
  • ベストアンサー率18% (72/384)
回答No.2

>if(month == 1,day > 31){ >printf("DATE = %d/%d\n",1,31); >}else if(month == 2,day > 28){ >printf("DATE = %d/%d\n",2,28); >}else if(month == 3,day > 31){ >printf("DATE = %d/%d\n",3,31); とありますが一行一文にこだわらずに if(month == 1,day > 31){printf("DATE = %d/%d\n",1,31);} else if(month == 2,day > 28){printf("DATE = %d/%d\n",2,28);} else if(month == 3,day > 31){printf("DATE = %d/%d\n",3,31);} としたほうが見やすい、分かりやすいと思いますがどうでしょう?

CHAMPloock
質問者

お礼

確かにこれなら中かっことかわかりやすいですね ありがとうございます(^u^)

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.1

>初期化するコンストラクタなんですが、 >void MyDate::Date~ >のような感じでいいのでしょうか? クラス名と同じ…なので、 void MyDate::MyDate() かと。 引数などには注意が必要でしょうけど。 >argMonthとかargDayとかいらないですか?ただMonthとDayだけでいいでしょうか? 引数で受け取ったモノを「メンバ変数」に代入するなりしないと意味がないと思いませんか? # 受け取った変数の内容だけ書き換えても無意味です。 あと、引数で受け取った内容が正しいものかどうかの確認も必要…でしょう。 # 初期化リストとかいろいろ手法がありますが…そちらはC++に詳しい方の回答に期待しておきます。 >print()のメンバ関数なんですが、条件式の中に組込むとメンバ関数がいらないんじゃないか、と思ってしまうのですが、条件式の最後のelse{~}の中身を入れればいいでしょうか? print()メンバ関数は、「表示するだけ」でいいのではないですか? changeMonth()/changeDay()メンバ関数で、渡された日付などが正しいか判定してメンバ変数に設定すればよいでしょう。 ……まぁ、無条件に受け入れてprint()メンバ関数で処理してもかまいませんけど。 # getMonth()/getDay()/getDate()とか追加した時に変な日付が渡されるけどそういうクラス設計であればいいだけのことですし。 >if(month == 1,day > 31){ if(month == 1 && day > 31) { と書きたいのではないですか? 「複数の条件」の書き方が想定とは違いますが…… >あと、today.changeMonth(12); >today.changeDay(35); >と入れると、12/-858993460とでてしまうのですが、 >条件式が間違ってるんでしょうか? 希望している >}else if(month == 12,day > 31){ に引っかからなかったのでしょう。 dayの値は不明ですしね。 コンストラクタで初期化していないからゴミが入っています。 今回は負数だったのでdayは31より小さかったのでしょう。

関連するQ&A