更改复数输出格式

发布于 2024-10-17 04:32:57 字数 187 浏览 1 评论 0原文

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

There is the complex<> template in C++ standard library, and it has an overloaded << operator so that it outputs complex numbers in the (real_part, im_part) format. I need to change the behavior of that operator for complex numbers so that the output format is changed to something completely different. Specifically, I need the output to be in the form real_part\tim_part. How do I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

避讳 2024-10-24 04:32:57

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

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

如果您想仍然使用漂亮的流语法,那么您可以做的一个技巧是创建一个包装器类来包装 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:
    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;

Which isn't Perfect,but is相当不错。

关于上述包装器需要注意的一件事是,它设置了一个隐式转换构造函数,可让您将 complex 转换为 ComplexPrinter。这意味着如果你有一个向量复合物>,您可以通过调用

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

On output 使用自定义代码将其打印出来,隐式转换构造函数会将您的 complex 转换为包装器,并且您的自定义代码将执行此操作为您打印。

如果您想要非常冒险并且不顾一切,您甚至可以编写该类,以便它只存储对原始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;
};

这完全消除了任何复制,并且只是使包装成为一个真正的复杂周围的薄饰面。 (没有双关语的意思)。如果你这样做,你必须非常小心,不要将这些对象传递到原始对象超出范围的范围边界,但如果这是你想要的,它可能会很好。

希望这有帮助!

There's no direct way to replace operator <<, but you do have a few options. First, you could just write your own function to print complex numbers:

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

If you want to still use the nice stream syntax, then one trick you could do would be to make a wrapper class that wraps a complex and then defines its own operator << that prints it out in a different way. For example:

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

Once you have this, you could write something like

cout << ComplexPrinter<double>(myComplex) << endl;

You can make this even cleaner by writing a function like this one to wrap the object for you:

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

This then lets you write

cout << wrap(myComplex) << endl;

Which isn't perfect, but is pretty good.

One thing to note about the above wrapper is that it has an implicit conversion constructor set up to let you convert complex<T>s to ComplexPrinter<T>s. This means that if you have a vector< complex<T> >, you can print it out using your custom code by calling

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

On output, the implicit conversion constructor will transform your complex<double>s into the wrappers, and your custom code will do the printing for you.

If you want to be very adventurous and cast caution to the wind, you could even write the class so that it just stores a reference to the original complex, as shown here:

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

This completely eliminates any copying and just makes the wrapper a thin veneer around a real complex. (No pun intended). You'd have to be very careful if you did this not to pass these objects around across scope boundaries where the original objects go out of scope, but if it's what you want it might work out just great.

Hope this helps!

り繁华旳梦境 2024-10-24 04:32:57
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);
}
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);
}
丢了幸福的猪 2024-10-24 04:32:57

对于 complex 的任何特定实例化,请使用强 typedef(boost 有一个版本)并在 << 期间强制转换为该类型。来电。覆盖<<对于那种类型。

如果您需要覆盖<<对于complex的任何变体,生活都会变得更加困难。

For any specific instantiation of complex<T>, Use a strong typedef (boost has a version) and cast to that type during << calls. Override << for that type.

If you need to override << for any variation of complex<T> then life will be harder.

笑脸一如从前 2024-10-24 04:32:57

我在这里对同一问题的回答: c++ 显示虚数部分包含 i 的复数 会产生您想要的行为,但代价是未来不兼容的一些风险,因为它将模板专门化插入到 std:: 命名空间中。

My answer to the same question here: c++ display complex number with i in imaginary part produces the behavior you want, at the expense of some risk of future incompatibility because it inserts a template specialization into the std:: namespace.

你不是我要的菜∠ 2024-10-24 04:32:57

没有真正简洁的方法可以做到这一点。我的建议是放弃 iostreams 并编写一些更像 C 的东西。它可能会更快地写入、读取和执行。

There is no really tidy way to do that. My suggestion would be to just ditch iostreams and write something more C-like instead. It will probably be faster to write, faster to read and faster to execute.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文