C言語関係掲示板

過去ログ

No821 カレンダーと曜日の出力

[戻る] [ホームページ]
No.10381

自作関数に
投稿者---ミコ(2003/11/09 03:27:07)


今,こういう↓カレンダーのプログラムを作っているのですが,

/* インクルード処理  */
#include <stdio.h>
#include <stdlib.h>
#include<string.h>

/* 関数プロトタイプ宣言 */
int day(int y, int m);
int date(int y, int m, int d);
void disp(int y, int m, int hi, int you);

/*------------*/
/* 計算関数1 */
/*------------*/
int day(int y, int m)
{
    int d = 0;                       //リターン値
    
    if ((m == 2)&&(((y%4 == 0) && (y%100 != 0)) || (y % 400 == 0)))//2月で閏年
			d = 29;
	else
	{
		 if (m == 2)                                              //2月で平常年
			d = 28;
		else
		{
			if((m == 4)||(m == 6)||(m == 9)||(m == 11))          //4,6,9,11月のとき
				d = 30;
			else										        //それ以外のとき
				d = 31;
		}
	}

    return d;
}

/*------------*/
/* 計算関数2 */
/*------------*/
int date(int y, int m, int d)
{
	if(m==1 || m==2)//1月および2月のときは,
	{
		y -= 1;     //年数から1を引き,
		m += 10;    //月数に10を加える。
	}
	else			//その他の月のときは,
		m -= 2;		//月数から2を引く。
  
    return (y + y / 4 - y / 100 + y / 400 + ((int)2.6 * m - (int)0.195) + d) % 7;//Zellerの公式
}

/*------------*/
/* 表示関数1*/
/*------------*/
void disp(int y, int m, int hi, int you)
{
    int i;

    you = date(y, m, 1);			//曜日コード
    hi = day(y, m);					//日付
    
    printf(" %d年%d月\n", y, m);		//西暦年と月を表示。
    printf(" 日 月 火 水 木 金 土\n");	//曜日を表示。
       
    for (i = 1; i <= you; i++)			//曜日コード数分だけ空白を表示。
        printf("   ");
    for (i = 1; i <= hi; i++)			//日付を表示。
	{
        printf(" %2d", i);				//土曜日なら改行し,
        if ( (i + you) % 7 == 0)			//曜日表示コードを0にする。
            putchar('\n');				//それ以外の曜日なら,曜日コードに1を足す。
    }
}

/* メイン関数  */
void main(void)
{

/* 各変数宣言  */ 
int y, m;	      //西暦年,月
int hi = 0,you = 0; //日数,曜日コード
int nEndFlg = 0;
/* カレンダー表示の場合 */

/* 西暦年と月の入力 */

	printf("西暦年と月を入力:");
	
/* 入力データチェック */
	while(nEndFlg != 1){
		
		rewind(stdin);
		scanf("%d %d",&y,&m);
		
		if((y >= 1000 && y <= 9999) && (m >= 1 && m <= 12))
			nEndFlg = 1;
		else{
			printf("入力エラー!\n");
			printf("西暦年と月を再入力:");
			}
	}
/* 表示1 */
	disp(y, m, hi, you);

	rewind(stdin);
	getchar();

	}


↑の,

/* 入力データチェック */
	while(nEndFlg != 1){
		
		rewind(stdin);
		scanf("%d %d",&y,&m);
		
		if((y >= 1000 && y <= 9999) && (m >= 1 && m <= 12))
			nEndFlg = 1;
		else{
			printf("入力エラー!\n");
			printf("西暦年と月を再入力:");
			}
	}


この部分を
void input(int *y, int *m)
という関数にしたいのですが,
上手く行きません。
どうすれば関数化できるでしょうか。
お願いします。





No.10388

Re:自作関数に
投稿者---たか(2003/11/09 18:41:49)


関数disp()にロジックミスがありましたので直しておきました。
0==日曜日、6==土曜日です。

