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

时间:2016-04-25 10:39:53

标签: c++ string tokenize

我看到如何以传统方式标记字符串(即此答案How do I tokenize a string in 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风格的算法来做这件事。绩效不是一个考虑因素。

1 个答案:

答案 0 :(得分:1)

或许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,