【问题标题】:Setting precision/field width in operator<< for an entire vector在 operator<< 中为整个向量设置精度/字段宽度
【发布时间】:2020-08-14 23:38:28
【问题描述】:

下面的代码将一个向量打印到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&lt;&lt;:

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;

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

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

【问题讨论】:

  • @Ron 谢谢;我知道。但是在打印下一个字段后修改会恢复,不是吗?
  • 令人困惑的是,您将类型命名为与标准库类型相同的名称,而标准库类型却截然不同。
  • @KennyOstrom 同意。这是一个假名字,我从不使用using namespace。会改变的。
  • 当我测试它时,精度似乎在流中持续存在。
  • @Ron 哦,好的。但由于std::setw 不粘,我猜这个问题或多或少不受影响。

标签: c++ c++17 iostream cout iomanip


【解决方案1】:

如 cmets 中所述,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]

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 这已经是您的问题了?如果不是,请将其编辑到问题中,不要将其作为答案发布。
    • 啊,是的,这基本上就是我所做的,只是有一些细微的差别。您希望宽度适用于左括号而不适用于右括号吗?你不需要精确。
    【解决方案3】:

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

    我认为您应该先验证这一点,然后再花更多时间尝试“解决”它。

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

    【讨论】:

    • 所以我对 std::setprecision 的看法是错误的,但对 std::setw 的看法却不是。我认为一般问题仍然存在。
    • 但现在你不会“思考”,你知道。好多了。
    • 我错了。我的问题实际上应该是关于打印对齐的矩阵。这是想要控制宽度的唯一原因。
    猜你喜欢
    • 2014-02-16
    • 2017-01-19
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    • 2021-12-18
    • 1970-01-01
    • 2015-04-29
    • 2022-07-11
    相关资源
    最近更新 更多