それから rewind(stdin); という実行結果が未定義な使い方をしてある
部分があります。stdinはパイプでつながれる可能性があるので、こういう
使い方は思わぬ実行時エラーを招く危険性をはらんでいます。

/* インクルード処理  */
#include <stdio.h>
#include <stdlib.h>
#include<string.h>

/* 関数プロトタイプ宣言 */
int day(int y, int m);
int date(int y, int m, int d);
void disp(int y, int m, int hi, int you);
void input(int *y, int *m);

/*------------*/
/* 計算関数1 */
/*------------*/
int day(int y, int m)
{
    int d = 0;                       //リターン値
    
    if ((m == 2)&&(((y%4 == 0) && (y%100 != 0)) || (y % 400 == 0)))//2月で閏年
			d = 29;
	else
	{
		 if (m == 2)                                              //2月で平常年
			d = 28;
		else
		{
			if((m == 4)||(m == 6)||(m == 9)||(m == 11))          //4,6,9,11月のとき
				d = 30;
			else										        //それ以外のとき
				d = 31;
		}
	}

    return d;
}

/*------------*/
/* 計算関数2 */
/*------------*/
int date(int y, int m, int d)
{
	if(m==1 || m==2)//1月および2月のときは,
	{
		y -= 1;     //年数から1を引き,
		m += 10;    //月数に10を加える。
	}
//	else			//その他の月のときは,
//		m -= 2;		//月数から2を引く。
  
    return (y + y / 4 - y / 100 + y / 400 + ((int)2.6 * m - (int)0.195) + d) % 7;//Zellerの公式
}

/*------------*/
/* 表示関数1*/
/*------------*/
void disp(int y, int m, int hi, int you)
{
    int i;

    you = date(y, m, 1);			//曜日コード
    hi = day(y, m);					//日付
    
    printf(" %d年%d月\n", y, m);		//西暦年と月を表示。
    printf(" 日 月 火 水 木 金 土\n");	//曜日を表示。
       
    for (i = 0; i < you; i++)			//曜日コード数分だけ空白を表示。
        printf("   ");
    for (i = 0; i < hi; i++)			//日付を表示。
	{
        printf(" %2d", i);				//土曜日なら改行し,
        if ( (i + you) % 7 == 6)			//曜日表示コードを0にする。
            putchar('\n');				//それ以外の曜日なら,曜日コードに1を足す。
    }
}

/* メイン関数  */
int main(void)
{

/* 各変数宣言  */ 
int y, m;	      //西暦年,月
int hi = 0,you = 0; //日数,曜日コード
/* カレンダー表示の場合 */

  input(&y, &m);

/* 表示1 */
	disp(y, m, hi, you);

	rewind(stdin);
	getchar();

  return 0;
}

void input(int *y, int *m)
{
  int nEndFlg = 0;

/* 西暦年と月の入力 */

	printf("西暦年と月を入力:");
	
/* 入力データチェック */
	while(nEndFlg != 1){
		
		rewind(stdin);
		scanf("%d %d", y, m);
		
		if((*y >= 1000 && *y <= 9999) && (*m >= 1 && *m <= 12))
			nEndFlg = 1;
		else{
			printf("入力エラー!\n");
			printf("西暦年と月を再入力:");
			}
	}
}


No.10391

Re:自作関数に
投稿者---ミコ(2003/11/09 20:25:41)


ご指摘ありがとうございます。

ただ,修正していただいたプログラムを実行したら,
奇妙な実行結果が表示されてしまったのですが・・・。

西暦年と月を入力:2003
11
 2003年11月
 日 月 火 水 木 金 土
                 0  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


No.10393

Re:自作関数に
投稿者---たか(2003/11/09 20:50:06)


>ご指摘ありがとうございます。
>
>ただ,修正していただいたプログラムを実行したら,
>奇妙な実行結果が表示されてしまったのですが・・・。

済みません、飲酒中のせいか(^_^;)いつもより集中力が大幅に
低下しています。これでおかしかったらまた言って下さい。

/* インクルード処理  */
#include <stdio.h>
#include <stdlib.h>
#include<string.h>

/* 関数プロトタイプ宣言 */
int day(int y, int m);
int date(int y, int m, int d);
void disp(int y, int m, int hi, int you);
void input(int *y, int *m);

/*------------*/
/* 計算関数1 */
/*------------*/
int day(int y, int m)
{
    int d = 0;                       //リターン値
    
    if ((m == 2)&&(((y%4 == 0) && (y%100 != 0)) || (y % 400 == 0)))//2月で閏年
			d = 29;
	else
	{
		 if (m == 2)                                              //2月で平常年
			d = 28;
		else
		{
			if((m == 4)||(m == 6)||(m == 9)||(m == 11))          //4,6,9,11月のとき
				d = 30;
			else										        //それ以外のとき
				d = 31;
		}
	}

    return d;
}

/*------------*/
/* 計算関数2 */
/*------------*/
int date(int y, int m, int d)
{
	if(m==1 || m==2)//1月および2月のときは,
	{
		y -= 1;     //年数から1を引き,
		m += 10;    //月数に10を加える。
	}
//	else			//その他の月のときは,
//		m -= 2;		//月数から2を引く。
  
    return (y + y / 4 - y / 100 + y / 400 + ((int)2.6 * m - (int)0.195) + d) % 7;//Zellerの公式
}

/*------------*/
/* 表示関数1*/
/*------------*/
void disp(int y, int m, int hi, int you)
{
    int i;

    you = date(y, m, 1);			//曜日コード
    hi = day(y, m);					//日付
    
    printf(" %d年%d月\n", y, m);		//西暦年と月を表示。
    printf(" 日 月 火 水 木 金 土\n");	//曜日を表示。
       
    for (i = 0; i <= you; i++)			//曜日コード数分だけ空白を表示。
        printf("   ");
    for (i = 0; i < hi; i++)			//日付を表示。
	{
        printf(" %2d", i + 1);				//土曜日なら改行し,
        if ( (i + you + 1) % 7 == 6)			//曜日表示コードを0にする。
            putchar('\n');				//それ以外の曜日なら,曜日コードに1を足す。
    }
}

/* メイン関数  */
int main(void)
{

/* 各変数宣言  */ 
int y, m;	      //西暦年,月
int hi = 0,you = 0; //日数,曜日コード
/* カレンダー表示の場合 */

  input(&y, &m);

/* 表示1 */
	disp(y, m, hi, you);

	rewind(stdin);
	getchar();

  return 0;
}

void input(int *y, int *m)
{
  int nEndFlg = 0;

/* 西暦年と月の入力 */

	printf("西暦年と月を入力:");
	
/* 入力データチェック */
	while(nEndFlg != 1){
		
		rewind(stdin);
		scanf("%d %d", y, m);
		
		if((*y >= 1000 && *y <= 9999) && (*m >= 1 && *m <= 12))
			nEndFlg = 1;
		else{
			printf("入力エラー!\n");
			printf("西暦年と月を再入力:");
			}
	}
}


No.10394

Re:自作関数に
投稿者---ミコ(2003/11/09 21:49:48)


動きました!。
ありがとうございます。

No.10395

Re:自作関数に
投稿者---ミコ(2003/11/09 22:36:31)


今度は「年,月,日」を入力して,
その日の「曜日」を表示させるプログラムを作っているのですが,

/* インクルード処理  */
#include <stdio.h>
#include <stdlib.h>

/* 関数プロトタイプ宣言 */
int date(int y, int m, int d);
void input(int *y, int *m);
void disp_2(int y, int m, int d);

/*------------*/
/* 計算関数2 */
/*------------*/
int date(int y, int m, int d)
{
    
	if (m == 1 || m == 2) {
        y -= 1;
        m += 10;
    }
//	else
		m -= 2;

    return (y + y/4 - y/100 + y/400 + ((int)2.6 * m - (int)0.195) + d) % 7;

}

