2017-08-10 94 views
0

我正在考虑在我们的项目中提出以下作为sprintf/snprintf的替代方案。strprintf - 这个实现是否安全和便携?

其动机是消除考虑缓冲区大小的需要,并尽可能地保留原始的便利性。

std::string strprintf(const char *fromat, ...) 
{ 
    std::string s; 
    s.resize(128); // best guess 
    char *buff = const_cast<char *>(s.data()); 

    va_list arglist; 
    va_start(arglist, fromat); 
    auto len = vsnprintf(buff, 128, fromat, arglist); 
    va_end(arglist); 

    if (len > 127) 
    { 
     va_start(arglist, fromat); 
     s.resize(len + 1); // leave room for null terminator 
     buff = const_cast<char *>(s.data()); 
     len = vsnprintf(buff, len+1, fromat, arglist); 
     va_end(arglist); 
    } 
    s.resize(len); 
    return s; // move semantics FTW 
} 

此代码是否有任何固有问题?

使用示例:

auto s = strprintf("Hello %d world", 777); 
+0

*“方便的原始”* - 这是非常值得商榷的。 – StoryTeller

+0

看起来技术上是正确的,但如果缓冲区超过128字节上限,性能似乎不是很高。它再次调用vsnprintf,使该函数花费两倍的时间。你必须权衡这里的便利性和性能。此外,您返回的字符串将被再次复制 - 这进一步影响了性能。 – Freakyy

+0

返回值具有移动语义,所以不应该有另一个副本。 – CplusPuzzle

回答

0

原来,有对这个已经在这里很多讨论:

std::string formatting like sprintf

主观上,我的版本看起来还是比大多数的东西有更简洁,而且它的功能与该线程上的一些建议解决方案相同。