今だけ人気マンガ100円レンタル特集♪

西暦、月、日(1900年1月1日以降対象)を入力して、曜日を求めるプログラムを考えています。
過去の質問なども参考にしたんですが、プログラムがうまく動かず困っています。
プログラム中コメントの日数を変える辺りに不備があるかと思い色々試しましたが、曜日がずれてしまいますし開始1900年1月1日も月曜なのに水曜と出力されます。
forやifの条件の記述がおかしいのでしょうか?
なにか根本的な所が欠如しているのでしょうか、回答をよろしくお願いします。
始めのgetsの所はあえてです。
#include<stdio.h>
#include<stdlib.h>

int main(void)

{
char ss[9],cop1[5],cop2[3],cop3[3];

int year,manth,day,aa,cc,i,f;

gets(ss);

ss[8] = 0;
cop1[4] = 0;
cop2[2] = 0;
cop3[2] = 0;

for(i = 0;i <= 3;i++){
cop1[i] = ss[i];
}
for(i = 0;i <= 1;i++){
cop2[i] = ss[i+4];
}
for(i = 0;i <= 1;i++){
cop3[i] = ss[i+6];
}
year = atoi(cop1);
manth = atoi(cop2);
day = atoi(cop3);

printf("%d年%d月%d日",year,manth,day);

for(f = 1900; f <= year; f++){  //閏年か平年で日数を変える
if((year%4) == 0 && year != 1900){
aa += 366;
}
else{
aa += 365;
}
}
if((year%4) == 0 && manth >= 3 ){//閏年かつ3月以降日数+1
aa += 1;
}

switch(manth){
case 1:
cc = (aa + day)%7;
break;
case 2:
cc = (aa + 31 +day)%7;
break;
case 3:
cc = (aa + 59 +day)%7;
break;
case 4:
cc = (aa + 90 +day)%7;
break;
case 5:
cc = (aa + 120 +day)%7;
break;
case 6:
cc = (aa + 151 +day)%7;
break;
case 7:
cc = (aa + 181 +day)%7;
break;
case 8:
cc = (aa + 212 +day)%7;
break;
case 9:
cc = (aa + 243 +day)%7;
break;
case 10:
cc = (aa + 273 +day)%7;
break;
case 11:
cc = (aa + 304 +day)%7;
break;
case 12:
cc = (aa + 334 +day)%7;
break;
}
switch(cc){
case 1:
printf(" (月)");
break;
case 2:
printf(" (火)");
break;
case 3:
printf(" (水)");
break;
case 4:
printf(" (木)");
break;
case 5:
printf(" (金)");
break;
case 6:
printf(" (土)");
break;
case 0:
printf(" (日)");
break;
}

return 0;

}

このQ&Aに関連する最新のQ&A

A 回答 (9件)

★追記。


・質問者さんのソースを元に書き直してみました。
 参考にして下さい。

#include <stdio.h>

// break 付きのキーワード
#define CASE  break;case
#define DEFAULT  break;default

// 西暦から閏年の判定
int FuncIsLeapYear( int year )
{
 if ( !(year % 3200) ) return 0;  // 平年(3200で割れる年)
 if ( !(year % 400) ) return 1;  // 閏年(400で割れる年)
 if ( !(year % 100) ) return 0;  // 平年(100で割れる年)
 if ( !(year % 4) ) return 1;  // 閏年(4で割れる年)
 return 0;       // 平年(それ以外の年)
}

// メイン関数
int main( void )
{
 static const char *table[] = { "日", "月", "火", "水", "木", "金", "土" };
 // 宣言
 int year = 0;
 int month = 0;
 int day = 0;
 int week = 0;
 // カウンタ
 int days;
 int i;
 
 // 年月日の入力
 scanf( "%04d/%02d/%02d", &year, &month, &day );
 // 1900年以降の日数を数える
 for ( days = 0, i = 1900 ; i < year ; i++ ){
  days += (FuncIsLeapYear(i) ? 366 : 365);
 }
 // 1月1日から日数を加える
 switch ( month ){
  CASE 1: days += 0;
  CASE 2: days += 31;
  CASE 3: days += 31 + 28;
  CASE 4: days += 31 + 28 + 31;
  CASE 5: days += 31 + 28 + 31 + 30;
  CASE 6: days += 31 + 28 + 31 + 30 + 31;
  CASE 7: days += 31 + 28 + 31 + 30 + 31 + 30;
  CASE 8: days += 31 + 28 + 31 + 30 + 31 + 30 + 31;
  CASE 9: days += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31;
  CASE 10: days += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30;
  CASE 11: days += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31;
  CASE 12: days += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30;
 }
 // 3月以降で閏年なら+1日
 if ( (month >= 3) && FuncIsLeapYear(year) ){
  days++;
 }
 // 入力した日付を加える
 days += day;
 // 曜日の計算
 week = (days % 7);
 // 表示
 printf( "year = %d\n", year );
 printf( "month = %d\n", month );
 printf( "day = %d\n", day );
 printf( "week = %s\n", table[week] );
 return 0;
}
以上。
    • good
    • 0

★アドバイス


>過去の質問なども参考にしたんですが、プログラムがうまく動かず困っています。
 ↑
 この質問を参考にしたのでしょうか?
 URL を貼り付けて欲しかったな。
・私も回答とかで過去に多数ソースを載せています。
 次のリンクを参考になると思いますけど。
 http://oshiete1.goo.ne.jp/qa3085731.html→『簡素で美しく記述するには・・・・』
 私の回答は No.2 です。
 閏年の判定関数は No.3 さんの方が見やすいです。
