陶树林 發表於 2026-1-8 08:55:14

在C++中正确处理日期字符串排序的方法

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>第一部分:&ldquo;自定义盒子&rdquo;&mdash;&mdash;Date结构体</li><li>第二部分:&ldquo;日历规则&rdquo;&mdash;&mdash;自定义比较器</li><li>第三部分:&ldquo;实战演练&rdquo;&mdash;&mdash;结合sort与&ldquo;规则&rdquo;</li><li>第四部分:&ldquo;X光透 视&rdquo;&mdash;&mdash;亲眼目睹&ldquo;规则&rdquo;被调用</li><ul class="second_class_ul"><li>&ldquo;X光&rdquo;实战(基于date_sort.cpp)</li></ul><li>动手试试!(终极挑战:你的&ldquo;学生排名器&rdquo;)</li><ul class="second_class_ul"></ul></ul></div><p>在C++编程中,排序是一个核心任务。<code>std::sort</code>(来自 <code>&lt;algorithm&gt;</code>)是一个极其强大的&ldquo;<strong>神奇黑盒</strong>&rdquo;,可以为你排序 <code>vector</code>。</p>
<ul><li><code>vector&lt;int&gt; nums = {50, 10, 30};</code></li><li><code>std::sort(nums.begin(), nums.end());</code> -&gt; <code>nums</code> 变成 <code>{10, 30, 50}</code> (从小到大)。</li><li><code>vector&lt;string&gt; names = {&quot;Charlie&quot;, &quot;Alice&quot;};</code></li><li><code>std::sort(names.begin(), names.end());</code> -&gt; <code>names</code> 变成 <code>{&quot;Alice&quot;, &quot;Charlie&quot;}</code> (按字母顺序)。</li></ul>
<p><strong>但是,如果你有一堆&ldquo;日期&rdquo;字符串呢?</strong><br /><code>vector&lt;string&gt; dates = {&quot;10-12-2023&quot;, &quot;05-01-2024&quot;};</code></p>
<p>如果你&ldquo;天真地&rdquo;调用 <code>std::sort</code>:<br /><code>std::sort(dates.begin(), dates.end());</code></p>
<ul><li>结果会是:<code>{&quot;05-01-2024&quot;, &quot;10-12-2023&quot;}</code>。</li><li><strong>这是错误的!</strong> 2024年的日期排在了2023年的<strong>前面</strong>!</li></ul>
<p><strong>一个简单的比喻:&ldquo;字典&rdquo; vs &ldquo;日历&rdquo;</strong></p>
<ul><li><strong>默认 <code>std::sort</code> (用于字符串)</strong>:就像一个&ldquo;<strong>字典</strong>&rdquo;。它<strong>只</strong>懂&ldquo;<strong>字母顺序</strong>&rdquo;。在&ldquo;字典&rdquo;里,<code>&quot;0&quot;</code> (以 &lsquo;0&rsquo; 开头) <strong>确实</strong>排在 <code>&quot;1&quot;</code> (以 &lsquo;1&rsquo; 开头) 的<strong>前面</strong>。</li><li><strong>你想要的(日期排序)</strong>:就像一个&ldquo;<strong>日历</strong>&rdquo;。你需要一种&ldquo;<strong>智能</strong>&rdquo;排序,它能<strong>理解</strong> <code>Year</code> (年), <code>Month</code> (月), <code>Day</code> (日) 的<strong>逻辑关系</strong>。</li></ul>
<p><strong>解决方案:</strong><br />我们不能直接排序字符串。我们必须:</p>
<ol><li><strong>&ldquo;教会&rdquo; C++ 如何&ldquo;阅读&rdquo;日期</strong>。最好的方法是创建一个&ldquo;<strong>自定义盒子</strong>&rdquo;(<code>struct</code>),把日期拆分成&ldquo;年&rdquo;、&ldquo;月&rdquo;、&ldquo;日&rdquo;三个整数。</li><li><strong>&ldquo;教会&rdquo; <code>std::sort</code> 我们的&ldquo;日历规则&rdquo;</strong>。我们必须提供一个&ldquo;<strong>自定义比较器</strong>&rdquo;(Comparator)函数,告诉 <code>std::sort</code>:&ldquo;<strong>先比较年份,如果年份相同,再比较月份&hellip;</strong>&rdquo;</li></ol>
<p><strong>在本教程中,你将学会:</strong></p>
<ul><li><strong>为什么不能直接排日期字符串</strong>(&ldquo;字典&rdquo; vs &ldquo;日历&rdquo;)。</li><li><strong>如何使用 <code>struct</code></strong> 来&ldquo;打包&rdquo;日期数据 (Y, M, D)。</li><li><strong>&ldquo;黄金法则&rdquo;</strong>:如何编写一个&ldquo;<strong>自定义比较器</strong>&rdquo;函数 (Comparator)。</li><li><strong><code>std::sort</code> 的&ldquo;第三个参数&rdquo;</strong>:如何把你的&ldquo;规则&rdquo;传递给 <code>std::sort</code>。</li><li><strong>实战演练</strong>:编写一个完整的 <code>sortDates</code> 程序。</li><li><strong>&ldquo;X光透 视&rdquo;</strong>:用调试器&ldquo;亲眼目睹&rdquo; <code>std::sort</code> 是如何&ldquo;调用&rdquo;你的&ldquo;自定义规则&rdquo;的。</li></ul>
<p><strong>前置知识说明 (100% 自洽):</strong></p>
<ul><li><strong>变量 (Variable)</strong>:理解存储数据的&ldquo;盒子&rdquo;,如 <code>int year = 2024;</code>。</li><li><strong><code>vector</code> (向量)</strong>:C++标准库提供的一种&ldquo;动态数组&rdquo;(&ldquo;魔法弹性盒子列表&rdquo;)。你需要 <code>#include &lt;vector&gt;</code>。</li><li><strong><code>struct</code> (结构体)</strong>:一种&ldquo;蓝图&rdquo;,用于创建&ldquo;自定义盒子&rdquo;,把相关数据(如 <code>y</code>, <code>m</code>, <code>d</code>)打包在一起。</li><li><strong><code>#include &lt;algorithm&gt;</code></strong>:<code>std::sort</code> &ldquo;神奇黑盒&rdquo;所在的&ldquo;工具包&rdquo;。</li><li><strong><code>bool</code> 函数</strong>:一个返回 <code>true</code> (真) 或 <code>false</code> (假) 的函数,我们将用它来编写&ldquo;规则&rdquo;。</li><li><strong><code>if/else if/else</code></strong>:用于编写&ldquo;规则&rdquo;的逻辑判断。</li><li><strong>编译 (Compile)</strong>:C++代码(&ldquo;食谱&rdquo;)必须被&ldquo;编译&rdquo;(&ldquo;烘焙&rdquo;),才能变成电脑可执行的程序(&ldquo;蛋糕&rdquo;)。</li></ul>
<p class="maodian"></p><h2>第一部分:&ldquo;自定义盒子&rdquo;&mdash;&mdash;Date结构体</h2>
<p>首先,我们&ldquo;设计&rdquo;一个&ldquo;蓝图&rdquo;,告诉C++一个 <code>Date</code> 对象长什么样。</p>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt; // 包含 std::sort
#include &lt;string&gt;
using namespace std;

