【问题标题】:c++ day of week for given date给定日期的c ++星期几
【发布时间】:2017-03-23 20:48:07
【问题描述】:

我正在尝试用 C++ 编写一个简单的程序,它返回给定日期的星期几。

输入格式为日、月、年。我无法让它与闰年一起工作。当输入年份是闰年时,我尝试从a 变量中减去一个,但程序最终崩溃而没有错误消息。

我会很感激任何建议,但请尽量保持简单,我仍然是初学者。为这个愚蠢的问题道歉,请原谅我的错误,这是我第一次在这个网站上发帖。

#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);
}

【问题讨论】:

  • 在调试器中单步执行会发生什么?
  • 在日期方面没有简单的程序(去问问 jon skeet)。该功能已经存在,为什么要重新发明它。
  • 有一个简单的公式来执行计算。见en.wikipedia.org/wiki/Determination_of_the_day_of_the_week
  • 在互联网上搜索“c++ 计算星期几”以找到大量示例。
  • y 已经是一个 int。因此,演员 (int) y/ 4 是多余的,(int)y/4 == y/4 始终为真

标签: c++ date weekday


【解决方案1】:

当一个数能被 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";
        }

【讨论】:

  • 不要听别人说不要使用自己的功能。
  • 据我们所知,您这样做是为了娱乐或学习体验。
  • 另外,请记住,您的最终程序在星期几方面是不正确的。那是因为闰年是棘手的事情,并不总是每 4 年发生一次。示例闰年不会发生在 100 年,但会发生在 400 年。所以,是的,日历会很快变得棘手。我的回答主要是帮助您找出程序崩溃的原因。
  • 谢谢,我从来没有想过 a 可能是 7 的倍数,我一定会调查一下。
【解决方案2】:

第一:不要编写自己的函数,如果已经有可以处理相同问题的标准化函数。重点是你可能很容易犯错误(我已经在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;
}

【讨论】:

  • 感谢您的建议,但是编写此程序的全部目的是练习编程并尝试掌握 c++ 的语法。不过,我不能怪你提出完全不同的方法,因为我在帖子中没有提到这一点。但是如果我在编写更复杂的程序时需要这样的东西,我会确保考虑这种方法!
  • 一年,约 1800 次观看,没有一次点赞。刚刚修好了。 @OerllydSaethwr 请点击分数附近的绿色复选标记接受这个(或另一个)答案。
  • 关于std::localtime的解决方案是尽快将其返回的副本:const std::tm time_out = *std::localtime(&amp;time_temp);。
  • @Striezel 你为什么使用 mktime?为什么不直接使用 strftime?
  • @Striezel 你也没有提供 tm_wday, tm_yday, tm_isdst。
【解决方案3】:

您对闰年的理解是错误的:

闰年是每 4 年一次除了如果它可以被 100 整除,但是即使它可以被 400 整除,它仍然是闰年。 em>

关于如何计算“天数”(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;
}

【讨论】:

    【解决方案4】:
    int dayofweek(int day,int month,int year)
    {
        int arr[] = {0,3,2,5,3,5,1,4,6,2,4};
        if(month<3)
            year--;
        return ((year+year/4-year/100+year/400+arr[month-1]+day)%7);
    }
    
    int main()
    {
        int day,month,year;
        cout<<"Enter the Date for which day of the week need to be find (DD/MM/YYYY)."<<endl;
        cin>>day>>month>>year;
        int x = dayofweek(day,month,year);
        if(x==0)
            cout<<"Sunday"<<endl;
        else if(x==1)
            cout<<"Monday"<<endl;
        else if(x==2)
            cout<<"Tuesday"<<endl;
        else if(x==3)
            cout<<"Wednesday"<<endl;
        else if(x==4)
            cout<<"Thursday"<<endl;
        else if(x==5)
            cout<<"Friday"<<endl;
        else if(x==6)
            cout<<"Saturday"<<endl;
    
    }
    

    【讨论】:

      【解决方案5】:

      您可以使用Boost C++ library 中的Gregorian Date System 来查找给定日期的星期几。这是一个简单的例子:

      #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。

      【讨论】:

        【解决方案6】:

        旧问题的新答案,因为它们正在改变工具......

        C++20 规范说,以下内容与问题中代码的意图具有相同的功能:

        #include <chrono>
        #include <format>
        #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';
        }
        

        今天可以通过使用free, open-source date/time library 来试验这种语法,只是日期对象在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';
        }
        

        【讨论】:

        • 感谢霍华德的代码。不幸的是,对于最新的 g++ 和 clang++,parse 和 format 似乎还没有准备好(-std=c++20)。最新我的意思是g++-11和clang++ 13。我说的是没有标题"date/date.h"的代码部分:(
        【解决方案7】:

        我遇到了同样的问题,我找到了一个简单的解决方案。

        据this发帖:
        "下面是Sakamoto, Lachman, Keith and Craver建议的一个简单的函数来计算天数。下面的函数返回0代表星期日,1代表星期一,等等。"

        int dayofweek(int d, int m, int y)  
        {  
            static int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };  
            y -= m < 3;  
            return ( y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) % 7;  
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-06-29
          • 1970-01-01
          • 2011-03-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-14
          • 2016-10-19
          相关资源
          最近更新 更多