将数字转换为C ++中具有指定长度的字符串

时间:2008-10-22 11:31:24

标签: c++ integer stdstring

我有一些不同长度的数字(如1,999,76492,依此类推),我想将它们全部转换为具有共同长度的字符串(例如,如果长度为6,那么这些字符串将是: '000001','000999','076492')。

换句话说,我需要在数字中添加正确数量的前导零。

int n = 999;
string str = some_function(n,6);
//str = '000999'

在C ++中是否有这样的函数?

8 个答案:

答案 0 :(得分:56)

或使用stringstreams:

#include <sstream>
#include <iomanip>

std::stringstream ss;
ss << std::setw(10) << std::setfill('0') << i;
std::string s = ss.str();

我编译了我在arachnoid.com上找到的信息,因为我更喜欢iostreams的类型安全方式。此外,您可以在任何其他输出流上使用此代码。

答案 1 :(得分:13)

char str[7];
snprintf (str, 7, "%06d", n);

请参阅snprintf

答案 2 :(得分:8)

可能希望了解的一件事是当您使用stringstream方法时可能会发生的潜在锁定。在Visual Studio 2008附带的STL中,至少有许多锁被取出并在格式化过程中使用各种区域设置信息时被释放。这可能会或可能不会成为您的问题,具体取决于您可能同时将数字转换为字符串的线程数...

sprintf版本没有采取任何锁定(至少根据我目前正在开发的锁定监视工具...),因此在并发情况下可能会“更好”。

我之所以注意到这一点,是因为我的工具最近吐出了'locale'锁,因为它是我服务器系统中最具竞争力的锁之一;这有点令人意外,可能会让我修改我一直采取的方法(即从sprintf转回stringstream)......

答案 3 :(得分:3)

stringstream会做(as xtofl pointed out)。 Boost format是更方便的替代snprintf。

答案 4 :(得分:3)

此方法不使用stream或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;
}

答案 5 :(得分:2)

有很多方法可以做到这一点。最简单的是:

int n = 999;
char buffer[256]; sprintf(buffer, "%06d", n);
string str(buffer);

答案 6 :(得分:1)

sprintf是类似C语言的方式,也可以在C ++中使用。

在C ++中,字符串流和流输出格式的组合(参见http://www.arachnoid.com/cpptutor/student3.html)将完成这项工作。

答案 7 :(得分:0)

这是一个旧线程,但是由于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系列之外,它们都不会牺牲类型安全性。