// “蓝图”:一个自定义的 Date 盒子
// 它把日期“拆分”成三个 *可比较* 的整数
struct Date {
    int day;
    int month;
    int year;
};
</pre></div>
<p>现在,我们可以创建 <code>Date</code> 对象的 <code>vector</code>,而不是 <code>string</code> 的 <code>vector</code>:<br /><code>vector&lt;Date&gt; calendar = { {10, 12, 2023}, {5, 1, 2024}, {15, 12, 2023} };</code></p>
<p class="maodian"></p><h2>第二部分:&ldquo;日历规则&rdquo;&mdash;&mdash;自定义比较器</h2>
<p><code>std::sort</code> 的&ldquo;默认规则&rdquo;是 <code>operator&lt;</code> (小于号)。我们现在要提供一个<strong>新</strong>的&ldquo;规则手册&rdquo;(一个函数),来代替 <code>&lt;</code>。</p>
<p><strong>比较器 (Comparator) 的&ldquo;黄金法则&rdquo;:</strong><br /><code>std::sort</code> 需要一个函数 <code>bool compare(A, B)</code>。</p>
<ul><li>如果你希望 <code>A</code> <strong>排在</strong> <code>B</code> 的<strong>前面</strong>,你的函数必须返回 <strong><code>true</code></strong>。</li><li>如果你希望 <code>A</code> <strong>排在</strong> <code>B</code> 的<strong>后面</strong>(或相同),你的函数必须返回 <strong><code>false</code></strong>。</li></ul>
<p><strong><code>compareDates.cpp</code> (&ldquo;日历规则&rdquo;函数)</strong></p>
<div class="jb51code"><pre class="brush:cpp;">// “规则手册”:告诉 std::sort 如何比较两个 Date 对象
bool compareDates(const Date&amp; a, const Date&amp; b) {
   
    // 规则 1:先比较“年”
    if (a.year &lt; b.year) {
      return true;// a 的年份小,a 应该排在前面
    }
    if (a.year &gt; b.year) {
      return false; // a 的年份大,a 应该排在后面
    }
   
    // “行内预警”:如果程序运行到这里,说明 a.year == b.year
   
    // 规则 2:如果年份相同,再比较“月”
    if (a.month &lt; b.month) {
      return true;// a 的月份小,a 应该排在前面
    }
    if (a.month &gt; b.month) {
      return false; // a 的月份大,a 应该排在后面
    }
   
    // “行内预警”:如果程序运行到这里,说明年份和月份都相同
   
    // 规则 3:如果月份相同,最后比较“日”
    return (a.day &lt; b.day); // 如果 a.day 小,返回 true
}
</pre></div>
<p class="maodian"></p><h2>第三部分:&ldquo;实战演练&rdquo;&mdash;&mdash;结合sort与&ldquo;规则&rdquo;</h2>
<p>现在我们把 <code>std::sort</code> 和我们的&ldquo;规则手册&rdquo; <code>compareDates</code> 结合起来。</p>
<p><strong><code>date_sort.cpp</code> (完整代码)</strong></p>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;
#include &lt;string&gt;
using namespace std;