/*--------------------------*/	
/* 入力データチェック関数 */
/*--------------------------*/	
void input(int *y, int *m)
{
	int d;
	int a;

/* 西暦年と月の入力 */
	printf("西暦年と月と日を入力:");

/* 入力データチェック */
	for(a = 0; a < 1;){
		
		rewind(stdin);
		scanf("%d %d %d",&*y,&*m,&d);
		
		if((*y >= 1000 && *y <= 9999) && (*m >= 1 && *m <= 12))
			a += 1;
		else{			
			printf("入力エラー!\n");
			printf("再入力:");
			}
	}
}

/*----------*/
/* 表示2 */
/*----------*/
void disp_2(int y, int m, int d);
void disp_2(int y, int m, int d) 
 
	{
	int k;                                                     //曜日
	static char *w[7] = { "日","月","火","水","木","金","土" };//曜日コード

	/* 計算◆*/
    k = date(y, m, d); 
	
	printf("西暦%d年%d月%d日は%s曜日です\n", y, m, d, w[k]);
	}

/* メイン関数  */
int main(void)
{

/* 各変数宣言  */ 

int y, m,d;						//西暦年,月,日

/* 曜日の表示 */


/* 入力データチェック */
	input(&y, &m);

/* 表示2 */
	disp_2(y, m, d);
	
	rewind(stdin);
	getchar();
	return 0;
}


↑これを,
 入力された「日」が
その「年」のその「月」に本当にあるのか確認,なければ再入力させる。
ということも含めて,きちんと動くように変えたいのですが。
どうしたらいいのか教えていただけませんか?

No.10400

Re:自作関数に
投稿者---たか(2003/11/10 13:30:19)


>今度は「年,月,日」を入力して,
>その日の「曜日」を表示させるプログラムを作っているのですが,
>これを,
>入力された「日」が
>その「年」のその「月」に本当にあるのか確認,なければ再入力させる。
>ということも含めて,きちんと動くように変えたいのですが。
>どうしたらいいのか教えていただけませんか?

こんな感じですね。
何度も言いますが、rewind(stdin)という使い方はやめましょう。
#Zellerの公式が通常使っているものとは異なってましたので
#ついでに直しておきました。

/* インクルード処理 */
#include <stdio.h>
#include <stdlib.h>

/* 関数プロトタイプ宣言 */
int date(int y, int m, int d);
void input(int *y, int *m, int *d);
void disp_2(int y, int m, int d);

/* メイン関数  */
int main(void)
{
  /*  各変数宣言  */ 
  int y, m, d; /* 西暦年,月,日 */

  /* 曜日の表示 */

  /* 入力データチェック */
  input(&y, &m, &d);

  /* 表示2 */
  disp_2(y, m, d);

  getchar();
  return 0;
}

/*------------*/
/* 計算関数2  */
/*------------*/
int date(int y, int m, int d)
{
  if (m == 1 || m == 2) {
    y--;
    m += 12;
  }
  /* Zellerの公式 */
  return (y + y / 4 - y / 100 + y / 400 + (int)((13.0 * m + 8) / 5 + d)) % 7;
}

/*--------------------------*/	
/*  入力データチェック関数  */
/*--------------------------*/	
void input(int *y, int *m, int *d)
{
  int leap;
  char buf[128];

  /*  西暦年と月の入力  */
  printf("西暦年と月と日を入力:");

  /*  入力データチェック  */
  while (1) {
    scanf("%d %d %d", y, m, d);
    gets(buf); /* バッファに残った文字を取り除く */
    
    /* 閏年以外の場合は2月29日という入力をエラーにする */
    leap = (*y % 4 == 0) && (*y % 100 != 0) || (*y % 400 == 0);
    if ((*y >= 1583 && *y <= 3999) && (*m >= 1 && *m <= 12))
      if (!leap)
        break;
      else /* 閏年 */
        if (*m != 2 || *m == 2 && *d < 29) break;
    printf("入力エラー!\n");
    printf("再入力:");
  }
}

