質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.33%

  • C

    3977questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

万年カレンダー c言語

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 228

ahirumoco

score 1

 前提・実現したいこと

万年カレンダーを作成したくてある万年カレンダーを参考にしている時の疑問です
ここに質問の内容を詳しく書いてください。
(例)PHP(CakePHP)で●●なシステムを作っています。
■■な機能を実装中に以下のエラーメッセージが発生しました。

 発生している問題・エラーメッセージ

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

ここの部分のコードがなんの役割をしているのか。
これは公式なのか。
ew,swはなんのことを表しているのか。

がわからなくて困っています

エラーメッセージ

 該当のソースコード

コード
#include <stdio.h>

int week(int y,int m,int d)
{
    if ( m < 3 ){ //1月を13,2月を14として計算するため
        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 = week(y,m,1);
    ew = week(y,m+1,1);

    if ( sw <= ew ){
        ew = ew - sw + 28 ; 
    }else{
        ew = 35 - sw + ew ; 
    }
    printf("\n");
    printf("%4d / %d\n",y,m);  //西暦と月の表示
    printf("SUM MON TUE WED THU FRI SAT");  //曜日の表示
    for (d=0 ;d<37 ;d++){
        if (d % 7 == 0){
            printf("\n");  //(土曜日まで(週の終わり)きたら改行)
        }
        if ( d < sw || d >= ew+sw ){
            printf("    ");
        } else {
            printf("%3d ",d-sw+1);  //日にちの表示
        }
    }
    printf("\n");
    return 0 ;
}

 試したこと

ここに問題に対して試したことを記載してください。

 補足情報(FW/ツールのバージョンなど)

初めての投稿なので色々間違っていたらすみません。
ここにより詳細な情報を記載してください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • y_waiwai

    2018/07/19 22:44

    ソースコードは<code>押して、'''の枠の中に貼り付けてください

    キャンセル

回答 2

checkベストアンサー

+1

まずはプログラムのコードの処理を一つずつ見ていきましょう。例えば sw や ew は week() という関数の戻り値で初期化されていますが、この関数内にコメントされている「ツェラーの公式」については調べてみましたか?

何も分からない状態からコードだけを読んで内容を理解するのは至難の技です (特に公式などを使っている場合) 。せっかくコメントにヒントがあるので、まずは細かい単位に分解して、上から順に頭の中で実行していき、そこが何をするためのコードなのか調べていくことが大切です。具体例を考えてみるのもよい手段です。


ツェラーの公式というのはどうやら年月日からその曜日を計算する公式のようですね。

つまり、sw というのは y 年 m 月 1 日の曜日であり、 ew というのは y 年 m + 1 月 1 日の曜日を指すようです。つまり、月の初めの曜日と、その次の月の最初の日の曜日が代入されます。 最初は 。

ちなみにこれは Wikipedia によると、

 日  月  火  水  木  金
0   1   2   3   4   5   6

という対応があるらしいです。

つまり 2018 年 7 月のカレンダーを作るなら、7 月 1 日は日曜日ですから sw == 1 となり、 2018 年 8 月 1 日は水曜日ですから ew = 4 となります。

 sw <= ew のとき

sw <= ew というのは、 月の最初の曜日が次の月の始まりの曜日より前である ということになりますね。具体的にカレンダーを考えてみればよいのです。つまりたとえば次のようなカレンダーです :

(2018 年 7 月)

 土  日  月  火  水  木  金
      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 (1)        

上のカレンダーで 1 日は日曜日ですから sw == 1 で、次の月の 1 日は水曜日ですから ew == 4 となります。これを代入してみると ew - sw + 28 == 31 となりますね。なんとなく察せるかと思いますが、これはつまり 2018 年 7 月の 総日数 です。計算式の意味としては、まず日曜日から火曜日までの 3 日間がある + まるまる 4 週間 (28 日) ある、ということでしょうね。上のカレンダー的には、 (1 日から 3 日までの 3 日間) + (4 日から 31 日までのまるまる 4 週間) という感じでしょうか。

つまり「とりあえず 4 週間はまるまるあるよね。後の残りをうまく計算して足そう。」という考えです。

 sw <= ew でないとき

sw <= ew でないというのは sw > ew ということなので、 月の最初の曜日が次の月の始まりの曜日より後である ということになりますね。つまりたとえば次のようなカレンダーです :

(実際にこんなカレンダーになるの何年何月か知らないですけど)

 土  日  月  火  水  木  金
                      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 (1) (2) (3) (4) (5)    

上のカレンダーで 1 日は木曜日ですから sw == 5 で、次の月の 1 日は日曜日ですから ew == 1 となります。これを代入してみると 35 - sw + ew == 31 となりますね。なんとなく察せるかと思いますが、これもつまりこの月の 総日数 です。計算式の意味としては、まずまるまる 5 週間あって、そこから存在しない日曜日から水曜日までを引く、ということでしょう。上のカレンダー的には、(1 日から次の月の 4 日までのまるまる 5 週間) - (次の月の 1 日から 4 日の 4 日間) ということです。

つまり、「とりあえず 5 週間あるということにしよう。そこから余計に数えている分を引こう。」という考え方です。

 書き換え

あまり思い付きませんが、強いていうなら、 ew という変数を異なる意味で使い回していることが気になりますね。ですのでまあ、あえて書くなら...

 // このあと、今表示したい月の総日数をここに入れます。
int num_of_day;
if ( sw <= ew ) {
  int extra = ew - sw; // 足りてない分
  num_of_day = extra + 28;
} else {
  int over = sw - ew;  // 余分にカウントした分
  num_of_day = 35 - over;
}

// ... 以後、 ew を num_of_day へ変更する

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

ここで、仮にprintf() で出力してみる(デバッガでも良い)と分かると思いますが、sw: Start Week, ew: End Week じゃないですか?
それぞれが、その月内での第何週か、でしょう。 で、月をまたがる場合に対応するために、

if ( sw <= ew ){

をしていると思われます。
(机上での確認のみ)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/19 22:58

    自分的にif ( sw <= ew ){
    ew = ew - sw + 28 ;
    }else{
    ew = 35 - sw + ew ;
    }
    のcordがわかりにくいので代わりとなるcordって思いつきますでしょうか。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.33%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • C

    3977questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。