// --- 1. “蓝图” ---
struct Date {
    int day;
    int month;
    int year;
};

// --- 2. “规则手册” ---
bool compareDates(const Date&amp; a, const Date&amp; b) {
    if (a.year &lt; b.year) return true;
    if (a.year &gt; b.year) return false;
   
    // 年份相同
    if (a.month &lt; b.month) return true;
    if (a.month &gt; b.month) return false;
   
    // 月份也相同
    return (a.day &lt; b.day);
}

// 辅助函数:打印日期
void printDates(const string&amp; title, const vector&lt;Date&gt;&amp; dates) {
    cout &lt;&lt; title &lt;&lt; endl;
    for (const auto&amp; d : dates) {
      // (为了美观,我们补 0)
      printf("%02d-%02d-%04d\n", d.day, d.month, d.year);
    }
}


int main() {
    // 3. 创建“自定义盒子”列表
    vector&lt;Date&gt; calendar = {
      {10, 12, 2023}, // 10-Dec-2023
      {5,1,2024}, // 05-Jan-2024
      {15, 12, 2023}, // 15-Dec-2023
      {2,2,2023}// 02-Feb-2023
    };
   
    printDates("--- 原始顺序 ---", calendar);

    // 4. “按下按钮”并“递上纸条” (规则手册)
    std::sort(calendar.begin(), calendar.end(), compareDates);

    printDates("\n--- 日历排序后 ---", calendar);
   
    return 0;
}
</pre></div>
<p><strong>&ldquo;手把手&rdquo;终端模拟:</strong></p>
<div class="jb51code"><pre class="brush:cpp;">PS C:\MyCode&gt; g++ date_sort.cpp -o date_sort.exe -std=c++11
PS C:\MyCode&gt; .\date_sort.exe
--- 原始顺序 ---
10-12-2023
05-01-2024
15-12-2023
02-02-2023