・この過去質問に
 (1)FuncIsLeapYear():西暦から閏年の判定関数
 (2)FuncGetDays():年月日から1月1日からの日数を取得
 の2つがあります。
 これを利用すれば楽に出来ますけど。
 下のそのサンプルを載せておきます。

サンプル:
// メイン関数
int main( void )
{
 // 宣言
 int year;
 int month;
 int day;
 int week;
 
 // 年月日の入力
 scanf( "%04d/%02d/%02d", &year, &month, &day );
 // 曜日の計算
 week = FuncGetDays( year, month, day );
 week %= 7;
 // 表示
 printf( "year = %d\n", year );
 printf( "month = %d\n", month );
 printf( "day = %d\n", day );
 printf( "week = %s\n", &"日\0月\0火\0水\0木\0金\0土"[week * 3] );
 return 0;
}

その他:
・上記のサンプルの FuncIsLeapYear()、FuncGetDays() 関数は
 http://oshiete1.goo.ne.jp/qa3085731.html→『簡素で美しく記述するには・・・・』
 の回答 No.2 の載せた関数です。コピー&ペーストしてソースに取り込んで下さい。
・あとサンプルでは 1900年1月1日以降かどうかの判定はしていません。
 単純に西暦1年1月1日からの通算日数を FuncGetDays() 関数で求めてから 7 で
 割ったあまりが曜日の 0~6 になるから問題はない。
・ただし西暦1年1月1日を入力しても正しい曜日は返らない。
 これは回答者 No.6 さんの回答でちょっと書かれていますが、ユリウス暦、グレゴリオ暦
 を判断して曜日を計算していないからです。
 このため FuncGetDays() 関数で求めた通算日数は西暦1年1月1日からの日数ですが
 今のグレゴリオ暦に合わせているためにユリウス暦での曜日は正しく計算できないのです。
・また、日本と海外の国ではユリウス暦からグレゴリオ暦に切り替わった年代が異なっています。
 このためユリウス暦に完全対応するには『国』を指定する必要があります。もしくは日本限定。
・以上。今後のカレンダー・プログラムの参考に。

参考URL:http://oshiete1.goo.ne.jp/qa3085731.html
    • good
    • 0

#6 です.ちょっと訂正します.



> // dayNumber ← グレゴリオ暦0年3月1日を第1日とする通算日数
> dayNumber = (365 * year + nDaysSinceMarch1st[month - 3] + day)
>       + floor((double)year / 4)
>       - floor((double)year / 100)
>       + floor((double)year / 400);

これだと INT_MIN≦year≦INT_MAX の範囲をフルに使えないので,
次のように変更します.

 dayNumber = nDaysSinceMarch1st[month - 3] + day
       + 365.0 * year
       + floor((double)year / 4)
       - floor((double)year / 100)
       + floor((double)year / 400);
    • good
    • 0

偶然ですが私も最近,昔考えた高速日付計算プログラムを


整理しているところなので参加します.(笑)

次のプログラムは紀元前 (年≦0) の日付でも計算できます.
(ただし西暦0年=紀元前1年である点に注意.)

計算可能な日付の範囲は,INT_MIN≦年≦INT_MAX です.
したがって int が32ビットならば,西暦 2,147,483,648 年問題
および西暦紀元前 2,147,483,649 年問題があります.(笑)


#include <assert.h>
#include <stdio.h>
#include <math.h>

/*--------------------------------------------------------------------------
通日 (通算日数) の基準日 (epoch) を表す定数
(グレゴリオ暦0年3月1日(水)を第1日とする通日)
--------------------------------------------------------------------------*/
// ユリウス日 (基準日時:-4713/11/24(月) 12:00 UTC)
#define EPOCH_JD    (-1721118.5) // 12:00 UTC
#define EPOCH_CJD   (-1721119)  // 00:00 UTC (Chronological Julian Day)

// 修正ユリウス日 (基準日時:1858/11/17(水) 00:00 UTC)
#define EPOCH_MJD   678882

// UNIX Time (C言語の time_t 型,基準日時:1970/01/01(木) 00:00 UTC)
#define EPOCH_UNIXTIME 719469

// Microsoft Excel 日付のシリアル値
// 基準日は 1900/01/01(月) ということになっているが,
// Excel では1900年 (平年) が閏年として扱われるため,事実上は次のとおり.
#define EPOCH_19000101 693902 // 基準日:1900/01/01(月),1900年2月以前の日付の場合
#define EPOCH_18991231 693901 // 基準日:1899/12/31(日),1900年3月以後の日付の場合

/*--------------------------------------------------------------------------
機能 :グレゴリオ暦 → 通日変換
    グレゴリオ暦 year 年 month 月 year 日を,
    所定の基準日を第0日とする通日 (通算日数) に変換する.
入力 :(1) (year, month, day):日付 (グレゴリオ暦).
    (2) epoch:グレゴリオ暦0年3月1日(水)から基準日までの日数 (EPOCH_*).
戻り値:epoch を基準日とするグレゴリオ暦 year 年 month 月 year 日の通日.
--------------------------------------------------------------------------*/
double DateToDayNumber(int year, int month, int day, double epoch)
{
 // 3月1日を第0日とする,3~14月1日の通算日数.
 // (1~2月は前年の13~14月として扱う.)
 static const unsigned short nDaysSinceMarch1st[12] = {
  0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337
 };

 double dayNumber;

 assert((1 <= month) && (month <= 12));
 assert((1 <= day) && (day <= 31));

 // 計算の都合上,year年1~2月は,(year-1)年13~14月として扱う.
 if(month < 3) {
  month += 12;
  year--;
 }

 // dayNumber ← グレゴリオ暦0年3月1日を第1日とする通算日数
 dayNumber = (365 * year + nDaysSinceMarch1st[month - 3] + day)
       + floor((double)year / 4)
       - floor((double)year / 100)
       + floor((double)year / 400);

 return dayNumber - epoch;
}

