用C++将数字转换为指定长度的字符串



我有一些不同长度的数字(如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;
}

相关内容

  • 没有找到相关文章

最新更新