我有一些不同长度的数字(如1、999、76492等),我想将它们全部转换为具有公共长度的字符串(例如,如果长度为6,则这些字符串将为:'0000001'、'0000999'、'076492')。
换句话说,我需要在数字上加上正确数量的前导零。
int n = 999;
string str = some_function(n,6);
//str = '000999'
C++中有这样的函数吗?
或使用字符串流:
#include <sstream>
#include <iomanip>
std::stringstream ss;
ss << std::setw(10) << std::setfill('0') << i;
std::string s = ss.str();
我整理了我在蜘蛛网上找到的信息,因为我更喜欢iostream的类型安全方式。此外,您可以在任何其他输出流上同样使用此代码。
char str[7];
snprintf (str, 7, "%06d", n);
请参阅snprintf
您可能需要注意的一件事是,当您使用stringstream
方法时,可能会发生潜在的锁定。至少在VisualStudio2008附带的STL中,由于在格式化过程中使用了各种区域设置信息,因此会取出并释放许多锁。这可能是一个问题,也可能不是,这取决于您有多少线程可能同时将数字转换为字符串。。。
sprintf
版本不带任何锁(至少根据我目前正在开发的锁监控工具…),因此在并发情况下使用可能"更好"。
我之所以注意到这一点,是因为我的工具最近抛出了"locale"锁,认为它是我的服务器系统中争夺锁最多的锁之一;这让我有点惊讶,可能会让我修改我一直采用的方法(即从stringstream
移回sprintf
)。。。
有很多方法可以做到这一点。最简单的是:
int n = 999;
char buffer[256]; sprintf(buffer, "%06d", n);
string str(buffer);
此方法既不使用流也不使用sprintf。除了存在锁定问题之外,流还会带来性能开销,而且确实是一种过度使用。对于流,开销来自于构建蒸汽和流缓冲区的需要。对于sprintf,开销来自于需要解释格式字符串。即使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;
}
字符串流就可以了(正如xtofl所指出的)。Boost格式是snprintf更方便的替代品。
这是一个旧线程,但由于fmt可能会将其纳入标准,因此这里有一个额外的解决方案:
#include <fmt/format.h>
int n = 999;
const auto str = fmt::format("{:0>{}}", n, 6);
注意,当在编译时已知所需宽度时,fmt::format("{:0>6}", n)
同样工作良好。另一种选择是下降:
#include <absl/strings/str_format.h>
int n = 999;
const auto str = absl::StrFormat("%0*d", 6, n);
同样,abs::StrFormat("%06d", n)
是可能的。boost格式是解决这个问题的另一个工具:
#include <boost/format.hpp>
int n = 999;
const auto str = boost::str(boost::format("%06d") % n);
不幸的是,不支持将可变宽度说明符作为与%
运算符链接的参数,这需要设置格式字符串(例如const std::string fmt = "%0" + std::to_string(6) + "d";
)。
在性能方面,下降和fmt声称非常有吸引力,并且比助推更快。在任何情况下,所有三种解决方案都应该比std::stringstream
方法更有效,并且除了std::*printf
系列之外,它们不会牺牲类型安全性。
sprintf是一种类似C的方法,它也适用于C++。
在C++中,字符串流和流输出格式的组合(请参阅http://www.arachnoid.com/cpptutor/student3.html)会完成这项工作。
从C++11,您可以执行:
string to_string(unsigned int number, int length) {
string num_str = std::to_string(number);
if(num_str.length() >= length) return num_str;
string leading_zeros(length - num_str.length(), '0');
return leading_zeros + num_str;
}
如果你还需要处理负数,你可以重写如下函数:
string to_string(int number, int length) {
string num_str = std::to_string(number);
if(num_str.length() >= length) return num_str;
string leading_zeros(length - num_str.length(), '0');
//for negative numbers swap the leading zero with the leading negative sign
if(num_str[0] == '-') {
num_str[0] = '0';
leading_zeros[0] = '-';
}
return leading_zeros + num_str;
}