/*----------*/
/*  表示2   */
/*----------*/
void disp_2(int y, int m, int d) 
{
  int k;                                                    //曜日
  static char *w[] = { "日","月","火","水","木","金","土" };//曜日コード

  /* 計算 */
  k = date(y, m, d); 
  
  printf("西暦%d年%d月%d日は%s曜日です\n", y, m, d, w[k]);
}


No.10401

Re:自作関数に
投稿者---たか(2003/11/10 13:45:16)


あっそうか、30日までしかない月の判別を忘れていました。
今ちょっと仕事が忙しいので夕方にでも。

No.10405

Re:自作関数に
投稿者---たか(2003/11/10 17:15:33)


これでどうでしょうか。

/* インクルード処理 */
#include <stdio.h>
#include <stdlib.h>

/* 関数プロトタイプ宣言 */
int date(int y, int m, int d);
int isexistthirty1st(int m);
void input(int *y, int *m, int *d);
void disp_2(int y, int m, int d);

/* メイン関数  */
int main(void)
{
  /*  各変数宣言  */ 
  int y, m, d; /* 西暦年,月,日 */

  /* 曜日の表示 */

  /* 入力データチェック */
  input(&y, &m, &d);

  /* 表示2 */
  disp_2(y, m, d);

  getchar();
  return 0;
}

/*------------*/
/* 計算関数2  */
/*------------*/
int date(int y, int m, int d)
{
  if (m == 1 || m == 2) {
    y--;
    m += 12;
  }
  /* Zellerの公式 */
  return (y + y / 4 - y / 100 + y / 400 + (int)((13.0 * m + 8) / 5 + d)) % 7;
}

/*------------*/
/* 計算関数3  */
/*------------*/
int isexistthirty1st(int m)
{
  int i, month[] = {1, 3, 5, 7, 8, 10, 12};

  for (i = 0; i < 7; i++)
    if (m == month[i]) return 1;
  return 0;
}

/*--------------------------*/
/*  入力データチェック関数  */
/*--------------------------*/
void input(int *y, int *m, int *d)
{
  int leap;
  char buf[128];

  /*  西暦年と月の入力  */
  printf("西暦年と月と日を入力:");

  /*  入力データチェック  */
  while (1) {
    scanf("%d %d %d", y, m, d);
    gets(buf); /* バッファに残った文字を取り除く */
    
    /* 30日までしかない月に31日以上を入れた場合、更に
    /* 更に閏年以外の場合は2月29日という入力をエラーにする */
    leap = (*y % 4 == 0) && (*y % 100 != 0) || (*y % 400 == 0);
    if ((*y >= 1583 && *y <= 3999) && (*m >= 1 && *m <= 12) && (isexistthirty1st(*m)) ? *d <= 31 : *d <= 30)
      if (!leap) {
        if (*m != 2 || *d >= 1 && *d < 29) break;
      } else /* 閏年 */
        if (*m != 2 || *d >= 1 && *d < 30) break;
    printf("入力エラー!\n");
    printf("再入力:");
  }
}

/*----------*/
/*  表示2   */
/*----------*/
void disp_2(int y, int m, int d) 
{
  int k;                                                    //曜日
  static char *w[] = { "日","月","火","水","木","金","土" };//曜日コード

  /* 計算 */
  k = date(y, m, d); 
  
  printf("西暦%d年%d月%d日は%s曜日です\n", y, m, d, w[k]);
}


No.10412

Re:自作関数に
投稿者---ミコ(2003/11/10 21:23:15)


何度もお世話になってすみません。
ありがとうございます。


No.10413

Re:自作関数に
投稿者---たか(2003/11/10 22:09:26)


>何度もお世話になってすみません。
>ありがとうございます。

あと強いて言えば2月以外の日の入力でマイナスの数を入れた時のチェック
を忘れていますので勉強がてら改造してみて下さい。