--- 日历排序后 ---
02-02-2023
10-12-2023
15-12-2023
05-01-2024
</pre></div>
<p><strong>顿悟时刻:</strong> 排序<strong>成功</strong>!<code>std::sort</code> 正确地理解了我们的&ldquo;日历规则&rdquo;,将 2023 年的日期排在了 2024 年的前面。</p>
<p class="maodian"></p><h2>第四部分:&ldquo;X光透 视&rdquo;&mdash;&mdash;亲眼目睹&ldquo;规则&rdquo;被调用</h2>
<p>我们无法(也不需要)用调试器&ldquo;步入&rdquo; (<code>F11</code>) <code>std::sort</code> 内部,因为它是一个高度优化的、编译好的&ldquo;黑盒&rdquo;。<br />但是,我们可以&ldquo;步入&rdquo;它<strong>调用我们</strong>的&ldquo;自定义规则&rdquo; (<code>compareDates</code>)!</p>
<p class="maodian"></p><h3>&ldquo;X光&rdquo;实战(基于date_sort.cpp)</h3>
<p><strong>设置断点:</strong></p>
<ul><li><strong>动作:</strong> 在VS Code中,把你的鼠标移动到**&ldquo;规则手册&rdquo;<strong>函数 <code>compareDates</code> 内部的</strong>第16行**(<code>if (a.year &lt; b.year)</code>)的<strong>行号左边</strong>。</li><li><strong>点击</strong>那个小 red dot,设置一个<strong>断点</strong>。</li></ul>
<p><strong>启动&ldquo;子弹时间&rdquo;(F5):</strong></p>
<ul><li><strong>动作:</strong> 按下 <code>F5</code> 键。</li><li><strong>你会看到:</strong> 程序执行 <code>main</code>,创建 <code>vector</code>,打印&ldquo;原始顺序&rdquo;。</li><li>当程序执行到 <code>std::sort(...)</code> 这一行时,它会**&ldquo;跳进&rdquo;<strong>你的 <code>compareDates</code> 函数,</strong>&ldquo;冻结&rdquo;**在第16行!</li></ul>
<p><strong>开启&ldquo;X光&rdquo;(观察&ldquo;裁判&rdquo;工作):</strong></p>
<ul><li><strong>动作:</strong> 仔细看那个&ldquo;变量&rdquo;(VARIABLES)窗口。</li><li><strong>你会看到:</strong><ul><li><code>a: {day: 5, month: 1, year: 2024}</code></li><li><code>b: {day: 10, month: 12, year: 2023}</code></li></ul></li><li><strong>顿悟时刻:</strong> <code>std::sort</code>(&ldquo;黑盒&rdquo;)为了决定 &ldquo;2024年&rdquo; 和 &ldquo;2023年&rdquo; 谁该排前面,它把<strong>这两个</strong>对象&ldquo;递&rdquo;给了你的&ldquo;裁判&rdquo; (<code>compareDates</code>)!</li><li><strong>动作:</strong> 按下 <code>F10</code> 键(&ldquo;Step Over&rdquo;)。</li><li><strong>你会看到:</strong> <code>(a.year &lt; b.year)</code> (即 <code>2024 &lt; 2023</code>) 计算为 <code>false</code>。高亮条跳到<strong>第19行</strong>。</li><li><strong>动作:</strong> 按下 <code>F10</code> 键。</li><li><strong>你会看到:</strong> <code>(a.year &gt; b.year)</code> (即 <code>2024 &gt; 2023</code>) 计算为 <code>true</code>。函数返回 <code>false</code>。<code>sort</code> 知道了 &ldquo;2024&rdquo; 应该在 &ldquo;2023&rdquo; 后面。</li></ul>
<p><strong>继续执行 (F5)。</strong></p>
<p><strong>第二次&ldquo;冻结&rdquo; (在 <code>compareDates</code> 内部):</strong></p>
<ul><li><strong>动作:</strong> 按下 <code>F5</code> 键,程序会<strong>再次</strong>停在 <code>compareDates</code> 断点处。</li><li><strong>观察&ldquo;变量&rdquo;窗口:</strong><ul><li><code>a: {day: 15, month: 12, year: 2023}</code></li><li><code>b: {day: 10, month: 12, year: 2023}</code></li></ul></li><li><strong>顿悟时刻:</strong> <code>std::sort</code> 现在正在比较两个<strong>同年份</strong>的日期!</li><li><strong>动作:</strong> 按下 <code>F10</code> 键(<code>if (a.year &lt; b.year)</code> -&gt; <code>false</code>)。</li><li><strong>动作:</strong> 按下 <code>F10</code> 键(<code>if (a.year &gt; b.year)</code> -&gt; <code>false</code>)。</li><li><strong>(关键!)</strong> 高亮条移动到<strong>第24行</strong>(比较月份)。</li><li><strong>动作:</strong> 按下 <code>F10</code> 键(<code>if (a.month &lt; b.month)</code> (<code>12 &lt; 12</code>) -&gt; <code>false</code>)。</li><li><strong>动作:</strong> 按下 <code>F10</code> 键(<code>if (a.month &gt; b.month)</code> (<code>12 &gt; 12</code>) -&gt; <code>false</code>)。</li><li><strong>动作:</strong> 按下 <code>F10</code> 键(<code>return (a.day &lt; b.day)</code> (<code>15 &lt; 10</code>) -&gt; <code>false</code>)。</li><li><strong>顿悟时刻:</strong> <code>sort</code> 知道了 &ldquo;15号&rdquo; 应该在 &ldquo;10号&rdquo; 后面。</li></ul>
<p><strong>(继续按 F5,<code>sort</code> 会调用你的&ldquo;裁判&rdquo;很多次&hellip;)</strong></p>
<p class="maodian"></p><h2>动手试试!(终极挑战:你的&ldquo;学生排名器&rdquo;)</h2>
<p>现在,你来当一次&ldquo;教务处&rdquo;老师。</p>
<p><strong>任务:</strong></p>
<ol><li><strong>设计一个 <code>Student</code> 结构体</strong>:
<ul><li><code>string name;</code></li><li><code>int score;</code> (分数)</li><li><code>int age;</code></li></ul></li><li><strong>创建</strong>一个 <code>vector&lt;Student&gt;</code> 并填入一些数据。</li><li><strong>编写一个&ldquo;规则手册&rdquo;</strong>:<code>bool compareStudents(const Student&amp; a, const Student&amp; b)</code>。</li><li><strong>(关键)</strong> 排序规则是:<ul><li><ol><li>优先按<strong>分数 (<code>score</code>) 降序</strong>(分数高的排前面)。</li></ol></li><li><ol start="2"><li>如果分数<strong>相同</strong>,则按<strong>年龄 (<code>age</code>) 升序</strong>(年龄小的排前面)。</li></ol></li></ul></li><li><strong>调用</strong> <code>std::sort</code>,传入你的&ldquo;规则手册&rdquo;。</li><li><strong>打印</strong>排序后的学生列表。</li></ol>
<p><strong><code>student_sort.cpp</code> (你的 TODO):</strong></p>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;
#include &lt;string&gt;
using namespace std;

