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

fxnxkyjh  于 2023-01-28  发布在  其他
关注(0)|答案(9)|浏览(170)

我有一些不同长度的数字(如1、999、76492等),我想将它们全部转换为具有相同长度的字符串(例如,如果长度为6,则这些字符串将为:“000001”、“000999”、“076492”)。
换句话说,我需要给数字加上正确数量的前导零。

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

C++中有这样的函数吗?

ttvkxqim

ttvkxqim1#

或使用字符串流:

#include <sstream>
#include <iomanip>

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

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

wnrlj8wa

wnrlj8wa2#

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

参见snprintf

gzjq41n4

gzjq41n43#

可能需要注意的一件事是,当您使用stringstream方法时,可能会发生潜在的锁定。至少在Visual Studio 2008附带的STL中,在格式化过程中使用各种语言环境信息时,会取出和释放许多锁。这可能会,也可能不会,对你来说是个问题,这取决于你有多少线程可能同时将数字转换为字符串。
sprintf版本不接受任何锁(至少根据我目前正在开发的锁监控工具...),因此可能“更适合”在并发情况下使用。
我之所以注意到这一点,是因为我的工具最近将“locale”锁作为服务器系统中最具竞争力的锁之一;这让我有点意外,可能会让我修改我一直采用的方法(即从stringstream回到sprintf)...

camsedfj

camsedfj4#

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

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

qacovj5a5#

这个方法既不使用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;
}
wfauudbj

wfauudbj6#

stringstream就可以了(正如xtofl所指出的)boost格式是snprintf更方便的替代品。

tf7tbtn2

tf7tbtn27#

这是一个老问题,但由于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 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家族,它们没有牺牲类型安全。

5kgi1eie

5kgi1eie8#

sprintf是一种类似于C语言的方法,它也可以在C中使用。
在C
中,字符串流和流输出格式的组合(参见http://www.arachnoid.com/cpptutor/student3.html)将完成这项工作。

jucafojl

jucafojl9#

从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;
}

相关问题