/*--------------------------------------------------------------------------
機能 :通日から曜日を求める.
入力 :(1) dayNumber:通日.
    (2) sunday:任意の日曜日の通日.
戻り値:dayNumber の曜日を表す文字列.
--------------------------------------------------------------------------*/
const char *DayOfWeek(double dayNumber, double sunday)
{
 static const char * const dayOfWeek[7] = {
  "日", "月", "火", "水", "木", "金", "土"
 };

 dayNumber -= sunday;
 return dayOfWeek[(int)(dayNumber - floor(dayNumber / 7) * 7)];
}

/*--------------------------------------------------------------------------
機能 :DateToDayNumber() のテスト.
--------------------------------------------------------------------------*/
void DateToDayNumberTest(void)
{
 double dayNumber;
 int year, month, day;
 char line[1024];

 for(;;) {
  fprintf(stderr, "year/month/day: ");
  if(fgets(line, sizeof(line), stdin) == NULL) break;
  if((sscanf(line, "%d/%d/%d", &year, &month, &day) != 3) ||
    (month < 1) || (month > 12) || (day < 1) || (day > 31)) {
   fprintf(stderr, "日付が無効です.\n");
  } else {
   dayNumber = DateToDayNumber(year, month, day, 0);
   printf("%d/%02d/%02d(%s)\n",
       year, month, day, DayOfWeek(dayNumber, (double)5));
   printf(" 1900/01/01(月)の%.16G日後\n", dayNumber - EPOCH_19000101);
   printf(" ユリウス日:%.16G\n", dayNumber - EPOCH_JD);
   printf(" 修正ユリウス日:%.16G\n", dayNumber - EPOCH_MJD);
   printf(" UNIX Time (time_t):%.16G\n",
       (dayNumber - EPOCH_UNIXTIME) * (60 * 60 * 24));
  }
 }
}

