アプリ版:「スタンプのみでお礼する」機能のリリースについて

問題文
西暦・月を入力してカレンダーを表示するプログラムを作成せよ。

プログラム全体のことを考える。プログラムの流れとしては、つぎのようになるであろう。
 (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
どなたかご教授お願いできないでしょうか・・・。

A 回答 (4件)

ツェラーの公式を使う際、1月・2月は前年の13月・14月とみなす、


という決まりがありませんでしたか?

> 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)

このif文、美しくないですね。それに、& じゃなくて && です。
もっと単純に、
if (m < 1 || 12 < m)
でいいんじゃないですか。
    • good
    • 0
この回答へのお礼

> 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)

このif文、美しくないですね。それに、& じゃなくて && です。
もっと単純に、
if (m < 1 || 12 < m)
でいいんじゃないですか。

>>ご指摘ありがとうございます。今度からは気をつけます。

お礼日時:2008/06/25 16:33

(7)より、(8)を先に考えた方が楽です。


まずは、1日が日曜日の場合を考えてみてください。
日~土まで表示するには1~7を表示します。
カレンダーの様にするには、土曜日にあたる7、14、21、28で次の行に移動し続けて数字を表示(7なら、次の行は8~)する方法を考えてください。
この部分ができると、次は1日を表示する位置を求めます。曜日を求める式はありますから、その曜日の前までは空白を表示していけばいいことになります。
そして、(8)の処理を日曜から1日が始まらない場合でも動作するように変更すればOKです。

それと
>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月以外で日数を出そうとした場合*/
は見難いので、if((m<1) || (12<m))のようにすべきです。
ちなみに「&」ではなく「&&」です
    • good
    • 0
この回答へのお礼

ご意見ありがとうございます。もう一度よく考えてみます。

お礼日時:2008/06/25 16:35

>(7)、(8)の部分の表現の仕方が良く分かりません。



 難しく考えていませんか。

 ・朔日の前に空白
 ・土曜( 6 )出力後改行

 だけですよね。
-------------------------------------
  i01Youbi = Zeller( year, m ); // 0-6

  for( i = 0; i < i01Youbi; i++ ) printf( "___" ); // 朔日の前に空白3つ▼×必要分(投稿上 _ としています)

  for( i = 1; i <= day[ m - 1 ]; i++ ){

    printf( "%3d", i ); // 3桁▲上と同じに

    if( 6 == ( ( i - 1 + i01Youbi ) % 7 ) ) printf( "\n" ); // 土曜出力後改行
  }
  printf( "\n" );
 (インデントに全角空白使用)
-------------------------------------
>day[ 1 ] += 1; 確かに 29 になるのですが、

 day[ 1 ] = 29; とした方が・・(今回はOKですが・・やがて?)。
    • good
    • 0
この回答へのお礼

#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 year,m,i,d;
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) || (12<m))/*1~12月以外で日数を出そうとした場合*/
{
printf("入力が誤っています。やりなおしてください。\n");
}

else
{
if (leapYear(year)==1)/*閏年の場合*/
{
printf("%d年は閏年です。\n",year);
day[1]=29; /*閏年の時は2月の日数が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");
d = i;

for(i = 0; i < d; i++) printf("☆");/*一日の前に空白を表示*/
for(i = 1; i <= day[ m - 1 ]; i++)
{
printf("%3d", i);
if(6 == ((i - 1 + d) % 7)) printf("\n");
}
printf("\n");
}
return 0;
}

アドバイスを踏まえてやったつもりです(☆は空白3つ)。プログラム実行結果表示もうまくいったのですが、何故か1月と2月だけ、ずれが発生します。
i01Youbi = Zeller( year, m );の部分を変に変えてしまったのが原因なのでしょうか?この部分だけ良く分からなかったので・・・

お礼日時:2008/06/25 17:00

> プログラム実行結果表示もうまくいったのですが、何故か1月と2月だけ、ずれが発生します。



それは「うまくいった」とは言いません。

> ツェラーの公式を使う際、1月・2月は前年の13月・14月とみなす、
> という決まりがありませんでしたか?

これへの対応は、どうなっていますか?
    • good
    • 0
この回答へのお礼

#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 year,m,i,d;
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) || (12<m))/*1~12月以外で日数を出そうとした場合*/
{
printf("入力が誤っています。やりなおしてください。\n");
}

else
{
if(m<=2)
{
i = ((year-1)+(year-1)/4 -(year-1)/100 +(year-1)/400 + ( 13*(m+12)+8 )/5 + 1) % 7;/*西暦~年、1月・2月の1日について*/
}
else
{
i = (year+year/4 -year/100 +year/400 + ( 13*m+8 )/5 + 1) % 7; /*西暦~年、3~12月の1日について*/
}

if (leapYear(year)==1)/*閏年の場合*/
{
printf("%d年は閏年です。\n",year);
day[1]=29; /*閏年の時は2月の日数が1増える*/
}

else/*閏年でない場合*/
{
printf("%d年は閏年ではありません。\n",year);
}

printf("日 月 火 水 木 金 土\n");
d = i;

for(i = 0; i < d; i++) printf(" ");/*一日の前に空白を表示*/
for(i = 1; i <= day[ m - 1 ]; i++)
{
printf("%3d", i);
if(6 == ((i - 1 + d) % 7)) printf("\n");
}
printf("\n");
}
return 0;
}

> ツェラーの公式を使う際、1月・2月は前年の13月・14月とみなす、
という決まりがありませんでしたか?

すみません・・・すっかり忘れていました。
上記のとおりsuncionさんの言うとおりやってみたら、1月と2月も問題なく表示できるようになりました!
貴重な時間を割いてもらって、お手数をおかけしました。そしてありがとうございました!

お礼日時:2008/06/25 21:07

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています