web-dev-qa-db-ja.com

指定された日付のc ++曜日

特定の日付の曜日を返す単純なプログラムをc ++で作成しようとしています。

入力形式は、日、月、年です。うるう年で動作させることはできません。入力年がうるう年のときにa変数から1を減算しようとしましたが、プログラムはエラーメッセージなしでクラッシュするだけです。

私はどんな提案も感謝しますが、シンプルなままにしてください、私はまだ初心者です。愚かな質問に謝罪し、私の間違いを許してください。このサイトに投稿するのは初めてです。

#include <iostream>
#include <string>
#include <vector>
#include <cmath>
using namespace std;


int d;
int m;
int y;


string weekday(int d, int m, int y){
    int LeapYears = (int) y/ 4;
    long a = (y - LeapYears)*365 + LeapYears * 366;
    if(m >= 2) a += 31;
    if(m >= 3 && (int)y/4 == y/4) a += 29;
    else if(m >= 3) a += 28;
    if(m >= 4) a += 31;
    if(m >= 5) a += 30;
    if(m >= 6) a += 31;
    if(m >= 7) a += 30;
    if(m >= 8) a += 31;
    if(m >= 9) a += 31;
    if(m >= 10) a += 30;
    if(m >= 11) a += 31;
    if(m == 12) a += 30;
    a += d;
    int b = (a - 2)  % 7;
    switch (b){
    case 1:
        return "Monday";
    case 2:
        return "Tuesday";
    case 3:
        return "Wednesday";
    case 4:
        return "Thursday";
    case 5:
        return "Friday";
    case 6:
        return "Saturday";
    case 7:
        return "Sunday";
    }
}

int main(){
    cin >> d >> m >> y;
    cout << weekday(d, m, y);
}
8
OerllydSaethwr

最初:同じ問題を処理できる標準化された関数が既に存在する場合、独自の関数を作成しないでください。ポイントは、間違いを犯しやすいことです( weekday()関数の最初の行にあるように見えますが、標準化された関数の実装は徹底的にテストされており、期待どおりの結果が得られると確信できます。 。

とはいえ、ここでは std :: localtime および std :: mktime を使用した可能なアプローチを示します。

#include <ctime>
#include <iostream>

int main()
{
  std::tm time_in = { 0, 0, 0, // second, minute, hour
      9, 10, 2016 - 1900 }; // 1-based day, 0-based month, year since 1900

  std::time_t time_temp = std::mktime(&time_in);

  //Note: Return value of localtime is not threadsafe, because it might be
  // (and will be) reused in subsequent calls to std::localtime!
  const std::tm * time_out = std::localtime(&time_temp);

  //Sunday == 0, Monday == 1, and so on ...
  std::cout << "Today is this day of the week: " << time_out->tm_wday << "\n";
  std::cout << "(Sunday is 0, Monday is 1, and so on...)\n";

  return 0;
}
9
Striezel

Gregorian Date SystemBoost C++ライブラリ から使用して、特定の日付の曜日を見つけることができます。以下に簡単な例を示します。

#include <boost/date_time.hpp>
#include <string>
#include <iostream>

const static std::string daysOfWeek[] = {
    "Sunday",
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday"
};

int getDayOfWeekIndex(int day, int month, int year) {
    boost::gregorian::date d(year, month, day);
    return d.day_of_week();
}

int main()
{
    const int index = getDayOfWeekIndex(30, 07, 2018);
    std::cout << daysOfWeek[index] << '\n';
}

このコードはMondayを出力します。

3
HugoTeixeira

うるう年を構成するものについてのあなたの理解は間違っています:

うるう年は4年ごとです[〜#〜] except [〜#〜]100で割り切れる場合、[〜#〜] but [〜#〜]それでも400で割り切れる場合はうるう年です。

「日番号」(dn)の計算方法の明確で簡潔な説明は、 here にあります。

日番号(dn)を取得したら、モジュラス7を実行します。結果は曜日(dow)になります。

以下に実装例を示します(日付が有効な入力であるかどうかをチェックしません):

#include <iostream>
#include <iomanip>

typedef unsigned long ul;
typedef unsigned int ui;

// ----------------------------------------------------------------------
// Given the year, month and day, return the day number.
// (see: https://alcor.concordia.ca/~gpkatch/gdate-method.html)
// ----------------------------------------------------------------------
ul CalcDayNumFromDate(ui y, ui m, ui d)
{
  m = (m + 9) % 12;
  y -= m / 10;
  ul dn = 365*y + y/4 - y/100 + y/400 + (m*306 + 5)/10 + (d - 1);

  return dn;
}

// ----------------------------------------------------------------------
// Given year, month, day, return the day of week (string).
// ----------------------------------------------------------------------
std::string CalcDayOfWeek(int y, ul m, ul d)
{
  std::string day[] = {
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
    "Sunday",
    "Monday",
    "Tuesday"
  };

  ul dn = CalcDayNumFromDate(y, m, d);

  return day[dn % 7];
}

// ----------------------------------------------------------------------
// Program entry point.
// ----------------------------------------------------------------------
int main(int argc, char **argv)
{
  ui y = 2017, m = 8, d = 29; // 29th August, 2017.
  std::string dow = CalcDayOfWeek(y, m, d);

  std::cout << std::setfill('0') << std::setw(4) << y << "/";
  std::cout << std::setfill('0') << std::setw(2) << m << "/";
  std::cout << std::setfill('0') << std::setw(2) << d << ": ";
  std::cout << dow << std::endl;

  return 0;
}
2
Andy Turfer

ツールが変化しているため、古い質問に対する新しい答え...

現在のドラフトC++ 2a仕様では、以下は問題のコードの意図と同じ機能を持つと述べています。

#include <chrono>
#include <iostream>

int
main()
{
    using namespace std;
    using namespace std::chrono;
    year_month_day dmy;
    cin >> parse("%d %m %Y", dmy);
    cout << format("%A", weekday{dmy}) << '\n';
}

現時点では、最終的なC++ 2a仕様はC++ 20になり、フォーマット文字列は"%A"から"{:%A}"に変更される可能性があります。

日付オブジェクトがnamespace dateの代わりにnamespace std::chronoにあることを除いて、この 無料のオープンソースの日付/時刻ライブラリ を使用して、今日この構文を試すことができます。

#include "date/date.h"
#include <iostream>

int
main()
{
    using namespace std;
    using namespace date;
    year_month_day dmy;
    cin >> parse("%d %m %Y", dmy);
    cout << format("%A", weekday{dmy}) << '\n';
}
0
Howard Hinnant

数値が7で完全に割り切れるとどうなりますか?

14/7 = 2 14%7 = 0

モジュロ演算子(%n)は、0〜n -1の数値を返します。

nを7で除算すると、剰余が7になることはない

int b = (a - 2)  % 7;
    switch (b){
    case 1:
        return "Monday";
    case 2:
        return "Tuesday";
    case 3:
        return "Wednesday";
    case 4:
        return "Thursday";
    case 5:
        return "Friday";
    case 6:
        return "Saturday";
    case 7:
        return "Sunday";
    }
}

この場合、日曜日になることはありません

これを試して

int b = (a - 2)  % 7;
        switch (b){
        case 0:
            return "Sunday";
        case 1:
            return "Monday";
        case 2:
            return "Tuesday";
        case 3:
            return "Wednesday";
        case 4:
            return "Thursday";
        case 5:
            return "Friday";
        case 6:
            return "Saturday";
        default:
            return "Error";
        }
0
ComradeJoecool