更改复数输出格式

时间:2011-02-14 06:59:07

标签: c++ complex-numbers

C ++标准库中有complex<>模板,它有一个重载的&lt;&lt;运算符,以便以(real_part,im_part)格式输出复数。我需要更改该运算符对复数的行为,以便将输出格式更改为完全不同的输出格式。具体来说,我需要输出格式为real_part\tim_part。我该怎么做?

5 个答案:

答案 0 :(得分:7)

没有直接替换operator <<的方法,但您确实有一些选择。首先,您可以编写自己的函数来打印复数:

template <typename T> void PrintComplex(const complex<T>& c) {
    /* ... */
}

如果你仍想使用漂亮的流语法,那么你可以做的一个技巧是创建一个包装complex的包装类,然后定义自己的operator <<打印出来一种不同的方式。例如:

template <typename T> class ComplexPrinter {
public:
    /* Conversion constructor allows for implicit conversions from
     * complex<T> to ComplexPrinter<T>.
     */
    ComplexPrinter(const complex<T>& value) : c(value) {
        // Handled in initializer list
    }

    /* Output the complex in your own format. */
    friend ostream& operator<< (ostream& out, const ComplexPrinter& cp) {
        /* ... print in your own format ... */
    }

private:
    complex<T> c;
};

一旦你有了这个,就可以写出像

这样的东西
cout << ComplexPrinter<double>(myComplex) << endl;

你可以通过写一个像这样的函数来使这个更清晰:

template <typename T>
ComplexPrinter<T> wrap(const complex<T>& c) {
    return ComplexPrinter<T>(c);
}

然后让你写

cout << wrap(myComplex) << endl;

哪个不完美,但非常好。

关于上述包装器需要注意的一点是,它设置了隐式转换构造函数,以便将complex<T>转换为ComplexPrinter<T> s。这意味着,如果您有vector< complex<T> >,则可以通过调用

使用自定义代码将其打印出来
vector< complex<double> > v = /* ... */
copy (v.begin(), v.end(), ostream_iterator< ComplexPrinter<double> >(cout, " "));

在输出时,隐式转换构造函数会将您的complex<double>转换为包装器,您的自定义代码将为您执行打印。

如果你想要非常冒险并且谨慎行事,你甚至可以编写课程,以便它只存储对原始complex的引用,如下所示:

template <typename T> class ComplexPrinter {
public:
    /* Conversion constructor allows for implicit conversions from
     * complex<T> to ComplexPrinter<T>.
     */
    ComplexPrinter(const complex<T>& value) : c(value) {
        // Handled in initializer list
    }

    /* Output the complex in your own format. */
    friend ostream& operator<< (ostream& out, const ComplexPrinter& cp) {
        /* ... print in your own format ... */
    }

private:
    const complex<T>& c;
};

这完全消除了任何复制,只是使包装器成为真实complex周围的薄单板。 (没有双关语)。你必须非常小心,如果你这样做不是为了在原始对象超出范围的范围边界上传递这些对象,但如果它是你想要的,它可能会很好。

希望这有帮助!

答案 1 :(得分:3)

template<class T>
struct my_complex_format_type {
  std::complex<T> const &x;
  my_complex_format_type(std::complex<T> const &x) : x (x) {}
  friend std::ostream& operator<<(std::ostream &out,
                                  my_complex_format_type const &value)
  {
    out << "format value.x however you like";
    return out;
  }
};
template<class T>
my_complex_format_type<T> my_complex_format(std::complex<T> const &x) {
  return x;
}

void example() {
  std::cout << my_complex_format(some_complex);
}

答案 2 :(得分:1)

对于complex<T>的任何特定实例化,使用强类型定义(boost具有版本)并在&lt;&lt;&lt;&lt;&lt;调用。覆盖&lt;&lt;对于那种类型。

如果您需要覆盖&lt;&lt;对于complex<T>的任何变化,那么生活将更加艰难。

答案 3 :(得分:0)

我在这里对同一问题的回答:c++ display complex number with i in imaginary part产生了您想要的行为,但以将来不兼容的风险为代价,因为它在std::命名空间中插入了模板特化。

答案 4 :(得分:-1)

没有非常整洁的方法可以做到这一点。我的建议是放弃iostream并写一些更像C的东西。写入速度可能更快,读取速度更快,执行速度更快。