// --- TODO 1: Student 结构体 ---
struct Student {
    string name;
    int score;
    int age;
};

// --- TODO 3 &amp; 4: 编写 *新* 的“规则” ---
// (按分数降序, 同分按年龄升序)
// bool compareStudents(const Student&amp; a, const Student&amp; b) {
//   // 1. 先比较分数
//   if (a.score &gt; b.score) return true;// 分数高,排前面
//   if (a.score &lt; b.score) return false; // 分数低,排后面
   
//   // 2. 如果分数相同 (a.score == b.score)
//   //    再比较年龄 (升序)
//   // return a.age &lt; b.age; // 年龄小,排前面
// }

int main() {
    // --- TODO 2: 创建数据 ---
    vector&lt;Student&gt; students = {
      {"Alice", 90, 20},
      {"Bob", 85, 22},
      {"Charlie", 90, 19}, // &lt;-- 和 Alice 同分
      {"David", 70, 21}
    };
   
    cout &lt;&lt; "--- 原始列表 ---" &lt;&lt; endl;
    // (在此处添加 for 循环打印)

    // --- TODO 5: 调用 sort ---
    // std::sort(students.begin(), students.end(), ...);

    cout &lt;&lt; "\n--- 排序后 ---" &lt;&lt; endl;
    // --- TODO 6: 打印结果 ---
    // (在此处添加 for 循环打印)
    // 预测:Charlie (90, 19) 应该在 Alice (90, 20) 之前
   
    return 0;
}
</pre></div>
<blockquote><p>这个挑战让你实践了如何编写一个&ldquo;<strong>多级</strong>&rdquo;比较规则,这是 std::sort 在真实项目中极其常见的用法!</p></blockquote>
<p>以上就是在C++中正确处理日期字符串排序的方法的详细内容,更多关于C++日期字符串排序处理方法的资料请关注琼殿技术社区其它相关文章!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>C++ 字符串去重排序实例代码</li><li>c++的字符串string基本操作大全</li><li>C/C++实现去除字符串中的空格(附带源码)</li><li>C++实现二进制字符串与十六进制字符串相互转换</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: 在C++中正确处理日期字符串排序的方法