« そろそろオリジナルアプリをつくってみよう(その4) | メイン | Cocoaはじめの一歩+α 練習問題5と6 »

Cocoaはじめの一歩+α 練習問題4

Cocoaはじめの一歩というサイトの歩き方です。
Cocoaはじめの一歩にある練習問題を通じでXcodeとobjective-Cになじもうとする企画です。

では練習問題4をやって見ましょう。

この問題はアプリケーションの仕様を考える問題です。「春分の日の次の満月の後の最初の日曜日」(イースター)をいかにして計算するかがポイントです。いつもどおり自分で考えてみてください。

xillionはリストを使用する方法を考えつきました。
予めイースターの日をプログラムにもっていて、入力に応じて表示させます。
そうですね、ユーザーに日付を入力してもらい、次回のイースターを表示させましょう。

とすると、今回のプログラムでは日付の比較が必要そうです。
でも日付ってどうしましょう。
多分、cocoaにも日付型のデータタイプがある筈です。
NSDateと当てずっぽうでマニュアルをみたらクラスがありました。

比較の方法も書いてありますが、compare:メソッドのDiscussion(=参考)をみると、NSDateは秒未満のコンペアもするようで、そこまでの精度が不要なら、NSCalendarDateが使えるとのこと。
(実際NSDateではうまく動きませんでしたし、単に不等号だけでもだめでした。入力値や配列を日付に変換するところで何かありそうです。)

ところが、NSCalendarDateのマニュアルをみても比較を行うメソッドがありません。
どうすれば良いのでしょう。
NSCalendarDateは比較のためのメソッドはありませんが年、月、日、時などの要素を取り出すことが可能です。
これで比較はできそうですね。

イースターのリスト(配列)を用意して、入力した日付と比べていき、はじめてイースターリストの日付が大きくなったところが、次のイースターとなります。


wikipwdiaをみていたら、イースターを求める算式が乗っていたので、こっちの機能も取り込んでしまいました。
(アプリとしてはちょっとヘンです。まあ練習ということで)
この算式中に剰余が登場しますが、Cでは剰余を計算する演算子は%です。

解答です。


プログラムは次のイースターを取得するsearchEaster:アクションと、
その年のイースターを計算するcalcEaster:アクションです。
コメントを沢山いれたので解説はなしです。

#import "MAEaster.h" @implementation MAEaster - (IBAction)searchEaster:(id)sender {   //入力日付を取得→inputDate    //dateWithNaturalLanguageString:メソッドを使用しているので"next year" などの入力も可能   NSCalendarDate *inputDate =   [NSCalendarDate dateWithNaturalLanguageString:[dateField stringValue]];    //Easterリスト、配列の最後はnil   NSArray *easterday = [[[NSArray alloc] initWithObjects:     @"2007/4/8",     @"2008/3/23",     @"2009/4/12",     @"2010/4/4",     @"2011/4/24",     @"2012/4/8",     @"2013/3/31",     @"2014/4/20",     @"2015/4/5",     @"2016/3/27",     @"2017/4/16",     @"2018/4/1",     @"2019/4/21",     @"2020/4/12",     @"2021/4/4",     nil] autorelease] ;   //Easterリストから取得する日付に使用   NSCalendarDate *compDate ;   //出力日付用のフォーマットyyyy/m/d形式   NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc]   initWithDateFormat:@"%1Y/%1m/%1d" allowNaturalLanguage:YES] autorelease];   //出力する日付に使用   NSString *formattedDateString = nil ;   //Easterリストを廻す添字   int i;   //Easterリストの最大値、iの上限   int max =  [easterday count] ;   //出力用の文字列   NSString *message;   //Easterリストを始めからループ   for ( i = 0; i < max;i++) {     //Easterリストから日付を取得→compDate     compDate =  [NSDate dateWithNaturalLanguageString:[easterday objectAtIndex:i]];     //入力日付とEasterリストの年を比較     if ( [inputDate yearOfCommonEra] < [compDate yearOfCommonEra])     {       //Easterリストの方が大きい場合、       //compdataが次のEasterの日となるのでformattedDateStringにセット       formattedDateString = [dateFormatter stringFromDate:compDate];       break;        //入力日付とEasterリストのt月日を比較(年は同じ)     }  else if  (  ([inputDate yearOfCommonEra] == [compDate yearOfCommonEra])           && ([inputDate dayOfYear] <= [compDate dayOfYear]) )       {       //Easterリストの方が大きい場合、       //compdataが次のEasterの日となるのでformattedDateStringにセット       formattedDateString = [dateFormatter stringFromDate:compDate];       break;     }   }   if (formattedDateString != nil)  {     //formattedDateStringがセットされていれば次のEasterとして表示     message = @"Next Easter Day is " ;     message = [message stringByAppendingString:formattedDateString];       [msgField setStringValue:message];   } else {     //formattedDateStringがセットされていない場合は上限エラー     [msgField setStringValue:@"Limit Date is 2021/4/4"]; }

- (IBAction)calcEaster:(id)sender
{
  //メイアス・ジョーンズ・ブッチャーのグレゴリオ暦アルゴリズム(wikipedia)
  //入力した年→year

  int year = [yearField intValue];
  int a,b,c,d,e,f,g,h,i,k,l,m,mm,dd;
  a=year % 19;  b=year / 100;  c=year % 100;  d=b / 4;  e=b % 4;  i = c / 4;  k = c % 4;
  f=( b + 8 ) / 25;  g=( b - f + 1 ) / 3;  h=( 19 * a + b - d - g + 15 ) % 30;
  l = ( 32 + 2 * e + 2 * i - h - k ) % 7;  m=( a + 11 * h + 22 * l ) / 451;
  mm=( h + l - 7 * m + 114) / 31;  dd = (( h + l - 7 * m + 114) % 31) + 1;
  //結果を表示
  [msgField setStringValue:
  [NSString stringWithFormat:@"The EASTER Day is %d/%d/%d",year,mm,dd] ];
    }
@end

Exercise4.zip


ひとつ前の投稿は「そろそろオリジナルアプリをつくってみよう(その4)」です。
次の投稿は「Cocoaはじめの一歩+α 練習問題5と6」です。

トラックバック

このエントリーのトラックバックURL:
http://www.xillion.net/mova/mt-tb.cgi/295

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

About

2008年03月03日 22:09に投稿されたエントリーのページです。

メインページアーカイブページも見てください。

Powered by
Movable Type 3.34