在运算符中设置整个矢量的精度/场宽<<

Setting precision/field width in operator<< for an entire vector

提问人:Museful 提问时间:4/30/2020 最后编辑:Museful 更新时间:4/30/2020 访问量:167

问:

下面的代码将向量打印到 。std::cout

struct vect {
    double x;
    double y;
};
std::ostream& operator<<(std::ostream& os, vect v){
    os << "[" << v.x << " " << v.y << "]";
    return os;
}

int main(){
    vect v = {1.0, 2.0};
    std::cout << v << std::endl;
    return 0;
}

控制每个字段的宽度/精度的好方法是什么?我可以用以下方式对其进行硬编码:operator<<

std::ostream& operator<<(std::ostream& os, vect v){
    os << "[" << std::setprecision(3) << std::setw(7) << v.x << " " << std::setprecision(3) << std::setw(7) << v.y << "]";
    return os;
}

但我宁愿从外面控制它:

std::cout << std::setprecision(3) << std::setw(7) << v << std::endl;

但是,我认为这只会设置向量第一个场的精度和宽度。

我的想法是首先在开头“getw”和“getprecision”,然后将它们保留到其他字段。有没有办法从流中检索这些东西,这个基本设计是否基于正确的假设?(我对 iomanipulators 的工作原理不是很有信心;我只知道在数据之前发送。operator<<std::setw

C++ C++17 IOstream cout iomanip

评论

0赞 Museful 4/30/2020
@Ron 谢谢;我知道那件事。但是在打印下一个字段后,修改会恢复,不是吗?
0赞 Kenny Ostrom 4/30/2020
令人困惑的是,您将类型命名为与标准库类型相同的类型,这是非常不同的。
0赞 Museful 4/30/2020
@KennyOstrom同意。这是一个虚拟的名字,我从不使用.会改变。using namespace
0赞 Kenny Ostrom 4/30/2020
当我测试它时,精度似乎在流上持续存在。
0赞 Museful 4/30/2020
@Ron 哦,好吧。但由于不粘,我想这个问题或多或少不受影响。std::setw

答:

0赞 Museful 4/30/2020 #1

这就是我所做的。这是一个声音设计吗?

std::ostream& operator<<(std::ostream& os, vect v){
    auto p = os.precision();
    auto w = os.width();
    os << "[" << std::setprecision(p) << std::setw(w) << v.x << " " << std::setprecision(p) << std::setw(w) << v.y << "]";
    return os;
}

评论

0赞 cigien 4/30/2020
这已经在你的问题中了吗?如果没有,请将其编辑到问题中,不要将其作为答案发布。
0赞 Kenny Ostrom 4/30/2020
啊,是的,这基本上就是我所做的,有一些细微的区别。是否希望宽度应用于左括号而不是右括号?你不需要精确。
0赞 Marshall Clow 4/30/2020 #2

但是,我认为这只会设置向量第一个场的精度和宽度。

我认为您应该在花更多时间尝试“解决”它之前验证这一点。

(不是真正的答案,但我不能在评论中引用等)

评论

0赞 Museful 4/30/2020
所以我错了,但不是.我认为,普遍问题仍然存在。std::setprecisionstd::setw
0赞 Marshall Clow 4/30/2020
但现在你不“思考”了,你知道的。好多了。
0赞 Museful 4/30/2020
我错了。我的问题实际上应该是关于打印对齐矩阵的。这是想要控制宽度的唯一原因。
1赞 Kenny Ostrom 4/30/2020 #3

如注释中所述,setprecision 仍然存在,但 setw 不会。

假设您希望 setw 应用于合成类型中的每个字段,而不是应用于其周围的格式字符。为此,请查看 width 属性,然后为每个数值字段设置该属性。

#include <iostream>
#include <iomanip>

struct coordinate {
    double x;
    double y;
};

std::ostream& operator<<(std::ostream& os, coordinate p) {
    auto w = os.width();
    os << std::setw(0) << "["  // we don't want the width yet
       << std::setw(w) << p.x  // set width on specific field
       << " " 
       << std::setw(w) << p.y  // set width on specific field
       << "]";
    return os;
}

int main() {
    coordinate value = { 1.000019, 2.000019 };
    std::cout << std::setprecision(3) << std::setw(7) << value << std::endl;
    std::cout << std::setprecision(6) << std::setw(7) << value << std::endl;
    std::cout << std::setprecision(1) << std::setw(3) << value << std::endl;
    return 0;
}

输出:

[      1       2]  
[1.00002 2.00002]  
[  1   2]