如何对std :: to_string函数进行零预填充?

7
在C++中使用std::to_string(),如何预填一个从整数转换而来的字符串?我尝试使用#include 和std::setfill('0'),但它没有起作用。这是简单的测试代码。
#include <iostream>
#include <string>
//#include <iomanip> // setw, setfill below doesn't work

int main()
{
int i;
for (i=0;i<20;i++){
    std::cout << "without zero fill : " << std::to_string(i) << ", with zero fill : " << std::to_string(i) << std::endl;
    //std::cout << std::setw(3) << std::setfill('0') << "without zero fill : " << std::to_string(i) << ", with zero fill : " << std::to_string(i) << std::endl;  // doesn't work
}
}

我想做的是将一些数字转换为字符串,但其中一些需要用零填充,而其他数字不需要(我实际上是用它来创建文件名)。应该如何做呢?(我不知道为什么这个问题不能像在C语言中使用%0d或者%04d格式说明符那样简单。)
补充:从添加前导零到字符串,不使用(s)printf,我找到了以下内容:
int number = 42;
int leading = 3; //6 at max
std::to_string(number*0.000001).substr(8-leading); //="042"

这种方法对我来说可行,但我更希望有更自然的解决方案,而不是像这样的技巧性方法。

2个回答

8

ostringstream 似乎有些过度,你可以直接插入所需数量的零:

template<typename T/*, typename = std::enable_if_t<std::is_integral_v<T>>*/>
std::string to_string_with_zero_padding(const T& value, std::size_t total_length)
{
    auto str = std::to_string(value);
    if (str.length() < total_length)
        str.insert(str.front() == '-' ? 1 : 0, total_length - str.length(), '0');
    return str;
}

如果value是负数,或者Tchar或相关类型,则此函数也可以正确地工作。


好主意。但是有一些建议:1)取消模板化(避免在未更改的文件中进行不必要的重新编译),2)添加默认值以不填充,如果未指定,则3)参数化使用的填充字符。std::string toString (int val, std::size_t padLen = 0, char padChar = '0') - automorphic
@automorphic 我认为它不应该成为非模板函数。除了 int 之外,我们还有许多不同的整数类型(std::to_string 有9个重载版本适用于不同的类型)。 - Evg
明白了。对于大多数项目来说,int 就足够了。去掉模板化并不是真正的改进 - 只是简化了代码。但另外两个改进才是重要的,因为它们可以在不改变逻辑的情况下扩展代码的用途。谢谢! - automorphic

3

如果不想使用std::to_string(),可以使用std::ostringstream。IO操作符可与std::ostringstream一起使用。

#include <iostream>
#include <sstream>
#include <iomanip>

int main()
{
   for ( int i = 1; i <= 10; ++i )
   {
      std::ostringstream str;
      str << std::setw(3) << std::setfill('0') << i;
      std::cout << str.str() << std::endl;
   }
}

输出:
001
002
003
004
005
006
007
008
009
010

请访问https://ideone.com/ay0Xzp查看其运行效果。


我明白了,谢谢。但是如果我想要最终值作为“字符串”而不是“ostringstream”,该怎么办?我想将其用作文件名的一部分。 - Chan Kim
我明白了,那个有效!也许我应该理解这个ostringstream。如果我在循环外部声明它,为什么输出会合并? - Chan Kim
1
@ChanKim 这样做是因为你要向 ostringstream 对象添加内容。如果将其定义在循环内部,每次迭代都会构造一个新对象。 - R Sahu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接