您可能需要注意的一件事是,当您使用stringstream方法时,可能会发生潜在的锁定。至少在Visual Studio 2008附带的STL中,在格式化过程中使用各种语言环境信息时,会取出和释放许多锁。这可能会,也可能不会,对你来说是个问题,这取决于你有多少线程可能同时将数字转换为字符串。 sprintf版本不接受任何锁(至少根据我目前正在开发的锁监控工具...),因此可能“更适合”在并发情况下使用。 我之所以注意到这一点,是因为我的工具最近将“locale”锁作为服务器系统中最具竞争力的锁之一;这让我有点意外,可能会让我修改我一直采用的方法(即从stringstream回到sprintf)...
这个方法既不使用streams也不使用sprintf。除了有锁定问题之外,streams还会产生性能开销,这确实是一个过度的行为。对于streams,开销来自于构造steam和streambuffer的需要。对于sprintf,开销来自于需要解释格式字符串。2即使当 n 为负或者当 n 的字符串表示比 len 长时,这也能工作。这是最快的解决方案。
inline string some_function(int n, int len)
{
string result(len--, '0');
for (int val=(n<0)?-n:n; len>=0&&val!=0; --len,val/=10)
result[len]='0'+val%10;
if (len>=0&&n<0) result[0]='-';
return result;
}
9条答案
按热度按时间ttvkxqim1#
或使用字符串流:
我编译了在arachnoid.com上找到的信息,因为我更喜欢iostreams的类型安全方式,此外,您可以在任何其他输出流上使用此代码。
wnrlj8wa2#
参见snprintf
gzjq41n43#
您可能需要注意的一件事是,当您使用
stringstream
方法时,可能会发生潜在的锁定。至少在Visual Studio 2008附带的STL中,在格式化过程中使用各种语言环境信息时,会取出和释放许多锁。这可能会,也可能不会,对你来说是个问题,这取决于你有多少线程可能同时将数字转换为字符串。sprintf
版本不接受任何锁(至少根据我目前正在开发的锁监控工具...),因此可能“更适合”在并发情况下使用。我之所以注意到这一点,是因为我的工具最近将“locale”锁作为服务器系统中最具竞争力的锁之一;这让我有点意外,可能会让我修改我一直采用的方法(即从
stringstream
回到sprintf
)...camsedfj4#
有很多方法可以做到这一点,最简单的方法是:
qacovj5a5#
这个方法既不使用streams也不使用sprintf。除了有锁定问题之外,streams还会产生性能开销,这确实是一个过度的行为。对于streams,开销来自于构造steam和streambuffer的需要。对于sprintf,开销来自于需要解释格式字符串。2即使当 n 为负或者当 n 的字符串表示比 len 长时,这也能工作。这是最快的解决方案。
wfauudbj6#
stringstream就可以了(正如xtofl所指出的)boost格式是snprintf更方便的替代品。
tf7tbtn27#
这是一个老问题,但由于fmt可能会成为标准,这里有一个额外的解决方案:
请注意,如果在编译时已知所需的宽度,
fmt::format("{:0>6}", n)
同样可以工作。同样,
abs::StrFormat("%06d", n)
也是可行的。boost format是解决此问题的另一个工具:遗憾的是,不支持将可变宽度说明符作为与
%
运算符链接的参数,这需要设置格式字符串(例如const std::string fmt = "%0" + std::to_string(6) + "d";
)。在性能方面,abseil和fmt声称非常有吸引力,而且比boost更快,无论如何,这三种解决方案都应该比
std::stringstream
方法更高效,而且除了std::*printf
家族,它们没有牺牲类型安全。5kgi1eie8#
sprintf是一种类似于C语言的方法,它也可以在C中使用。
在C中,字符串流和流输出格式的组合(参见http://www.arachnoid.com/cpptutor/student3.html)将完成这项工作。
jucafojl9#
从C++ 11开始,您可以执行以下操作:
如果您还需要处理负数,则可以将函数重写如下: