• ベストアンサー

F-BASIC ツェラーの公式 年月を入力してカレンダー表示

F-BASICの下記の問題がどうしても分からなくて困っています。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ツェラーの公式を使い、年と月を入力すればその月のカレンダーを以下の例のように表示するプログラムを作成せよ。ただし、ツェラーの公式は次のように与えられる。西暦年、月、曜日を y%,m%,d% とすると (y%+y%\4-y%\100+y%\400+(13*m%+8)\5+d%)MOD 7 ただし、m%<=2 のときは上の式で y%=y%-1,m%=m%+12 とおく。 この結果、0なら日曜、1なら月曜・・・、6なら土曜となる。 例 2003年6月 1 日 2 月 3 火 4 水 5 木 ・ ・ ・ ・ 28 土 29 日 30 月 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 一週間悩んだのですが、分かりませんでした。 どうかよろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.5

>たてに全部表示したいのですが 1日から月末日まで 1 火 2 水 ・・ ・・ 31 木 のように画面に出したいと言うことだと思いますが そうなりませんか。掲出のプログラムのロジック上はそうなると思いますが。 >半分で切れてしまいます。 半分で切れるとは? ----- 横にならべては。 '----月前半 for i=1 to 15 print i;" ";week$((K-i+1)mod 7); next i print '----月後半 for i=16 to days(M) print i;" ";week$((K-i+1)mod 7); next i print

その他の回答 (4)

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.4

#3です。補足に対して。 >F-BASICでどうしても作らないといけないのです だから、#3のVBAは旧DOS-BASICで書いたようなものですから、Cells()の行をPrint文に置きかえれば、どんなBASICでも動くはずです。 Cellsを除くと、Int、Mod,ForNextしか使ってないじゃないですか。 一応のロジックを紹介するために載せました。 (1)月末対応と(2)1,2月対応が入れてないので 、そっくりそのまま使えなくて申し訳ないですが、その点はお出来になると言うことでよろしく。

jalinkochie
質問者

補足

遅くなってしまい申し訳ありません。 あれから教えていただいたのを参考に 自分なりにやってみました。 ですがどうもうまくいきません。 たてに全部表示したいのですが、半分で切れて しまいます。そこで、スペースキーなどを 押して前半部分、後半部分を表示したいのですが どうすればよいでしょうか? 以下、imogasiさんのを参考にして 自分なりに考えたものです。 var Y as integer var M as integer var D as integer var K as integer var CURX as integer var cury as integer dim days(12) AS INTEGER for I=1 TO 12 read days(I) next I data 31,28,31,39,31,30,31,31,30,31,30,31 dim weeks(6) weeks$(0)="日" weeks$(1)="月" weeks$(2)="火" weeks$(3)="水" weeks$(4)="木" weeks$(5)="金" weeks$(6)="土" input "西暦年、月";Y,M if Y mod 4=0 and Y mod 100>0 or Y mod 400=0 then DAYS(2)=29 endif D=1 if M<3 then Y=Y-1 M=M+12 endif K=(Y+Y¥4-Y¥100+Y¥400+(13*M+8)¥5+D) mod 7 for i=1 to days(M) print i;week$((K-i+1)mod 7) next i DUMMY$=input$(1) end

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.3

サイトを参考にして作りました。 F-Basicが私にはなくて、エクセルVBAでやりました。 ツェラーの公式は完全には理解で来てないのですが 4年1回100年1回400年1回のグレゴリオ歴修正 が入っていることは判ります。 コーディングのご参考になれば幸いです。2003年 6,7,8月はあっています。 Sub test02() y = 2003 ' 2003 m = 8 '6 '------ c = Int(y / 100) y = y - c * 100 w1 = Int(c / 4) w2 = -2 * c w3 = Int(y / 4) w4 = y w5 = Int((26 * m + 16) / 10) + 14 '------ For d = 1 To 31 w6 = d Cells(d, "A") = d Cells(d, "B") = (w1 + w2 + w3 + w4 + w5 + w6) Mod 7 Next d End Sub Cells(・・)のところ2箇所はPrint文で置換えて見てください。 1,2月の13,14月にする部分は組み入れていません。月末日対応もしていません。For d=1 to 31 の部分。 http://www.mogami-wire.co.jp/unix/isholiday.htmlhttp://cluster.f7.ems.okayama-u.ac.jp/~t2/textinf/calendar.htmlを参考にしましたが 後者の式(誤り)を修正しました。w5の+14も私が入れました。

jalinkochie
質問者

お礼

ごめんなさい、F-BASICでどうしても作らないといけないのです・・・。 エクセルVBAがどんなものなのか知らないのですが 私なんかのために時間を割いてくださり、どうも ありがとうございました。感謝します。

  • ymmasayan
  • ベストアンサー率30% (2593/8599)
回答No.2

No.1のymmasayanです。 >>年、月、日 ですよね。 >いえ、入力するのは年と月だけなのです。 >年と月だけ入力してその年のその月の >カレンダー表示をするプログラムなんです。 問題で入力するのは年月ですが、ツェラーの公式には年月日が必要です。 だから日=1をプログラムで入れてやるのです。 >閏年や、月によって日数が違う時には >どうすればよいのでしょうか? これは自分で月の日数を決めてやるしかありません。 大の月、小の月、2月の3つに分けた処理をします。 うるう年については (1)西暦が400の倍数なら閏年。 (2)西暦が4で割リ切れて100で割リ切れなければ閏年。 ということから2月の日数が決まります。 注意して欲しいのはツェラーの公式の但し書きです。 「ただし、m%<=2 のときは上の式でy%=y%-1,m%=m%+12 とおく。」 これはツェラーの式の計算前に実行する必要があります。 少しだけ添削しておきます。 input "年";y% input "月";m% ここで日付けd%に1代入。 ここで但し書き実行・・IF文 N=y%+y%\4-y%\100+y%\400+(13*m%+8)\5+d%)MOD 7 ここで閏年の判定 ここでその月の日数の決定(S) ここでループをまわす.(For i=1to S) J=(N-1+I) MOD 7 Jを日本語の曜日に変換(表示) NEXT I end

jalinkochie
質問者

補足

添削してくださり、ありがとうございました。 ですが、BASIC初心者の私には難しく お恥ずかしながら、ヒントを頂いてもほとんど 分かりませんでした。 差し出がましいお願いなのですが、全部作ってくださると大変うれしいです。 よろしくお願いします。

  • ymmasayan
  • ベストアンサー率30% (2593/8599)
回答No.1

ヒントだけ。 >西暦年、月、曜日を y%,m%,d% とすると 年、月、日 ですよね。 2003年6月なら2003年6月1日を式で計算します。結果をNとします。 1日から30日までの日付をIとするとIに対する曜日(数字)Jは  J=(N-1+I) MOD 7となります。 あとはJで曜日テーブルを引けばいいでしょう。 曜日テーブルは0~6が日曜~土曜に対応するものです。

jalinkochie
質問者

補足

>年、月、日 ですよね。 いえ、入力するのは年と月だけなのです。 年と月だけ入力してその年のその月の カレンダー表示をするプログラムなんです。 お答えくださってありがとうございます。 しかし、私の能力不足で分かりません。 閏年や、月によって日数が違う時には どうすればよいのでしょうか? ↓できるところまで作ってみました。 よろしくお願いいたします。 input "年";y% input "月";m% y%+y%\4-y%\100+y%\400+(13*m%+8)\5+d%)MOD 7 (この間分かりません) d$=input$(1) end