/*--------------------------------------------------------------------------
--------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
 DateToDayNumberTest();
 return 0;
}

参考URL:http://www5d.biglobe.ne.jp/~noocyte/Programming/ …
    • good
    • 0

time.h系のCの標準ライブラリを使うべきですね。



Cygwinで確認しました。

まず、struct tm に年月日をいれて
次に time_t に変換(1900年年頭からの秒数)
もいちど time_t から strut tm に戻せば
曜日が設定されます。


#include <time.h>
#include <stdio.h>

int main( void )
{
struct tm when;
time_t when_t;
int input_year, input_month,input_day;
printf("time_tの長さ%02d\n",sizeof(time_t));//time_tのサイズを確認

memset(&when,0,sizeof(struct tm));
printf("年月日を8桁で入力してください:-->");
scanf("%04d%02d%02d",&input_year,&input_month,&input_day);
when.tm_mday = input_day;
when.tm_mon = input_month -1;
when.tm_year = input_year - 1900;

if ((when_t = mktime(&when)) != (time_t)-1)
{
localtime_r(&when_t,&when);
switch(when.tm_wday)
{
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;
default:
printf("入力ミスです\n");
}
}
else
printf("入力ミスです\n");

}



実際には、2038年問題がないよう、64bit化されたtime_tの処理系で書き直したらよいと思います。

参考URL:http://msdn2.microsoft.com/ja-jp/library/w4ddyt9h(VS.80).aspx
    • good
    • 0

windowsなら



GetLocalTime 現在のローカル日時を取得します。

VOID GetLocalTime(
LPSYSTEMTIME lpSystemTime // システム日時
);

SYSTEMTIME構造体のメンバwDayOfWeekが曜日
Sunday = 0
Monday = 1
Tuesday = 2
Wednesday = 3
Thursday = 4
Friday = 5
Saturday = 6
    • good
    • 0

> 入力した年月日までの総日数



サンプルコードです。たぶん、合っていると思います。

#include <stdio.h>

int isLeap(int y)
{
  // 閏年かどうかの判定
  return y % 4 == 0 && y % 100 != 0 || y % 400 == 0;
}

int main(void)
{
  int y, m, d, yy, mm, days;
  int mdays[2][13] = {
    { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
    { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
  };
  
  // 年月日の入力
  do {
    printf("年 > "), scanf("%d", &y);
  } while (y < 1900);
  
  do {
    printf("月 > "), scanf("%d", &m);
  } while (m < 1 || 12 < m);
  
  do {
    printf("日 > "), scanf("%d", &d);
  } while (d < 1 || mdays[isLeap(y)][m] < d);
  
  // 前年までの通算日数
  for (days = 0, yy = 1900; yy < y; yy++)
    days += 365 + isLeap(yy);
  
  // 当年前月までの通算日数
  for (mm = 0; mm < m; mm++)
    days += mdays[isLeap(y)][mm];
  
  // 当日までの通算日数
  days += d;
  printf("1900年1月1日~%d年%d月%d日の日数:%d\n", y, m, d, days);
  return 0;
}

(注)インデントのため、全角空白を使っています。
    • good
    • 0
この回答へのお礼

2次元配列を使ったり、do-whileにもこんな使い方があるんですね。
サンプルまで書いて頂いてありがとうございました。

お礼日時:2007/08/13 23:24

最初に日数を加算するループの終了条件が f <= year となっていますよね


これだと 入力された年1年分を加算することになりませんか
そうなると翌年の日付を算出となって食い違いますよね
    • good
    • 0
この回答へのお礼

返信ありがとうございます。
(year - 1)という事でしょうか。。
参考にしてがんばります。

お礼日時:2007/08/13 23:15

「Zellerの公式」でググってみてください。

    • good
    • 0
この回答へのお礼

返信、有難うございます。
先ほどから調べているおりに目にはしていたのですが、ここまで便利な公式だとは・・・。当然の様にプログラムは動いてくれました。
ただ、ツェラーの公式で求める事の出来た入力した年月日までの総日数を(閏年も考慮して)自分で計算したいのです方法は沢山あるきもしたのですが、力及ばずなにか簡潔な方法があれば、助言頂きたいと質問しています。
重ね重ねすいませんが、お願いします。

お礼日時:2007/08/13 21:04

このQ&Aに関連する人気のQ&A

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

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

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q曜日を求めるプログラムはどうやるの?

ただいま、C言語に苦戦中です。教えてください
2001年の月日の入力データから、曜日を求めるプログラム。
(実行結果例)
月を入力してください: 9↓
日を入力して下さい : 15↓

9月15日は土曜日です。

Aベストアンサー

またまたarthurです。

1月~12月までの各月の日数を12コの配列に入れ、
1月から入力してもらった月の1つ前の月までの日数を合計します。
例)9月と入力された場合
1月の日数(31日)+2月の日数(28日)+・・・+8月の日数(31日)
さらに入力された日にち分を加算します。
例)15日と入力された場合
1月~8月の合計日数+15日
その合計の値をさらに7(1週間=7日)で割ります。
7で割った余りの数字によって曜日を割り当てます。
1月1日(月)が最初なので、余りが1の時月曜日とすると、余りが2の時は・・・

と、まぁ、ヒントはここまでです^^;
後は自分の力でがんばってください。

Q(C言語)西暦年月日を入力して、その日の曜日を表示させるプログラムを試したのですが…

西暦年月日を入力して、その日の曜日を表示させるプログラムを作りたいのですが、とりあえず、やってみましたが…

int main(void)
{

int i,y,m,d,dy,dw;

int D[]={0,31,28,31,30,31,30,31,31,30,31,30,31};

printf("Year?");

scanf("%d",&y);

printf("Month?");

scanf("%d",&m);

printf("Day?");

scanf("%d",&d);

for(i=0;i<=m-1;i++){
dy = d + D[i] ;
}

if(m>=3){
if(y % 4 == 0){
if(y % 400 == 0){
dy = dy + 1 ;
}
else if(y % 100 ==0){
dy = dy ;
}
else{
dy = dy + 1 ;
}
}

else if(y % 4 == 1 || y % 4 == 2 || y % 4 == 3 ){
dy = dy ;
}
}
dw = (dy -1 + ( y + ( y - 1 )/4 - ( y - 1 )/100 + ( y - 1 )/400))%7 ;

if (dw == 0) printf("Sunday\n");
else if (dw == 1) printf("Monday\n");
else if (dw == 2) printf("Tuesday\n");
else if (dw == 3) printf("Wednesday\n");
else if (dw == 4) printf("Thursday\n");
else if (dw == 5) printf("Friday\n");
else if (dw == 6) printf("Saturday\n");

return 0 ;

}
このプログラムを各年の1月1日~2月28日で試してみると、うまくいくのですが、3月1日に入るとなぜかうまく働いてくれません。(ちなみに2005年の11月では偶然うまくいっています。)その理由が分からないのでどなたか教えてください。ちなみに、この一連のプログラムを行うにはもっと簡単に行える関数というかコマンド?みたいなものがあるようですが、基本的に各年の1月1日を、
(y+(y-1)/4-(y-1)/100+(y-1)/400)%7で(0:Sunday~)、同年の○月○日は1月1日から△日経過しているという考え方で、曜日を割り出すプログラムにしなければならないといけないので、注文が多いですがよろしくお願いします。

西暦年月日を入力して、その日の曜日を表示させるプログラムを作りたいのですが、とりあえず、やってみましたが…

int main(void)
{

int i,y,m,d,dy,dw;

int D[]={0,31,28,31,30,31,30,31,31,30,31,30,31};

printf("Year?");

scanf("%d",&y);

printf("Month?");

scanf("%d",&m);

printf("Day?");

scanf("%d",&d);

for(i=0;i<=m-1;i++){
dy = d + D[i] ;
}

if(m>=3){
if(y % 4 == 0){
if(y % 400 == 0){
dy = dy + 1 ;
}
else if(y % 100 ==0){
dy = dy ;
}
e...続きを読む

Aベストアンサー

プログラムのおかしいところについては#1の回答のとおりです。
したがって、
>int D[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
これを
>int D[]={0,31,59,90,120,151,181,212,243,273,304,335};
>//各月の前月までの年初からの日数
として、
>for(i=0;i<=m-1;i++){
> dy = d + D[i] ;
>}

>dy = d[m-1] + d;
とするという解法もあります。あらかじめ足しておいてはいけないということはないでしょう。

ただ、標準関数に日付の関数はあります。
もちろん制限はあって、time_tのサイズが32bit(=signed long int)の場合、1901年12月14日05:45:52~2038年1月19日12:14:07の間だけが正常に動作するようになっていますし、上記のアルゴリズムとは違って1970年1月1日00:00:00を基準とした秒数をもとにして計算しているため、今回は利用できませんね。

ところで、
> ちなみに2005年の11月では偶然うまくいっています。
の理由について回答が出ていませんが、それは、2005年1月と2005年10月がたまたま同じ曜日で始まっていてかつ、1月と10月が同じ日数(31日)だからです。

プログラムのおかしいところについては#1の回答のとおりです。
したがって、
>int D[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
これを
>int D[]={0,31,59,90,120,151,181,212,243,273,304,335};
>//各月の前月までの年初からの日数
として、
>for(i=0;i<=m-1;i++){
> dy = d + D[i] ;
>}

>dy = d[m-1] + d;
とするという解法もあります。あらかじめ足しておいてはいけないということはないでしょう。

ただ、標準関数に日付の関数はあります。
もちろん制限はあって、time_tのサイズが32bit...続きを読む

Q万年カレンダーのC言語プログラムを教えてください

西暦年と月を入力すると、その年月のカレンダーが出てくる万年カレンダーのC言語プログラムを教えてください!お願いします!

Aベストアンサー

>ありがとうございます。さっそくプログラムを動かしてみました。でも第一週と第二週の日付がうまくつながっていないです。これはどうしてでしょうか?

ごめんなさい。
htmlの半角スペースを連続して書くと1個にされてしまう事を忘れていました。
下から7行目の
printf(" ");
の半角スペース1個は半角スペース3個にしてください。

QC言語でのカレンダー作成

今、C言語でカレンダーを表示させるプログラムを作成しています

西暦と月を入力すると、その年、その月の1ヶ月分のカレンダーが表示されるプログラムを作りました

そこで、次は入力した月から3ヶ月分のカレンダーを表示させるプログラムを作成したいのですが、どなたか教えてくださいませんか?

配列を使う方法や文字列など色々な方法があると伺って、どの方法が作りやすいのかわからないんです・・・

borland c を使用しています

Aベストアンサー

こんにちは。

前提として、作成するプログラムがコンソールアプリで、コンソール画面
にカレンダーを表示する場合ですが。。。
※以下は、あくまで一例です。

■縦方向に並べて表示する場合
※こちらは、#1さんの言われるように、単純に作成済みの1ヶ月カレンダー
 表示プログラムを、3回呼ぶだけで良いと思います。

1)既に作成済みのカレンダー表示を行うプログラムを関数化します。
  例)
  void DispMonth( int nYear, int nMonth );
   int nYear  : カレンダーの年
   int nMonth : カレンダーの月

2)入力された[年]、[月]を基準にして、forループなどで、[月]及び[年]を
  変えながら、1)の関数を呼出す。

 入力された[月]を中央にして、前後3ヶ月分のカレンダーを表示する場合、
 ================================================
 int nYear, nMonth;
 int m, nYY, nMM;
 nYear = 2010;  /* ←入力[年]とします */
 nMonth = 11;   /* ←入力[月]とします */
 /* 月単位のループ処理 */
 for ( m=nMonth-1; m<=nMonth+1; ++m ) {
   nYY = nYear;
   nMM = m;
   if ( nMM < 1 ) {
     nMM += 12;
     nYY--;
   }
   else if ( nMM > 12 ) {
     nMM -= 12;
     nYY++;
   }
   DispMonth( nYY, nMM );
   /* 必要であれば、ここで空白行などを出力し間隔を調整する */
 }
 ================================================
 のような処理になると思います。

