2015-05-19 83 views
6

在C++程序中,我想要显示一列浮点值,以便符号,数字和小数点全部对齐。必要时,多个前导零应填充每个值的整个数字部分。例如:如何在C++中显示浮点值的多个前导零?

A column of floating point values: 
    +000.0012 
    -000.
    +000.1235 
    -001.2346 
    +012.3457 
    -123.4568 

我有一个精心评论的测试程序,证明了这个问题。但是,正如我在编辑这篇文章,我找到了答案,我需要在这里:
- Extra leading zeros when printing float using printf?

面临的关键问题是,我使用的"%+04.4f"格式代码时,我应该使用"%+09.4f",因为总场宽度我要的是9:

  • 1为标志
  • 3为全数字
  • 1小数点
  • 4为小数位

我没有足够的声望点评论这篇文章,所以在这里感谢你,@AndiDog。

我仍然不知道如何使用流格式化标志获得多个前导零。但那是另一天的战斗。现在我会坚持使用printf和stream的混合。

+0

请参阅:http://stackoverflow.com/questions/1714515/how-can-i-pad-an-int-with-leading-zeros-when-using-cout-operator – NathanOliver

+2

使用std :: setfill(' 0')和std :: setw() – 911

+0

我不认为'setfilll'将在这种情况下工作。使用'0'作为填充字符,他的第一个结果最终会像'00 + 0.0012'一样,而不是所有数字前面的'+'。 –

回答

8

一对夫妇的意见都提到std::setfill('0')std::setw。虽然这些必要的,但它们不足以完成任务。例如,此代码:

std::cout << std::setfill('0') << std::setw(7) << std::showpos << 0.012; 

将生成:0+0.012作为其输出。这显然不是我们想要的。

我们需要添加std::internal标志来告诉流插入“内部填充” - 即,填充应的符号和数字的休息,所以代码之间插入这样的:

std::cout << std::setfill('0') << std::setw(7) << std::internal << std::showpos << 0.012; 

...产生我们想要的输出:+00.012

另请注意,填充字符是“粘滞”的,所以如果您在使用std::setw与数字和非数字类型之间交替使用,则您可能需要/每次都要更改它。否则,诸如std::cout << setw(12) << name;之类的结果将产生如下结果:0000000Jerry,这也是很少需要的。

为了确保我们总是得到相同的一些地方,小数点后,我们还需要设置std::fixed标志,并与std::setprecision指定的名额,如:

#include <iostream> 
#include <iomanip> 
#include <vector> 

int main() { 
    std::vector<double> values { 0.1234, 1.234, 1.5555 }; 

    for (auto d : values) 
     std::cout << std::internal << std::showpos << std::setw(9) 
        << std::setprecision(3) << std::setfill('0') << d << "\n"; 
} 

将会产生我相信希望输出:

+0000.123 
+0001.234 
+0001.556 

有一个情况下,你不会得到,虽然对齐结果是这样的:如果你有一个数太大,无法在提供的字段,所有之前的地方decim点仍将被打印。例如,如果我们将1e10添加到前面的代码要打印的数字列表中,则会将其打印为:+10000000000.000,这显然不会与其他对齐。

处理这个问题的一个显而易见的方法就是忍受它,并且如果它经常出现足以关心的问题,请增大字段大小以容纳更大的数字。

另一种可能性是使用固定的符号,只有数字低于某个阈值,并切换到(例如)科学记数法以获取较大的数字。

至少在我的经验中,这样的代码倾向于主要用于财务数据,在这种情况下后者通常是不可接受的。

3

要显示正号,可以使用std :: showpos。

要显示前导零,可以使用std :: setw(n)和std :: setfill('0')。

要显示零后的数字,请使用std :: setprecision(m)。

要显示+符号和第一个数字之间的零,可以使用std :: internal。

要将数字保持在固定位置,请使用std :: fixed。

#include <iostream>  // std::cout, std::fixed 
#include <iomanip>  // std::setprecision 

int main() { 
    double f =1.234; 
    double g =-12.234; 
    std::cout << std::showpos<< std::internal << std::fixed << std::setprecision(4)<<std::setw(9) <<std::setfill('0') << f << '\n'; 
    std::cout <<std::setw(9)<< std::setfill('0') <<g<<"\n"; //repeat these for a new number 
    return 0; 
    } 


//output: 
//+001.2340 
//-012.2340 
+0

您的代码打印出'000 + 1.234' – hyde

+0

您应该使用std :: fixed来显示前导零。打印线将变为: std :: cout << std :: showpos << std :: fixed << std :: setprecision(4)<< std :: setw(9)<< std :: setfill('0 ')<< f <<'\ n'; –

+1

我的不好,你还需要std :: internal。我现在编辑示例。 –

0

我现在该怎么做到这一点的唯一方法是显示符号,然后设置填充,宽度和精度后,你已经显示的迹象显示正值。您还需要格式标志设置为ios::fixed

#include <iostream> 
#include <iomanip> 
using namespace std; 

int main() 
{ 
    float x[] = { 000.0012, .0123, .1235, 1.2346, 12.3457, 123.4568 }; 
    cout.setf(ios::fixed); 
    for (int i = 0; i < 6; i++) 
     cout << (x[i] > 0 ? '+' : '-') << setfill('0') << setw(8) << setprecision(4) << abs(x[i]) << endl; 
    return 0; 
} 

显示

+000.0012 
-000.
+000.1235 
-001.2346 
+012.3457 
-123.4568 
+0

这不是“唯一的方法”。查看其他答案 –

+0

@CaioOliveira我从来没有说过这是唯一的方法。这是我写这篇文章的唯一途径。 – NathanOliver