C++中将数字转换为指定长度的字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/225362/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert a number to a string with specified length in C++
提问by Degvik
I have some numbers of different length (like 1, 999, 76492, so on) and I want to convert them all to strings with a common length (for example, if the length is 6, then those strings will be: '000001', '000999', '076492').
我有一些不同长度的数字(如 1、999、76492 等),我想将它们全部转换为具有共同长度的字符串(例如,如果长度为 6,则这些字符串将是:'000001' , '000999', '076492')。
In other words, I need to add correct amount of leading zeros to the number.
换句话说,我需要为数字添加正确数量的前导零。
int n = 999;
string str = some_function(n,6);
//str = '000999'
Is there a function like this in C++?
C++中有这样的函数吗?
回答by xtofl
or using the stringstreams:
或使用字符串流:
#include <sstream>
#include <iomanip>
std::stringstream ss;
ss << std::setw(10) << std::setfill('0') << i;
std::string s = ss.str();
I compiled the information I found on arachnoid.combecause I like the type-safe way of iostreams more. Besides, you can equally use this code on any other output stream.
我编译了我在arachnoid.com 上找到的信息,因为我更喜欢 iostreams 的类型安全方式。此外,您可以在任何其他输出流上同样使用此代码。
回答by Len Holgate
One thing that you maywant to be aware of is the potential locking that may go on when you use the stringstream
approach. In the STL that ships with Visual Studio 2008, at least, there are many locks taken out and released as various locale information is used during formatting. This may, or may not, be an issue for you depending on how many threads you have that might be concurrently converting numbers to strings...
您可能需要注意的一件事是使用该stringstream
方法时可能会发生的潜在锁定。至少,在 Visual Studio 2008 附带的 STL 中,由于在格式化过程中使用了各种区域设置信息,因此取出和释放了许多锁。这对您来说可能是也可能不是问题,具体取决于您有多少线程可能同时将数字转换为字符串...
The sprintf
version doesn't take any locks (at least according to the lock monitoring tool that I'm developing at the moment...) and so might be 'better' for use in concurrent situations.
该sprintf
版本不带任何锁(至少根据我目前正在开发的锁监控工具......),因此在并发情况下使用可能“更好”。
I only noticed this because my tool recently spat out the 'locale' locks as being amongst the most contended for locks in my server system; it came as a bit of a surprise and may cause me to revise the approach that I've been taking (i.e. move back towards sprintf
from stringstream
)...
我之所以注意到这一点,是因为我的工具最近吐出了“语言环境”锁,因为它是我的服务器系统中竞争最激烈的锁之一;这有点令人惊讶,可能会导致我修改我一直采用的方法(即sprintf
从移回stringstream
)...
回答by Pramod
There are many ways of doing this. The simplest would be:
有很多方法可以做到这一点。最简单的是:
int n = 999;
char buffer[256]; sprintf(buffer, "%06d", n);
string str(buffer);
回答by PW.
stringstream will do (as xtofl pointed out). Boost formatis a more convenient replacement for snprintf.
stringstream 会做(正如 xtofl 指出的那样)。Boost 格式是 snprintf 的更方便的替代品。
回答by sep
This method doesn't use streams nor sprintf. Other than having locking problems, streams incur a performance overhead and is really an overkill. For streams the overhead comes from the need to construct the steam and stream buffer. For sprintf, the overhead comes from needing to interpret the format string. This works even when nis negative or when the string representation of nis longer than len. This is the FASTEST solution.
此方法不使用流或 sprintf。除了有锁定问题之外,流还会产生性能开销,而且确实是一种矫枉过正。对于流,开销来自需要构建流和流缓冲区。对于 sprintf,开销来自需要解释格式字符串。这样,即使ñ为负或当的字符串表示ñ长于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;
}
回答by lubgr
This is an old thread, but as fmtmight make it into the standard, here is an additional solution:
这是一个旧线程,但由于fmt可能会使其成为标准,这里是一个额外的解决方案:
#include <fmt/format.h>
int n = 999;
const auto str = fmt::format("{:0>{}}", n, 6);
Note that the fmt::format("{:0>6}", n)
works equally well when the desired width is known at compile time. Another option is abseil:
请注意,fmt::format("{:0>6}", n)
当在编译时已知所需的宽度时,该方法同样有效。另一种选择是abseil:
#include <absl/strings/str_format.h>
int n = 999;
const auto str = absl::StrFormat("%0*d", 6, n);
Again, abs::StrFormat("%06d", n)
is possible. boost formatis another tool for this problem:
再次,abs::StrFormat("%06d", n)
是可能的。boost 格式是解决这个问题的另一个工具:
#include <boost/format.hpp>
int n = 999;
const auto str = boost::str(boost::format("%06d") % n);
Unfortunately, variable width specifier as arguments chained with the %
operator are unsupported, this requires a format string setup (e.g. const std::string fmt = "%0" + std::to_string(6) + "d";
).
不幸的是,%
不支持可变宽度说明符作为与运算符链接的参数,这需要格式字符串设置(例如const std::string fmt = "%0" + std::to_string(6) + "d";
)。
In terms of performance, abseil and fmt claim to be very attractive and faster than boost. In any case, all three solutions should be more efficient than std::stringstream
approaches, and other than the std::*printf
family, they do not sacrifice type safety.
在性能方面,abseil 和 fmt 声称非常有吸引力,而且比 boost 更快。无论如何,所有三种解决方案都应该比std::stringstream
方法更有效,并且除了std::*printf
家庭之外,它们不会牺牲类型安全。
回答by Chris Johnson
sprintf is the C-like way of doing this, which also works in C++.
sprintf 是一种类似 C 的方法,它也适用于 C++。
In C++, a combination of a stringstream and stream output formatting (see http://www.arachnoid.com/cpptutor/student3.html) will do the job.
在 C++ 中,字符串流和流输出格式的组合(参见http://www.arachnoid.com/cpptutor/student3.html)将完成这项工作。