2011-02-14 50 views
5

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

+1

要什么?你冷淡的想要截断这个数字,或者想要每次都打印'pear!',你需要指定。 – GManNickG 2011-02-14 07:05:54

回答

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

一旦你有了这个,你甚至可以清洁通过编写一个函数像这样的包装对象为你喜欢写东西

​​

你可以这样:

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

这就让你写

cout << wrap(myComplex) << endl; 

这并不完美,但很不错。

有一点需要注意上面的包装,它有一个隐含的转换构造函数,可以让您将complex<T> s转换为ComplexPrinter<T> s。这意味着,如果你有一个vector< complex<T> >,您可以使用自定义代码调用

vector< complex<double> > v = /* ... */ 
copy (v.begin(), v.end(), ostream_iterator< ComplexPrinter<double> >(cout, " ")); 

输出时,隐式转换构造函数将改变你的complex<double> S插入包装打印出来,和您的自定义代码将执行为您打印。

如果你想成为非常冒险和投谨慎的风,你甚至可以写的类,以便它只是存储到原来的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。 (没有双关语意)。如果你这样做的话,你必须非常小心,不要将这些对象在原始对象超出范围的范围边界传递,但如果这是你想要的,它可能会发挥出色。

希望这会有所帮助!

+0

谢谢!这正是我需要的! – grzkv 2011-02-14 07:25:08

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); 
} 
+0

不是说这不是一个很好的答案,但是这几乎不是我几分钟前发布的吗? :-) – templatetypedef 2011-02-14 07:11:56

+0

@templatetypedef:我开始阅读这个问题,然后在发布前几分钟输入我的答案,并且只在您之后点击提交67秒。那是问题吗? – 2011-02-14 07:16:24

-1

有没有真正干净的方法来做到这一点。我的建议就是抛开iostreams,而不是写更类似C的东西。写入速度可能会更快,读取速度更快,执行速度更快。

1

对于complex<T>的任何特定实例,请在< <调用期间使用强类型定义(boost有一个版本)并强制转换为该类型。覆盖该类型的< <。

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