自分のお店を開く時の心構えとは? >>

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;
}

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

A 回答 (3件)

とりあえず、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)を作って、それにコピーした後で、前後の年月にするための変更をローカル変数に行うべきです。

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

遅くなって申し訳ありません。
丁寧で分かりやすいご回答ありがとうございました。
テンポラリを作成してソースを改造してみたところ、思い通りの動きにすることができました!
普通に考えれば分かることでしたが、自分だけで考えてた時はテンポラリを作成するという事を全く思いつかなかったので非常に助かりました。

お礼日時:2012/06/01 15:44

グローバル変数使わずに1月分のカレンダー表示から始めた方がいいと思う。

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

現在の月から始めたかったんですけど、1月分からの方が考え方は簡単ですよね。
それと、たまに日数がきちんと表示されないバグがグローバル変数をやめることで直りました!
ありがとうございました。

お礼日時:2012/06/01 15:48

症状を正確に書いてほしいんだけどなぁ....



ひょっとして表示される 3か月の中央が 12月だと「その次の月」が「13月」になってたりしませんか?

変数の使い分けが変だと思う.

この回答への補足

すみません、字数制限の関係で詳しく書けませんでした。
具体的には一ヶ月ずつ進めていくと、おっしゃる通り以下のような感じになります。

2012  11月        2012  12月         2012  13月
日 月 火 水 木 金 土  日 月 火 水 木 金 土    月 火 水 木 金 土
          1 2 3                1
 4 5 6 7 8 9 10   2 3  4 5 6  7 8
11 12 13 14 15 16 17  9 10 11 12 13 14 15
18 19 20 21 22 23 24  16 17 18 19 20 21 22
25 26 27 28 29 30    23 24 25 26 27 28 29
                30 31
ESCキーで終了

2013 0月 2013 1月 2013 2月
日 月 火 水 木 金 土  日 月 火 水 木 金 土  日 月 火 水 木 金 土
114 4 57  13 24 4       1 2 3 4 5             1 2
112 4 144        6 7 8 9 10 11 12  3  4 5 6  7 8  9
               13 14 15 16 17 18 19   10 11 12 13 14 15 16
               20 21 22 23 24 25 26   17 18 19 20 21 22 23
               27 28 29 30 31       24 25 26 27 28

ESCキーで終了
-----------------------------------------------------------

一年後にすると
2010   4月       2010   5月       2010   6月
日 月 火 水 木 金 土  日 月 火 水 木 金 土  日 月 火 水 木 金 土
 1 2 3 4 1 2  3    1 2  3 4 5 6 1        1  2 3 4 5
4 5 6 7 8 9 10    2 3  4 5 6 7 8    6 7 8  9 10 11 12
11 12 13 14 15 16 17  9 10 11 12 13 14 15  13 14 15 16 17 18 19
18 19 20 21 22 23 24  16 17 18 19 20 21 22  20 21 22 23 24 25 26
25 26 27 28 29 30 30  23 24 25 26 27 28 29  27 28 29 30 30 29 30
                30 31
ESCキーで終了

と、表示されてしまいます。

>変数の使い分けが変だと思う.
具体的にどこの変数の使い方がおかしいのでしょうか?
ご教授くだされば嬉しいです。

補足日時:2012/05/24 14:54
    • good
    • 0

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

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

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

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

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言語プログラムを教えてください

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

Aベストアンサー

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

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

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カレンダー作成

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

Qカレンダープログラム、曜日の出力について。

西暦、月、日(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;

}

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

Aベストアンサー

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

#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;
}
以上。

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

#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;  // ...続きを読む

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

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

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の間は日付を表示する

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

Qint型からchar型への変換

タイトル通り、int型からchar型への変換の仕方がわかりません!><
どうしたらいいのでしょうか?

Aベストアンサー

#include <stdio.h>


char buf[5];
int no;

no = 10;
sprintf(buf, "%d", no);

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&Aランキング

おすすめ情報