西暦年月日を入力して、その日の曜日を表示させるプログラムを作りたいのですが、とりあえず、やってみましたが…
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日から△日経過しているという考え方で、曜日を割り出すプログラムにしなければならないといけないので、注文が多いですがよろしくお願いします。
No.3ベストアンサー
- 回答日時:
プログラムのおかしいところについては#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日)だからです。
No.8
- 回答日時:
蛇足ながら、1582年を境にグレゴリオ暦とユリウス暦が使い分けられています。
そのパッチを加えました。#include <stdio.h>
#include <stdlib.h>
int
getint(void)
{
char buf[BUFSIZ];
fgets(buf, BUFSIZ, stdin);
return (atoi(buf));
}
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 };
char *Week[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday" };
printf("Year?");
y = getint();
printf("Month?");
m = getint();
printf("Day?");
d = getint();
for (i = 0; i <= m - 1; i++) {
d += D[i];
}
dy = d;
if (m >= 3) {
if (y % 400 == 0 || (y % 100 != 0 && y % 4 == 0)) dy++;
}
dy += y * 365 + y / 4 - y / 100 + y / 400;
/* printf("dy = %d\n", dy); */
if (dy >= 578101) { /* 1582年10月15日以降はグレゴリオ暦 */
dw = (dy + 6) % 7;
}
else if (dy <= 578090) { /* 1582年10月4日以前はユリウス暦 */
dy = d;
if (m >= 3) {
if (y % 4 == 0) dy++;
}
dy += y * 365 + y / 4;
dw = (dy + 4) % 7;
}
else {
printf("その日は存在しません。\n");
return(0);
}
printf("%s\n", Week[dw]);
return 0;
}
No.7
- 回答日時:
がると申します。
んっと。曜日の算出にはいくつか種類がありますが、有名なツェラーの公式をお勧めします。
どうでしょうか?
参考URL:http://www004.upp.so-net.ne.jp/s_honma/doweek.ht …
No.6
- 回答日時:
>この一連のプログラムを行うにはもっと簡単に行える関数というかコマンド?みたいなものがあるようですが
蛇足ですが…
#include <stdio.h>
#include <time.h>
int
getint(void)
{
char buf[BUFSIZ];
fgets(buf, BUFSIZ, stdin);
return (atoi(buf));
}
int
main(void)
{
struct tm day;
time_t time;
char *Week[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday" };
printf("Year?");
day.tm_year = getint() - 1900;
printf("Month?");
day.tm_mon = getint() - 1;
printf("Day?");
day.tm_mday = getint();
day.tm_hour = day.tm_min = day.tm_sec = 0;
time = mktime(&day);
localtime_r(&time, &day);
printf("%s\n", Week[day.tm_wday]);
return 0;
}
No.5
- 回答日時:
#include <stdio.h>
int
getint(void)
{
char buf[BUFSIZ];
fgets(buf, BUFSIZ, stdin);
return (atoi(buf));
}
int
main(void)
{
int i, y, m, dy, dw;
int D[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
char *Week[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday" };
printf("Year?");
y = getint();
printf("Month?");
m = getint();
printf("Day?");
dy = getint();
for (i = 0; i <= m - 1; i++) {
dy += D[i];
}
if (m >= 3) {
if (y % 400 == 0 || (y % 100 != 0 && y % 4 == 0)) dy++;
}
dw = (dy - 1 + (y + (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400)) % 7;
printf("%s\n", Week[dw]);
return 0;
}
No.4
- 回答日時:
#3です。
書き間違えてました。>int D[]={0,31,59,90,120,151,181,212,243,273,304,335};
最後の335は334の間違い。
No.2
- 回答日時:
//何かの参考に
#include <stdio.h>
#include <stdlib.h>
int isLeapYear(unsigned y){
return ((0 == y % 400)||((0 == y % 4)&&(0 != y % 100)));
}
unsigned leapDays(unsigned y){
/* 基準日から指定年までの閏日の日数 */
return (y/4 - y/100 + y/400);
}
unsigned daysFromYearTop(unsigned y, unsigned m, unsigned d){
/* 指定日の年頭からの日数 */
static unsigned daysOfMonth[]={
NULL, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
};
return (daysOfMonth[m]+((m>2 && isLeapYear(y))? 1:0) + d);
}
unsigned long days(unsigned y, unsigned m, unsigned d){
/* 基準日から指定日までの通算日数 */
unsigned lastYear=y-1;
return(leapDays(lastYear) + lastYear*365 + daysFromYearTop(y, m, d));
}
#define JAPANESE 0
#define ENGLISH 1
#define ENGSHORT 2
const char *week_day(unsigned long days,int country){
/* 基準日からの通算日を指定した時の曜日を文字列で返す */
static const char *weekDays[][7]={
{"日", "月", "火", "水", "木", "金", "土"},
{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"},
{"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"}
};
return(weekDays[country][days % 7]);
}
int main(void){
unsigned y, m, d;
printf("Year?");
scanf("%u",&y);
printf("Month?");
scanf("%u",&m);
printf("Day?");
scanf("%u",&d);
printf("%s\n",week_day(days(y,m,d), ENGLISH));//通算日の曜日
return(EXIT_SUCCESS);
}
No.1
- 回答日時:
>for(i=0;i<=m-1;i++){
>dy = d + D[i] ;
>}
これでは前月のみの日付が加算されるだけです。
だから2月までならうまくいくわけです。
簡単に修正するならこんな感じでしょうか。
dy = d;
for (i = 0; i < = m - 1; i++)
{
dy += D[i] ;
}
Cの標準関数で日付関数はなかったと思います。
日付計算はよく使われるので探せばライブラリがありそうですが。
参考URLに日付関数のサンプルがありましたので参考にしてみてはいかがでしょう。
参考URL:http://hp.vector.co.jp/authors/VA016117/date.html
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラムの時、フローチャートはどうなりますか?図でお願いします。 int main(void) { 1 2022/10/01 22:45
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# プログラミングのペーパーテスト 実行結果がどのように表示されるか答えよ #include <stdi 1 2022/07/09 14:27
- C言語・C++・C# C言語 3 2022/11/09 13:27
- C言語・C++・C# C言語 プログラミング 4 2022/05/22 11:53
- C言語・C++・C# プログラミングのペーパーテスト 実行結果を表示せよ #include <stdio.h> int h 1 2022/07/09 15:27
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
strcmp
-
【C言語教えてください】sin波...
-
球の体積と表面積を表示するプ...
-
cshの文字列操作(0埋め)
-
10個出力で改行したいのですが...
-
ifなんですが
-
printf で二進表示を行いたい。
-
関数について
-
円の面積を求めるプログラミン...
-
Visual Sutdio 2017 でのC言語...
-
コマンドプロンプトがすぐ消える
-
C言語の配列問題について
-
c言語 成績表示のプログラムで...
-
(C言語)西暦年月日を入力して...
-
printfの出力内の文字をdefine...
-
コンパイルエラーについて
-
C言語で五目並べを作成している...
-
%P と %X の違い
-
2つ分数の四則演算を行うプロ...
-
hit&bolwのプログラミングがで...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
10個出力で改行したいのですが...
-
printf で二進表示を行いたい。
-
【C言語教えてください】sin波...
-
strcmp
-
コンパイルエラーについて
-
c言語でAからZまでを表示する...
-
コマンドラインに出力した文字...
-
cshの文字列操作(0埋め)
-
4の倍数を論理演算で表す。。
-
C言語 プログラミング
-
%P と %X の違い
-
8人分のテストの点数を入力し、...
-
C言語での、年複利の計算方法...
-
printf( " %2d", p * q );
-
hit&bolwのプログラミングがで...
-
scanfに文字が入力されたときに...
-
error C2143: 構文エラー : ';'...
-
printfの出力内の文字をdefine...
-
テキストカーソル位置の取得
-
unsigned int型について
おすすめ情報