我有一些不同长度的数字(如 1、999、76492 等),我想将它们全部转换为具有公共长度的字符串(例如,如果长度为 6,那么这些字符串将是: '000001 '、'000999'、'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();
我整理了在 arachnoid.com 上找到的信息,因为我更喜欢 iostream 的类型安全方式。此外,您同样可以在任何其他输出流上使用此代码。
char str[7];
snprintf (str, 7, "%06d", n);
参见snprintf
您可能想要注意的一件事是,当您使用
stringstream
方法时可能会发生潜在的锁定。至少在 Visual Studio 2008 附带的 STL 中,由于格式化过程中使用了各种区域设置信息,因此取消和释放了许多锁。这对您来说可能是问题,也可能不是问题,具体取决于您有多少线程可能同时将数字转换为字符串......
sprintf
版本不采用任何锁(至少根据我目前正在开发的锁监控工具......),因此在并发情况下使用可能“更好”。
我之所以注意到这一点,是因为我的工具最近将“区域设置”锁吐出为我的服务器系统中竞争最激烈的锁之一;这有点令人惊讶,可能会让我修改我一直在采取的方法(即从
sprintf
回到 stringstream
)...
有很多方法可以做到这一点。最简单的是:
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;
}
stringstream 就可以了(正如 xtofl 指出的那样)。 Boost 格式 是 snprintf 的更方便的替代品。
这是一个旧线程,但由于 fmt 可能会将其纳入标准,这里有一个额外的解决方案:
#include <fmt/format.h>
int n = 999;
const auto str = fmt::format("{:0>{}}", n, 6);
请注意,当编译时已知所需宽度时,
fmt::format("{:0>6}", n)
也同样有效。另一种选择是abseil:
#include <absl/strings/str_format.h>
int n = 999;
const auto str = absl::StrFormat("%0*d", 6, n);
再次强调,
abs::StrFormat("%06d", n)
是可能的。 boost format 是解决此问题的另一个工具:
#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";
)。
在性能方面,abseil和fmt号称非常有吸引力,而且比boost更快。无论如何,所有三种解决方案都应该比
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;
}
std::format
(godbolt):
int n = 999;
std::string str = std::format("{:0{}}", n, 6);
// str == "000999"