![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e6f04cf)
西暦、月、日(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;
}
No.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;
}
以上。
No.8
- 回答日時:
★アドバイス
>過去の質問なども参考にしたんですが、プログラムがうまく動かず困っています。
↑
この質問を参考にしたのでしょうか?
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
No.7
- 回答日時:
#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);
No.6
- 回答日時:
偶然ですが私も最近,昔考えた高速日付計算プログラムを
整理しているところなので参加します.(笑)
次のプログラムは紀元前 (年≦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/ …
No.5
- 回答日時:
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/w4ddyt9 …
No.4
- 回答日時:
windowsなら
GetLocalTime 現在のローカル日時を取得します。
VOID GetLocalTime(
LPSYSTEMTIME lpSystemTime // システム日時
);
SYSTEMTIME構造体のメンバwDayOfWeekが曜日
Sunday = 0
Monday = 1
Tuesday = 2
Wednesday = 3
Thursday = 4
Friday = 5
Saturday = 6
No.3
- 回答日時:
> 入力した年月日までの総日数
サンプルコードです。たぶん、合っていると思います。
#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;
}
(注)インデントのため、全角空白を使っています。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- JavaScript jsで、switch文で書かれた分をif文にできませんか。 1 2022/07/28 15:10
- JavaScript switch文のswitch(n)の部分を複数の値にするか、if文に変えてほしいです。 1 2022/07/27 17:18
- JavaScript セレクトボックスを2つ設けて選択して初めてメッセを表示 1 2022/07/27 12:15
- JavaScript セレクトボックスを2つ選択してメッセージなどを表示するには。~運賃検索プログラムを完成させたい~ 1 2022/07/22 11:10
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- その他(プログラミング・Web制作) python 気象データの取得 2 2023/06/20 23:54
- JavaScript 以前の質問だと、どの条件でも配列が表示されてしまいます。 1 2022/07/09 11:40
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
6月の第2 第4火曜日は何日...
-
月の第一週とは
-
よくある 『 第○(1・2・3・4・...
-
[Excel] ある日の曜日が当月の"...
-
週2回のペースって だいたい何...
-
毎○曜日って、使いますか?
-
VBA。複数のChangeイベントをま...
-
エクセルで毎月第2週日の水曜日...
-
Excel VBA 第〇△曜日の場合休日...
-
土曜日の26時って何曜日の何時...
-
毎週同じ曜日にラブホに行くと...
-
英語で「何年何月何日何曜日に」
-
第○曜日であるかを取得する関数
-
曜日を求めるプログラムはどう...
-
カレンダープログラム、曜日の...
-
一度会っただけで忘れられない...
-
入力した日は何曜日か
-
Excel関数で当月の第一日曜日の...
-
DBを10件毎に表示ページング...
-
VBAでExcelのヘッダーに文字列+...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
月の第一週とは
-
よくある 『 第○(1・2・3・4・...
-
エクセルで毎月第2週日の水曜日...
-
6月の第2 第4火曜日は何日...
-
毎○曜日って、使いますか?
-
週2回のペースって だいたい何...
-
燃えるゴミの日は何曜日ですか?
-
[Excel] ある日の曜日が当月の"...
-
【機械式腕時計のメカニズムの...
-
VBA。複数のChangeイベントをま...
-
Excelで第一〇曜日を求める方法...
-
日本語問題 昨日は何曜日ですか...
-
毎週同じ曜日にラブホに行くと...
-
曜日のなぞ
-
c言語の質問です。 ある月のカ...
-
ユーザー定義の(aaa)
-
今週とは何曜日から何曜日まで...
-
カレンダープログラム、曜日の...
-
曜日と曜の使い分けがわかりま...
-
西暦・月からカレンダーを表示
おすすめ情報