【问题标题】:C++ date comparison does not always evaluate to the same logical valueC++ 日期比较并不总是评估为相同的逻辑值
【发布时间】:2017-06-22 18:47:20
【问题描述】:

我正在制作一个必须跟踪与书籍相关的日期的项目。我将日期存储为字符串。我需要打印出在给定日期之后出版的所有书籍。

下面是一个类似于我在代码中所做的循环,它复制了两个日期的值比较不一致的问题。

#include <time.h>
#include <stdio.h>
#include <string>
#include <ctime>
#include <vector>

int main()
{
    std::string comp_against = "11/1995";
    std::vector<std::string> dates = {"11/1995", "10/1990", "03/2004", "2/1992", "11/1995"};

    for(auto it = dates.begin(); it != dates.end(); ++it)
    {
        std::string date = *it;

        struct tm t1;
        struct tm t2;

        // parse the dates with mm/YYYY format
        strptime(comp_against.c_str(), "%m/%Y", &t1);
        strptime(date.c_str(), "%m/%Y", &t2);

        std::time_t s1 = mktime(&t1);
        std::time_t s2 = mktime(&t2);

        printf("%s > %s: %s\n", date.c_str(), comp_against.c_str(), (s2 > s1 ? "true" : "false"));
    }

    return 0;
}

我电脑上的输出:

11/1995 > 11/1995: false        <- these two are different
10/1990 > 11/1995: false                |
03/2004 > 11/1995: true                 |
2/1992 > 11/1995: false                 |
11/1995 > 11/1995: true         <- these two are different

当我运行我的实际代码时,问题正好相反。当在第一次迭代的循环开始时将日期“11/1995”与自身进行比较时,s2&gt;s1 的计算结果为true,而不是像上面的输出那样false,第二次比较的计算结果为false .

编辑: 如果我与 difftime 进行比较,我会遇到同样的问题。在上面代码中的printf之后添加printf("%s &gt; %s: %s\n", date.c_str(), comp_against.c_str(), (difftime(s2, s1) &gt; 0.0 ? "true" : "false"));printf("\n");,你会得到下面的输出。

11/1995 > 11/1995: false        <- different
11/1995 > 11/1995: false              |

10/1990 > 11/1995: false              |
10/1990 > 11/1995: false              |

03/2004 > 11/1995: true               |
03/2004 > 11/1995: true               |

2/1992 > 11/1995: false               |
2/1992 > 11/1995: false               |

11/1995 > 11/1995: true               |
11/1995 > 11/1995: true        <- different

【问题讨论】:

    标签: c++ time strptime time-t


    【解决方案1】:

    您的strptime 提取没有填充您提供给它们的struct tm 构造中的所有内容;他们只填充制造您请求的格式数据所需的项目。

    将您的 struct tm 声明更改为:

    struct tm t1{}; // value initialize members
    struct tm t2{}; // here too.
    

    假设您使用的是符合 C++11 的工具链。这样做,结果是:

    11/1995 > 11/1995: false
    10/1990 > 11/1995: false
    03/2004 > 11/1995: true
    2/1992 > 11/1995: false
    11/1995 > 11/1995: false
    

    如果你想知道如何:

    printf("%ld %ld : %s > %s: %s\n", s1, s2, date.c_str(),
           comp_against.c_str(), (s2 > s1 ? "true" : "false"));
    

    它在没有对你的 tm 结构进行值初始化的情况下产生了这个:

    815126400 815126400 : 11/1995 > 11/1995: false
    817804800 657360000 : 10/1990 > 11/1995: false
    815212800 1080720000 : 03/2004 > 11/1995: true
    815212800 699523200 : 2/1992 > 11/1995: false
    815212800 815299200 : 11/1995 > 11/1995: true
    

    并通过初始化产生这个:

    815126400 815126400 : 11/1995 > 11/1995: false
    815126400 654681600 : 10/1990 > 11/1995: false
    815126400 1078041600 : 03/2004 > 11/1995: true
    815126400 696844800 : 2/1992 > 11/1995: false
    815126400 815126400 : 11/1995 > 11/1995: false
    

    【讨论】:

    • 啊,对。没有理由我不应该自己意识到这一点。谢谢。
    【解决方案2】:

    来自the strptime(3) reference

    原则上,这个函数不会初始化 tm 而是存储指定的值。这意味着 tm 应该在调用之前初始化。

    解决方案:

    struct tm t1 = {}; // same for t2 ...
    

    【讨论】:

      【解决方案3】:

      使用此free, open-source, header-only, C++11/14 date library,这是一种使您的代码更简单且不易出错的方法:

      #include "date.h"
      #include <iostream>
      #include <vector>
      
      int main()
      {
          using namespace date::literals;
          auto comp_against = 1995_y/11;
          std::vector<date::year_month> dates = {1995_y/11, 1990_y/10, 2004_y/03,
                                                 1992_y/2, 1995_y/11};
      
          std::cout << std::boolalpha;
          for(auto it = dates.begin(); it != dates.end(); ++it)
              std::cout << *it << " > " << comp_against << ": "
                        << (*it > comp_against) << '\n';
      }
      

      输出是:

      1995/Nov > 1995/Nov: false
      1990/Oct > 1995/Nov: false
      2004/Mar > 1995/Nov: true
      1992/Feb > 1995/Nov: false
      1995/Nov > 1995/Nov: false
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多