c++将 time_t 格式化为 std::string: 缓冲区长度的函数?

发布于 2024-12-13 01:23:35 字数 493 浏览 0 评论 0原文

我想要一个函数,它将接受 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 作为缓冲区长度的事情。但我猜你不能动态设置缓冲区长度?也许我可以选择一个任意大的缓冲区?我对如何使其通用感到有点困惑。

我怎样才能编写一个函数来实现这个目的?

I want a function that will take a time_t parameter and an arbitrary format string and format it. I want something like this:

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;
}

However one problem I'm running into is the buffer length. I was thinking of doing something like formatString * 4 as the buffer length. But I guess you can't dynamically set the buffer length? Maybe I could pick an arbitrarily large buffer? I'm a little stuck as to how to make it generic.

How can I write a function to achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

作妖 2024-12-20 01:23:35

如果您使用 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 作为常量引用(为了速度和安全),并使用结果字符串作为缓冲区,这比稍后进行额外的复制要快。我也以与格式字符串相同的大小开始,并在每次尝试时将大小加倍,但这很容易更改为更适合 strftime 结果的内容。

If you have 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;
}

Note I take formatString as a const reference, (for speed and safety), and use the result string as the buffer, which is faster than doing an extra copy later. I also start at the same size as the formatstring, and double the size with each attempt, but that's easily changable to something more appropriate for the results of strftime.

放低过去 2024-12-20 01:23:35

使用 std::put_time() 的 C++11 解决方案:

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

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

C++11 solution with std::put_time():

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

    std::ostringstream os;
    os << std::put_time(timeinfo, formatString.c_str());
    return os.str();
}
善良天后 2024-12-20 01:23:35

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

Use a vector<char> for the buffer instead of an array. Repeatedly increase the size until strftime returns non-zero.

深空失忆 2024-12-20 01:23:35

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

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%、加倍等)来增加缓冲区大小。

I would think your best bet would be to provide a fixed buffer that is likely to handle the vast majority of cases, and then do special handling for the rest. Something like (untested, except in the wetware inside my skull):

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 will return zero if the provided buffer wasn't big enough. In that case, you start allocating bigger buffers until it fits.

Your non-allocated buffer size and the increment you use for allocation size can be tuned to your needs. This method has the advantage that you won't notice an efficiency hit (however small it may be) except for the rare cases - no allocation is done for that vast majority.

In addition, you could choose some other method (e.g., +10%, doubling, etc) for increasing the buffer size.

怪我入戏太深 2024-12-20 01:23:35

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

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

The strftime() function returns 0 if the buffer's size is too small to hold the expected result. Using this property, you could allocate the buffer on the heap and try the consecutive powers of 2 as its size: 1, 2, 4, 8, 16 etc. until the buffer is big enough. The advantage of using the powers of 2 is that the solution's complexity is logarithmically proportional to the result's length.

There's also a special case that needs to be thought of: the format might be such that the result's size will always be 0 (e.g. an empty format). Not sure how to handle that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文