字符串标记化,按标记而不是分隔符拆分

String tokenisation, split by token not separator

本文关键字:分隔符 拆分 字符串      更新时间:2023-10-16

我看到了如何以传统方式标记字符串(即这里的答案如何在C++中标记字符串?)但是我如何通过其标记拆分字符串,也包括它们?

例如,

给定一个日期/时间图片,例如 yyyy\MMM\dd HH:mm:ss,我想分成一个包含以下内容的数组:

"yyyy", "", "MMM", "", "dd", " " , "HH", ":", "mm", ":", "ss"

在此示例中,"令牌"是 yyyy、MMM、dd、HH、mm、ss。 我不知道分隔符是什么,只知道令牌是什么。 但是,分隔符需要出现在最终结果中。 令牌的完整列表是:

        "yyyy"  // – four-digit year, e.g. 1996
        "yy"    // – two-digit year, e.g. 96
        "MMMM"  // – month spelled out in full, e.g. April
        "MMM"   // – three-letter abbreviation for month, e.g. Apr
        "MM"    // – two-digit month, e.g. 04
        "M"     // – one-digit month for months below 10, e.g. 4
        "dd"    // – two-digit day, e.g. 02
        "d"     // – one-digit day for days below 10, e.g. 2
        "ss"    // - two digit second
        "s"     // - one-digit second for seconds below 10
        "mm"    // - two digit minute
        "m"     // - one-digit minute for minutes below 10
        "tt"    // - AM/PM designator
        "t"     // - first character of AM/PM designator
        "hh"    // - 12 hour two-digit for hours below 10
        "h"     // - 12 hour one-digit for hours below 10
        "HH"    // - 24 hour two-digit for hours below 10
        "H"     // - 24 hour one-digit for hours below 10

我注意到标准库 std::string 在解析和标记方面不是很强,我不能使用 boost。 有没有一个严格的、惯用的解决方案? 我不想为此打破 C 风格的算法。 性能不是考虑因素。

也许 http://www.cplusplus.com/reference/cstring/strtok/就是你要找的,有一个有用的例子。

但是,它会吃掉分隔符。您可以通过比较基指针和生成的字符串来解决此问题,并按字符串长度向前移动。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <sstream>
int main() 
{
    char data[] = "yyyy\MMM\dd HH:mm:ss";
    std::vector<std::string> tokens;
    char* pch = strtok (data,"\:");                                        // pch holds 'yyyy'
    while (pch != NULL)
    {
        tokens.push_back(pch);
        int delimeterIndex = static_cast<int>(pch - data + strlen(pch));    // delimeter index: 4, 8, ...
        std::stringstream ss;
        ss << delimeterIndex;
        tokens.push_back(ss.str());
        pch = strtok (NULL,"\:");                                          // pch holds 'MMM', 'dd', ...
    }
    for (const auto& token : tokens)
    {
        std::cout << token << ", ";
    }
}

这给出了以下输出:

yyyy, 4, MMM, 8, dd HH, 14, mm, 17, ss, 20,