■横方向に並べて表示する場合
※こちらの場合は、少し工夫が必要になります。

1)まず、作成済みのカレンダー表示を行うプログラムを組み直して、週単位
  (第1週~第6週)で表示を行う関数にします。
  例)
  void DispWeek( int nYear, int nMonth, int nWeek );
   int nYear  : カレンダーの年
   int nMonth : カレンダーの月
   int nWeek : 週単位のインデックス(1~6)
 ※出力の際、行末には改行を付加しないようにしておきます。
 ※週インデックスが、その月の週の数を越えた場合は、空白(スペース等)
  を出力するようにしておきます。

2)入力された[年]、[月]を基準にして、forループなどで、[月]、[年]、及び、
  [週のインデックス]を変えながら、1)の関数を呼出す。

 入力された[月]を中央にして、前後3ヶ月分のカレンダーを表示する場合、
 ================================================
 int nYear, nMonth;
 int m, nYY, nMM, nWeek;
 nYear = 2010;  /* ←入力[年]とします */
 nMonth = 11;   /* ←入力[月]とします */
 /* 必要であれば、ここで年、月、及び、曜日名などの表示を行う */
 ~~~
 /* 週単位のループ処理 */
 for ( nWeek=1; nWeek<=6; ++nWeek ) {
   /* 月単位のループ処理 */
   for ( m=nMonth-1; m<=nMonth+1; ++m ) {
     nYY = nYear;
     nMM = m;
     if ( nMM < 1 ) {
       nMM += 12;
       nYY--;
     }
     else if ( nMM > 12 ) {
       nMM -= 12;
       nYY++;
     }
     DispWeek( nYY, nMM, nWeek );
     /* 必要であれば、ここでスペースなどを出力し間隔を調整する */
   }
   /* ここで改行を出力する */
 }
 ================================================
 のような処理になると思います。

※GUIアプリの場合でも、基本的に月毎に表示位置をずらすようにすれば良い
 と思います。

以上です。

こんにちは。

前提として、作成するプログラムがコンソールアプリで、コンソール画面
にカレンダーを表示する場合ですが。。。
※以下は、あくまで一例です。

■縦方向に並べて表示する場合
※こちらは、#1さんの言われるように、単純に作成済みの1ヶ月カレンダー
 表示プログラムを、3回呼ぶだけで良いと思います。

1)既に作成済みのカレンダー表示を行うプログラムを関数化します。
  例)
  void DispMonth( int nYear, int nMonth );
   int nYear  : カレンダーの年
   int nMonth : カレン...続きを読む

Qカレンダーのプログラムについて

三次元配列を使い、その年を入力すると一年分のカレンダーが出力するC言語のプログラムを教えてください。
それで、一ヶ月を六週として数字が当てはまらない所には「0」が入るようにして、後で「0」を空白に変えるようにして、1月の第1週が出力された後、2月の第1週、3月の第1週、1月の第2週、2月の第2週・・・・・と順に表示させるようなプログラムです。
出力結果は横に三か月分、縦に四か月分が出力される(下記)ようにしたいのですが、よろしくお願いします。

