c ++将time_t格式化为std :: string:buffer length的函数?

时间:2011-10-28 22:22:37

标签: c++ time buffer stdstring strftime

我想要一个带有time_t参数和任意格式字符串并对其进行格式化的函数。我想要这样的东西:

std::string GetTimeAsString(std::string formatString, time_t theTime)
{
    struct tm *timeinfo;
    timeinfo = localtime( &theTime);

    char buffer[100];
    strftime(buffer, 100, formatString.c_str(), timeinfo);
    std::string result(buffer);
    return result;
}

然而,我遇到的一个问题是缓冲区长度。我想做一些像formatString * 4这样的缓冲区长度。但我猜你不能动态设置缓冲区长度?也许我可以挑选一个任意大的缓冲区?关于如何使它变得通用,我有点困惑。

如何编写实现此功能的函数?

5 个答案:

答案 0 :(得分:4)

如果你有C ++ 11:

std::string GetTimeAsString(std::string formatString, time_t theTime)
{
    struct tm *timeinfo;
    timeinfo = localtime( &theTime);

    formatString += '\a'; //force at least one character in the result
    std::string buffer;
    buffer.resize(formatstring.size());
    int len = strftime(&buffer[0], buffer.size(), formatString.c_str(), timeinfo);
    while (len == 0) {
        buffer.resize(buffer.size()*2);
        len = strftime(&buffer[0], buffer.size(), formatString.c_str(), timeinfo);
    } 
    buffer.resize(len-1); //remove that trailing '\a'
    return buffer;
}

注意我将formatString作为const引用(为了速度和安全性),并使用结果字符串作为缓冲区,这比以后执行额外的复制更快。我也从与formatstring相同的大小开始,并且每次尝试都会增加一倍,但是这很容易变成更适合strftime结果的东西。

答案 1 :(得分:3)

使用vector<char>作为缓冲区而不是数组。反复增加大小,直到strftime返回非零值。

答案 2 :(得分:2)

我认为你最好的选择是提供一个可能处理绝大多数情况的固定缓冲区,然后对其余情况进行特殊处理。像(未经测试的,除了我头骨里面的湿器):

std::string GetTimeAsString (std::string formatString, time_t theTime) {
    struct tm *timeinfo;
    char buffer[100], *pBuff = buffer;
    int rc, buffSize = 100;

    timeinfo = localtime (&theTime);
    rc = strftime(pBuff, 100, formatString.c_str(), timeinfo);

    // Most times, we shouldn't enter this loop.

    while (rc == 0) {
        // Free previous in it was allocated.

        if (pBuff != buffer)
            delete[] pBuff;

        // Try with larger buffer.

        buffSize += 100;
        pBuff = new char [buffSize];
        rc = strftime(pBuff, buffSize, formatString.c_str(), timeinfo);
    }

    // Make string then free buffer if it was allocated.

    std::string result(pBuff);
    if (pBuff != buffer)
        delete[] pBuff;

    return result;
}
如果提供的缓冲区不够大,

strftime将返回零。在这种情况下,您开始分配更大的缓冲区,直到它适合。

您的未分配缓冲区大小和用于分配大小的增量可以根据您的需要进行调整。这种方法的优点是你不会注意到效率受到影响(尽管可能很小),除了极少数情况 - 没有为绝大多数人做分配。

此外,您可以选择其他方法(例如,+ 10%,加倍等)来增加缓冲区大小。

答案 3 :(得分:1)

带有std::put_time()的C ++ 11解决方案:

std::string GetTimeAsString(std::string formatString, time_t theTime)
{
    struct tm *timeinfo;
    timeinfo = localtime( &theTime);

    std::ostringstream os;
    os << std::put_time(timeinfo, formatString.c_str());
    return os.str();
}

答案 4 :(得分:0)

如果缓冲区的大小太小而无法保存预期结果,则strftime()函数返回0。使用此属性,您可以在堆上分配缓冲区并尝试连续2的幂作为其大小:1,2,4,8,1等等,直到缓冲区足够大。使用2的幂的优点是解决方案的复杂性与结果的长度成对数。

还需要考虑一个特殊情况:格式可能是结果的大小始终为0(例如空格式)。不知道如何处理。