関連するQ&A

  • 西暦・月からカレンダーを表示

    問題文 西暦・月を入力してカレンダーを表示するプログラムを作成せよ。 プログラム全体のことを考える。プログラムの流れとしては、つぎのようになるであろう。  (1)変数の宣言: プログラムの中で使う変数や配列等をすべてここに集めておく。          (2)入力: キーボードから、西暦年の値を読み取る ← scanf( ) 関数  1月から12月まで、以下を繰り返す。  (3)カレンダーの年・月の表示: (例えば、2008年1月 と表示)  (4)各曜日名の表示: 「日 月 火 水 木 金 土」と表示  (5)月の日数の算出: 月の最後の日を計算しておく。(*1~12月以外では誤りとすること)  (6)曜日の算出: 月の初めの日(ついたち)の曜日をツェラー公式で計算しておく。  (7)空列の表示: ついたちの前の空白部分を表示する ← for文 を利用。  (8)各日の表示: 月の各日を順に表示していく ← for文を利用          (土曜の後に改行を入れる) #include <stdio.h> int leapYear(int year) { if (year%400==0||(year%4==0 && year%100!=0)) { return 1; } else { return 0; } } int main(void) { int d,year,m,i; int day[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; /*1~12月までの各月の日数*/ printf("西暦を入力してください:"); scanf("%d",&year); printf("月を入力してください:"); scanf("%d",&m); if(m!=1 & m!=2 & m!=3 & m!=4 & m!=5 & m!=6 & m!=7 & m!=8 & m!=9 & m!=10 & m!=11 & m!=12)/*1~12月以外で日数を出そうとした場合*/ { printf("入力が誤っています。やりなおしてください。\n"); } else{ if (leapYear(year)==1)/*閏年の場合*/ { printf("%d年は閏年です。\n",year); day[1] +=1; } else/*閏年でない場合*/ { printf("%d年は閏年ではありません。\n",year); } i = (year+year/4 -year/100 +year/400 + ( 13*m+8 )/5 + 1) % 7; /*西暦~年・1~12月の1日の曜日について考える*/ printf("日 月 火 水 木 金 土\n"); (7)・・・ (8)・・・ } return 0; } 手順に沿ってやっていく課題なのですが(7)、(8)の部分の表現の仕方が良く分かりません。(求めた月の日数をカレンダー形式に表示する方法・1日の前に空白を入れる等) 過去の質問も見たのですが、いまいち理解できず・・・orz どなたかご教授お願いできないでしょうか・・・。

  • 曜日計算 公式 Floraの公式

    年月日を代入したら曜日を返す公式を自作しました。 もちろん、ツェラーの公式があるのは知っていたのですが。 誰か数学に詳しい方、私が自作した公式「Floraの公式」を、評価していただけたらなと思い、投稿させていただきました。 ブログを持っており、リンク先には証明および関連記事があります。 詳しい方からのアドバイスを待っております。 <証明> Floraの公式はY年M月D日の曜日を返す式である。 Floraの公式  Flr(Y,M,D) = R + [R/4] - [Y/100] + [Y/400] + [2.6*M + 2.7] + D - 1 (R = Y%28) 結果は以下のように定義する。  Flr(Y,M,D)%7 = 0: Sun., = 1: Mon., .= 2: Tue., = 3: Wed., = 4:Thu., = 5: Fri., = 6: Sat.   (ただし、M = 1,2はそれぞれM = 13,14としY = Y - 1とする。)   (RはYを28で割った余りである。R = Y%28) 式の証明は大きく以下のように分けられる(1,2月は、前年の13,14月とする。)。 A、同一世紀内での規則性を式にあらわす式を証明する。 B、世紀をまたがった規則性をあらわす式を証明する。 C、月毎の変化をあらわす式を証明する。 D、まとめ ただし、以下の点に注意。 ※0は日曜日、1は月曜日、2は火曜日、・・・である。 ※1年は3月から始まり、次の年の2月で終わることとし、1月を13月、2月を14月とする)、と考える。 ※20世紀は、1900~1999年のような間をさす。他の世紀も同様に。 以下の詳しい証明は、ブログに書いております。ブログ『心善淵』の関連記事:http://blog.goo.ne.jp/hihumizzz/c/3efe00080b47e4d6e59aac992ebb8891

  • 日付と曜日から、1週間前(7日前)の日付を算出するプログラム

    ツェラーの公式を用いて、日付(年月日)から曜日を算出する方法があります。 例えばY年M月D日の曜日は、下式で求められます。 (Y + Y/4 - Y/100 + Y/400 + (13*M + 8)/5 + D) % 7 *但し、1月・2月は、前年の13月・14月とする。 *答えは0=日曜~6=土曜 これを応用して(別に応用しなくても良いんですが・・・)日付と曜日から、1週間前の同一曜日の日付を求めるプログラムを考えております。 例) 入力:2005年9月21日、水曜日 出力(解):2005年9月14日 この例は非常に簡単に求められますが、完全汎用型のプログラムを考えております。 しかし、なかなか良い知恵が出ません!! どなたかご教示頂けると助かります。 よろしくお願いします。

  • c# ツェラーの公式を利用した計算方法

    利用言語はc# ソフトはvisual studio2022を利用しています。 年・月・日をそれぞれ入力し、ツェラーの公式を利用して曜日を出したいのですがやり方が分からず困っています。 分かる方がいらっしゃいましたらお力を貸していただけましたら幸いです。 曜日の判定をする部分は以下で実現したいです。 Console.WriteLine("{0}曜日", g[dayofweek]);

  • C言語 ツェラーの公式を使った曜日の計算

    ツェラーの公式を使い、年、月、日にちから曜日を表示するプログラムを作りました。 #include<stdio.h> main() { int y,m,d,x,z; printf("年、月、日にちの順に入力してください→"); scanf("%d%d%d",&y,&m,&d); if(m<2){ m=m+12; y=y-1; } x=y+y/4-y/100+y/400+(13*m+8)/5+d; z=x%7; switch(z){ case 0: printf("日曜日\n"); break; case 1: printf("月曜日\n"); break; case 2: printf("火曜日\n"); break; case 3: printf("水曜日\n"); break; case 4: printf("木曜日\n"); break; case 5: printf("金曜日\n"); break; case 6: printf("土曜日\n"); break; } } これを基本に、1582年10月5日以前の入力があったとき「エラー」と表示するにはどうすればいいですか? 解答お願いします。

  • C言語でのカレンダーの表示について質問です

    VisualStudioを使ってC言語でコンソールアプリケーションのカレンダーを作っています。 やりたいことは以下の通りです。 プログラムを起動すると、現在の月を中央に三ヶ月分のカレンダーを表示。 Lキーでカレンダー全体を一ヶ月前に変更 Rキーで一ヶ月後に変更 Dキーで三ヶ月前に変更 Uキーで三ヶ月後に変更 Aキーで一年前に変更 Bキーで一年後に変更 起動時にカレンダー表示するのはできているんですが、Rでカレンダーを進めていくと12月の次が13月、次が0月、その次が1月となってしまい、日付も上手いこと表示されません。 L,D,U,でも同じようになります。 また、A,Bで年を変えると日付が正確に表示されないです。 これらを正しく表示させる方法をご教授いただけますでしょうか。 #include <stdio.h> #include <conio.h> #include <time.h> #define KEY_ESC (0x1b) // エスケープ #define KEY_L (0x6c) // L #define KEY_D (0x64) // D #define KEY_R (0x72) // R #define KEY_U (0x75) // U #define KEY_A (0x61) // A #define KEY_B (0x62) // B time_t timer; // 現在の時刻 struct tm local; // 地方時 int curr_year; // 現在の年 int curr_mon; // 現在の月 int input; // どのキーが入力されたか int calendar[12][6][7]; // 月、最大の週、1週間 int year; // 年 int month; // 月 int day; // 日 int nweek; // その月が何周あるか int nday; // その月が何日まであるか int day_of_week; // その月が何曜日から始まるか void CalendarDisplay(void); void CalendarSet(void); void DayOfWeek(int, int, int); void NumOfDay(int); void KeyOperat(int); int LaepYear(int, int); int Zeller(int, int, int); int main(void) { CalendarDisplay(); while (1) { printf("ESCキーで終了\n\n"); input = _getch(); if(input == KEY_ESC) { break; } else if(input == KEY_L || input == KEY_D || input == KEY_R || input == KEY_U || input == KEY_A || input == KEY_B) { KeyOperat(input); } } return 0; } // カレンダーの表示 void CalendarDisplay(void) { // 現在時刻を取得 timer = time(NULL); // 地方時に変換 localtime_s(&local, &timer); // 現在の年 curr_year = local.tm_year + 1900; // 現在の月 curr_mon = local.tm_mon + 1; CalendarSet(); } // 当月とその±1の月を設定 void CalendarSet(void) { for (month = curr_mon-1; month <= curr_mon+1; month++) { // 12月を超えたら次の年に if(curr_mon > 12) { curr_mon = 1; month = 1; curr_year += 1; } // 1月を超えたら前の年に else if(curr_mon < 1) { curr_mon = 12; month = 12; curr_year -= 1; } // その月が何日まであるか求めて代入 nday = LaepYear(curr_year, month); // その月が何曜日から始まるか day_of_week = Zeller(curr_year, month, 1); nweek = 0; for (day = 1; day <= nday; day++) { calendar[month-1][nweek][day_of_week] = day; //printf("day-> %d ", day); if (++day_of_week == 7) { day_of_week = 0; nweek++; } } } DayOfWeek(month, curr_mon, curr_year); } // 月と曜日の表示 void DayOfWeek(int m, int cur_m, int cur_y) { for (m = cur_m-1; m <= cur_m-1; m++) { printf("%d%6d月%16d%6d月%16d%6d月\n" "日 月 火 水 木 金 土  " "日 月 火 水 木 金 土  " "日 月 火 水 木 金 土\n", cur_y, m, cur_y, m + 1, cur_y, m + 2); NumOfDay(&calendar[m-1]); } } // 日数の表示 void NumOfDay(int calendar[][6][7]) { int max_w = 0, nmon = 0, w = 0; // その月の最大週の間 for (max_w = 0; max_w < 6; max_w++) { // 3ヶ月分表示 for (nmon = 0; nmon < 3; nmon++) { for (w = 0; w < 7; w++) { if (calendar[nmon][max_w][w]) { printf("%2d ", calendar[nmon][max_w][w]); } else { printf(" "); } } printf(" "); } printf("\n"); } } // キー操作でカレンダーの表示を変える void KeyOperat(int input) { do { switch(input) { case KEY_L: curr_mon -= 1; break; case KEY_R: curr_mon += 1; break; case KEY_D: curr_mon -= 3; break; case KEY_U: curr_mon += 3; break; case KEY_A: curr_year -= 1; break; case KEY_B: curr_year += 1; break; default : input = !input; break; } } while(!input); CalendarSet(); } // うるう年の判定 int LaepYear(int y, int m) { const int num_day[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; if (m == 2 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) { return 29; } return num_day[m - 1]; } // ツェラーの公式から曜日を求める int Zeller(int y, int m, int d) { int dow;   // 1月と2月の場合、それぞれ前年の13月、14月とする if(m == 1 || m == 2) { y--; m = m + 12; } dow = (y + y/4 - y/100 + y/400 + (13*m+8)/5 + d) % 7; return dow; }

  • ツェラーの公式について

    最近ツェラーの公式を知ったのですが、その時に、 「ツェラーの公式は1582年10月15日(金)以降でのみ正しく判定出来ます。」 と書かれていました。 これは何故でしょうか? 1582年10月15日以前では、どのような不具合が出てくるのでしょうか? 分かる方教えてください。 よろしくお願いします。

  • エクセル【年月を入力→曜日に対応した日付を表示】

    以前自分で作ったのですが、すっかり忘れてしまいましたので、恥ずかしながらご回答いただければと思います。 a1に任意の西暦、b1に任意の月を入力するものとします。 2行目は、a2から右へ日月火水木金土日月・・・・と入力してあり、これは変えません。 (a2=日、b2=月、c2=火、d2=水、e2=木、f2=金、g2=土、h2=日・・・という具合です) 3行目に年月と曜日に対応した日付を表示したいのです。 例えば、2011年1月の1日が土曜日だとすると、「a1に2011」「b1に1」と入力した場合に、 a3からf3までは空白でg3から1日が表示されるようにしたいのですが。

  • カレンダーの処理が分かりません

    休みの日を判定しようと思います。 土曜日か日曜日なら曜日を表示させるプログラムです。 2005/6/26日は日曜日なのですが「日曜日」と表示されません。どこがいけないのでしょうか? public void day() { Calendar calendar = Calendar.getInstance(); int y = 2005; int m = 6; int d = 26; calendar.set(y,m,d); // 日曜日のとき if(calendar.get(calendar.DAY_OF_WEEK) == calendar.SUNDAY){ System.out.println("日曜日"); } // 土曜日のとき else if(calendar.get(calendar.DAY_OF_WEEK) == calendar.SATURDAY){ System.out.println("土曜日 } }

    • ベストアンサー
    • Java
  • 今、C言語の勉強をしていて、「西暦と月をscanfで入力し、”西暦●●

    今、C言語の勉強をしていて、「西暦と月をscanfで入力し、”西暦●●年の●月は●日です”というプログラムを完成させなさい」という問題がありました。 また、条件が「4の倍数で、かつ100の倍数でない場合か、400の倍数の場合は閏年である」また 「西暦が0以下のとき、月が1以下12以上の場合はエラーメッセージを表示させなさい。」というものです。 そこで、コーディングした結果、下記のようになりました。 #include <stdio.h> main() { int y,m,d; printf("西暦=");scanf("%d",&y); printf("月=");scanf("%d",&m); if(y<0 || d>1 && d<12) printf("エラーです。"); else if(m==1 || m==3 || m==5 || m==7 || m==8 || m==10 || m==12) d=31; printf("西暦%d年の%d月は%d日です。",y,m,d); else if(m==4 || m==6 || m==9 || m==11 ) d=30; printf("西暦%d年の%d月は%d日です。",y,m,d); else if(m==2 && y%4==0 && y%100>0 || y%400==0) d=29; printf("西暦%d年の%d月は%d日です。",y,m,d); else d=29; printf("西暦%d年の%d月は%d日です。",y,m,d); } これを、学校の先生が開発したコンパイラで文法チェックを施したところ、 「予約語elseは使用できません」と文法エラーがでました。 「else」は、if文のthen/elseの意味で利用したのにそういう風にとらえてくれませんでした。 また、字下げは適当にやっているだけですので気にしないでください。 これ、どこかおかしいところありますか・・・?

専門家に質問してみよう