出力結果
      ・・・年
   1月  2月  3月
   4月  5月  6月
   7月  8月  9月
   10月  11月  12月

Aベストアンサー

これは何かの演習問題ですか?
他人のプログラムを見るのも勉強と思いますので参考プログラムを書きますが、何をやっているかは理解して下さいね。(全角スペースを使っています)
#include <stdio.h>

int main(void) {
 int i,j,k;
 int cal[12][6][7];
 int mon[12]={31,28,31,30,31,30,31,31,30,31,30,31};
 int year,weekday,day;
 
 scanf("%d",&year);
 for (i=0; i<12; i++) for (j=0; j<6; j++) for (k=0; k<7; k++) cal[i][j][k]=0;
 /* うるう年判定 */
 if (((year%4==0)&&(year%100!=0))||(year%400==0)) mon[1]=29; else mon[1]=28;
 /* 1月1日の曜日 */
 weekday=((year-1)+(year-1)/4-(year-1)/100+(year-1)/400+(13*13+8)/5+1)%7;
 /* 計算 */
 day=1;
 for (i=0;i<12;) {
  for(j=0;j<6;) {
   cal[i][j][weekday++]=day++;
   if (weekday==7) {weekday=0; j++;} /* 次の週 */
   if (mon[i]<day) {i++; day=1; break;} /* 次の月 */
  }
 }
 /* 表示 */
 for (i=0;i<12;i+=3) {
  printf("     %2d月          %2d月          %2d月\n",i+1,i+2,i+3);
  for (j=0; j<6; j++) {
   for (k=0; k<7; k++) if (cal[i][j][k]==0) printf("  "); else printf("%2d ",cal[i][j][k]);
   printf("  ");
   for (k=0; k<7; k++) if (cal[i+1][j][k]==0) printf("  "); else printf("%2d ",cal[i+1][j][k]);
   printf("  ");
   for (k=0; k<7; k++) if (cal[i+2][j][k]==0) printf("  "); else printf("%2d ",cal[i+2][j][k]);
   printf("\n");
  }
  printf("\n");
 }
 return 0;
}

これは何かの演習問題ですか?
他人のプログラムを見るのも勉強と思いますので参考プログラムを書きますが、何をやっているかは理解して下さいね。(全角スペースを使っています)
#include <stdio.h>

int main(void) {
 int i,j,k;
 int cal[12][6][7];
 int mon[12]={31,28,31,30,31,30,31,31,30,31,30,31};
 int year,weekday,day;
 
 scanf("%d",&year);
 for (i=0; i<12; i++) for (j=0; j<6; j++) for (k=0; k<7; k++) cal[i][j][k]=0;
 /* うるう年判定 */
 if (((year%4==0)&&(year%...続きを読む

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

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

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

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

プログラム全体のことを考える。プログラムの流れとしては、つぎのようになるであろう。
 (1)変数の宣言: プログラムの中で使う変数や配列等をすべてここに集めておく。        
 (2)入力: キーボードから、西暦年の値を読み取る ← scanf( ) 関数
 1月から12月まで、以下を繰り返す。
 (3)カレンダーの年・月の表示: (例えば、2008年1月 と表示)
 (4)各曜日名の表示: 「日 月 火 水 木 金 土」と表示
 (...続きを読む

Aベストアンサー

>(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ですが・・やがて?)。

>(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...続きを読む

QC言語での万年カレンダーのソースコートを教えてもらったのですが意味がわ

C言語での万年カレンダーのソースコートを教えてもらったのですが意味がわからないところがあります


#include <stdio.h>

int weekday(int y,int m,int d)
{
if ( m < 3 ){
m += 12 ;
y -- ;
}

return (y+y/4-y/100+y/400+(m*13+8)/5+d)%7 ;
}

int main()
{
int y,m,d,sw,ew ;

printf("年 : ");
scanf("%d",&y);

printf("月 : ");
scanf("%d",&m);

sw = weekday(y,m,1);
ew = weekday(y,m+1,1);

if ( sw <= ew ){
ew = ew - sw + 28 ;
}
else {
ew = 35 - sw + ew ;
}

printf("%4d / %d\n",y,m);
printf("日 月 火 水 木 金 土");
for (d=0 ;d<37 ;d++){

if (!(d%7)){
printf("\n");
}

if ( d < sw || d >= ew+sw ){
printf(" ");
}

else {
printf("%2d ",d-sw+1);
}
}
return 0 ;
}

sw = weekday(y,m,1);
ew = weekday(y,m+1,1);
のところから下の部分なのですがどういう場合分けをしているのですか?
一部分でもいいので教えていただけるとありがたいです。

C言語での万年カレンダーのソースコートを教えてもらったのですが意味がわからないところがあります


#include <stdio.h>

int weekday(int y,int m,int d)
{
if ( m < 3 ){
m += 12 ;
y -- ;
}

return (y+y/4-y/100+y/400+(m*13+8)/5+d)%7 ;
}

int main()
{
int y,m,d,sw,ew ;

printf("年 : ");
scanf("%d",&y);

printf("月 : ");
scanf("%d",&m);

sw = weekday(y,m,1);
ew = weekday(y,m+1,1);

if ( sw <= ew ){
ew = ew - sw + 28 ;
}
else {
ew = 35 - sw + ew ;
}

printf("%4d / %d\n",y,m);
printf...続きを読む

Aベストアンサー

曜日を0~6として
weekdayは指定した年月日から曜日を求める関数
swは当月の1日の曜日
ewは翌月の1日の曜日から当月の日数に変換しています。
dは月曜日からの通しのカウントですね
dがsw~sw+ewの範囲が当月の日付になります。
日付はswの分だけずれているのでマイナスして表示しています。

2010/06の場合
sw=2,ew=4
ew=4-2+28 = 30
dが2~32の間は日付を表示する

2010/07の場合
sw=4,ew=0
ew=35-4+0 = 31
dが4~35の間は日付を表示する

質問の部分は当月と翌月の曜日の前後による月の日数計算の場合分けですね
カレンダーを見ながらなら理解し易いと思います。

QカレンダーのC言語プログラムを教えてください!

西暦年と月を入力すると、その年月のカレンダーが出てくる万年カレンダーのC言語プログラムを教えてください!

その出力結果が
2***年 *月
月 火 水 木 金 土 日 月 火 水 木 金 土 日
1 2 3 4 5 6 7 8 9 10 11 12 13 14
15 16 17 18 19 20 21 22 23 24 25 26 27 28
29 30 31

というように二週間ごとに表示するもので、
うるう年の判別ができるものになるようにしたいのですが。
年=n月=g
で入力するものを作りたいんです。
よろしくお願いします!!!(>_<)

Aベストアンサー

なんとなく作りました。
入力に関してはそちらで考えてください

#include<stdio.h>

int dayofw(int ,int ,int );

void main()
{
int y, m, dw, i, cnt, j;
char week[7][2]={"日", "月", "火", "水", "木", "金", "土"};
int mday[12]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

printf("年=");//入力
scanf("%d", &y);

printf("月=");
scanf("%d", &m);

if((y%4)==0 && (y%100) != 0 || (y%400) == 0){
mday[1] = 29;
}else{
mday[1] = 28;
}

dw=dayofw(y, m, 1);
cnt=dw;

printf("%d年%d月\n ", y, m);
for(j=0; j<2; j++){
for(i=0; i<7; i++){
printf(" %s ", week[i]);
}
}
printf("\n");

for(i=0; i<dw; i++){
printf(" ");
}
for(i=1; i<=mday[m-1]; i++){
printf(" %3d ", i);
cnt++;
if(cnt==14){
printf("\n");
cnt=0;
}
}
printf("\n");
}

int dayofw(int y, int m, int d)
{
int y1, yobi;

y1=(y+(y/4)-(y/100)+(y/400)+(2.6*m+1.6)+d);
yobi=y1%7;

return(yobi);
}

なんとなく作りました。
入力に関してはそちらで考えてください

#include<stdio.h>

int dayofw(int ,int ,int );

void main()
{
int y, m, dw, i, cnt, j;
char week[7][2]={"日", "月", "火", "水", "木", "金", "土"};
int mday[12]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

printf("年=");//入力
scanf("%d", &y);

printf("月=");
scanf("%d", &m);

if((y%4)==0 && (y%100) != 0 || (y%400) == 0){
mday[1] = 29;
}else{
mday[1] = 28;
}

dw=dayofw(y, m, 1);
cnt...続きを読む

Qカレンダー作成

C言語初心者です。

西暦と月を入力してその月のカレンダーを作成するプログラムの問題なのですが

#include<stdio.h>

#define MMAX 12
#define COMP (year - 1)

int main(void)
{
 int i, j, year, month, day, youbi, ycnt, mcnt = 0;
 int mday[MMAX] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

 printf("西暦と月を入力して下さい-->");
 scanf("%4d%2d, &year, &month");

 if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
  mday[1] = 29;

 for (i = 0; i < [A]; i++) {
  mcnt += mday[i];
 }

 mcnt++;
 [B] = ((COMP + COMP / 4 - COMP / 100 + COMP / 400) + mcnt) % 7;

 printf("\n%4d 年%2d 月\n", year, month);
 printf("----------------------------\n");
 printf(" 日 月 火 水 木 金 土\n");

 for (j = 0, ycnt = 0; j < youbi; j++, ycnt++) {
  printf("");
 }

 for (day =1; day <= mday[month - 1]; day++) {
  if ([C])
   printf("[%2d]", day);
  else
   printf(" %2d ", day);
  ycnt++;
  if ([D]) {
   printf("\n");
   ycnt = 0;
  }
 }
 return (0);
}

[A]、[B]、[C]、[D]に答えを入れなきゃいけないのですが私が考えた答えだと

カレンダーの表示すらされません。どこがいけないのでしょうか?

#include<stdio.h>

#define MMAX 12
#define COMP (year - 1)

int main(void)
{
 int i, j, year, month, day, youbi, ycnt, mcnt = 0;
 int mday[MMAX] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

 printf("西暦と月を入力して下さい-->");
 scanf("%4d%2d, &year, &month");

 if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
  mday[1] = 29;

 for (i = 0; i < month; i++) {
  mcnt += mday[i];
 }

 mcnt++;
 youbi = ((COMP + COMP / 4 - COMP / 100 + COMP / 400) + mcnt) % 7;

 printf("\n%4d 年%2d 月\n", year, month);
 printf("----------------------------\n");
 printf(" 日 月 火 水 木 金 土\n");

 for (j = 0, ycnt = 0; j < youbi; j++, ycnt++) {
  printf("");
 }

 for (day =1; day <= mday[month - 1]; day++) {
  if (youbi = 0)
   printf("[%2d]", day);
  else
   printf(" %2d ", day);
  ycnt++;
  if (youbi > 7) {
   printf("\n");
   ycnt = 0;
  }
 }
 return (0);
}

よろしくお願いします。

C言語初心者です。

西暦と月を入力してその月のカレンダーを作成するプログラムの問題なのですが

#include<stdio.h>

#define MMAX 12
#define COMP (year - 1)

int main(void)
{
 int i, j, year, month, day, youbi, ycnt, mcnt = 0;
 int mday[MMAX] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

 printf("西暦と月を入力して下さい-->");
 scanf("%4d%2d, &year, &month");

 if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
  mday[1] = 29;

 for (i = 0; i < [A]; i...続きを読む

Aベストアンサー

>カレンダーを作成するプログラムの問題なのですが

>  if ([C])
>   printf("[%2d]", day);
>  else
>   printf(" %2d ", day);

 うぅ~、難しい。
 質問者様のように、その月の朔日が日曜なら、全ての日に [] を付ける、というのもありそうだし・・。
 あと考えられるのは、特定曜日に [] を付ける、くらいかなぁ。

>カレンダーの表示すらされません。どこがいけないのでしょうか?

 年月の取得で、

  scanf("%4d%2d, &year, &month"); はマズイです。
  scanf("%4d%2d", &year, &month); です。

 あと、1週間が8日になっています。#1 さんが指摘した

  if (youbi > 7) { は、 if( ycnt > 6 ){ です。

 些末
   for( j = 0, ycnt = 0; j < youbi; j++, ycnt++) {
     printf("");
   }
   ↓ j は不要です
   for( ycnt = 0; ycnt < youbi; ycnt++ ){
     printf( " .. " );
   }
  (投稿すると、連続する空白は1つになるので、.. 使用)

脱線
それにつけても、年寄りは日曜から始まるカレンダーはどうも苦手です。
週末が週の頭にあるなんて・・。
  http://www.nhk.or.jp/bunken/research/kotoba/kotoba_qq_04040101.html

>カレンダーを作成するプログラムの問題なのですが

>  if ([C])
>   printf("[%2d]", day);
>  else
>   printf(" %2d ", day);

 うぅ~、難しい。
 質問者様のように、その月の朔日が日曜なら、全ての日に [] を付ける、というのもありそうだし・・。
 あと考えられるのは、特定曜日に [] を付ける、くらいかなぁ。

>カレンダーの表示すらされません。どこがいけないのでしょうか?

 年月の取得で、

  scanf("%4d%2d, &year, &month"); はマズイです。
  scanf("%4d%2d", &year...続きを読む

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

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;// 現在の年
intcurr_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;
}

VisualStudioを使ってC言語でコンソールアプリケーションのカレンダーを作っています。

やりたいことは以下の通りです。

プログラムを起動すると、現在の月を中央に三ヶ月分のカレンダーを表示。
Lキーでカレンダー全体を一ヶ月前に変更
Rキーで一ヶ月後に変更
Dキーで三ヶ月前に変更
Uキーで三ヶ月後に変更
Aキーで一年前に変更
Bキーで一年後に変更

起動時にカレンダー表示するのはできているんですが、Rでカレンダーを進めていくと12月の次が13月、次が0月、その次が1月となってしまい、日付も上手いこと表...続きを読む

Aベストアンサー

とりあえず、CalenderSet()の月判定が間違っていますね。

if( curr_mon > 12 ) は、if( month > 12 ) ではないですか?
1月未満か、の判定も同じく。

また、ループの終了条件はループする毎に評価されますから、このfor( month = curr_mon-1; month <= curr_mon+1; month++ )の終了条件を作る材料である、curr_monをループ内で変更してしまうと、終了条件も変わりますよ?

そして、ループカウンタでもあるmonth=1や=12とやってしまうと、今度は1や12からカウントを始めますので、意図しない月数表示されたり、前後分合わせて3ヶ月のうち1~2月分しか表示しない、等の動作を行う気もします。

for()ループのカウンタ(ここではmonth)と終了条件に参照する変数(ここではcurr_mon)は、変更しないで、テンポラリを作成したほうが良いと思います。

void CalenderSet( void )
{
int dispmon; //monthの代わり
int dispyear;

for( month = curr_mon-1; month <= curr_mon+1; month++ ){
dispmon = month; //表示したい月をdispmonにセット
dispyear = curr_year;

if( dispmon > 12 ){
dispmon -= 12; //今回は+-1月なので、dispmon = 1でもOK。2月以上前後に対応したかったら12を引く
dispyear = curr_year + 1;
}
if( dispmon < 1 ){
dispmon += 12; //上と同じ
dispyear = curr_year - 1;
}

// その月が何日まであるか求めて代入
nday = LaepYear( dispyear, dispmon ); //変更前→curr_year, month);
// その月が何曜日から始まるか
day_of_week = Zeller(dispyear, dispmon, 1 ); //変更前→ curr_year, month, 1);
nweek = 0;

以降省略。必要に応じて、変更してください。

変な動作をする原因は、このCalenderSet()で、中央の年月を記憶する変数(curr_year, curr_mon)を変更してしまっているということではないでしょうか?
curr_monやcurr_yearは、中央に表示したい年月であり、キー操作によって”のみ”移動させたいのでしょうから、キー操作以外で変更してはいけません。

表示するために前後の年月が必要なのであれば、それを記憶するためのローカル変数(dispyear, dispmon)を作って、それにコピーした後で、前後の年月にするための変更をローカル変数に行うべきです。

これ以外の部分は見てないのですが、とりあえずここを変更してみて、デバックを進めてみてはどうでしょう?

とりあえず、CalenderSet()の月判定が間違っていますね。

if( curr_mon > 12 ) は、if( month > 12 ) ではないですか?
1月未満か、の判定も同じく。

また、ループの終了条件はループする毎に評価されますから、このfor( month = curr_mon-1; month <= curr_mon+1; month++ )の終了条件を作る材料である、curr_monをループ内で変更してしまうと、終了条件も変わりますよ?

そして、ループカウンタでもあるmonth=1や=12とやってしまうと、今度は1や12からカウントを始めますので、意図しない月数表示さ...続きを読む


人気Q&Aランキング

おすすめ情報