Изменить формат вывода комплексного числа - PullRequest
5 голосов
/ 14 февраля 2011

В стандартной библиотеке C ++ есть шаблон complex<>, и в нем есть перегруженный оператор <<, поэтому он выводит комплексные числа в формате (real_part, im_part).Мне нужно изменить поведение этого оператора для комплексных чисел, чтобы формат вывода изменился на что-то совершенно другое.В частности, мне нужно, чтобы вывод был в виде <code>real_part\tim_part.Как мне это сделать?

Ответы [ 5 ]

7 голосов
/ 14 февраля 2011

Нет прямого способа заменить operator <<, но у вас есть несколько вариантов. Во-первых, вы можете просто написать свою собственную функцию для печати комплексных чисел:

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

Если вы все еще хотите использовать синтаксис nice stream, то вы могли бы сделать один трюк - создать класс-оболочку, который обернет 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> с. Это означает, что если у вас есть 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. (Не каламбур предназначен). Вам следует быть очень осторожным, если вы сделаете это, чтобы не пропустить эти объекты через границы области видимости, где исходные объекты выходят из области видимости, но если это то, что вам нужно, это может сработать просто замечательно.

Надеюсь, это поможет!

3 голосов
/ 14 февраля 2011
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);
}
1 голос
/ 14 февраля 2011

Для любого конкретного экземпляра complex<T>, используйте сильный typedef (у boost есть версия) и приводите его к этому типу во время << вызовов. Переопределить << для этого типа. </p>

Если вам нужно переопределить << для любого варианта <code>complex<T>, тогда жизнь будет сложнее.

0 голосов
/ 19 октября 2018

Мой ответ на тот же вопрос здесь: c ++ отображает комплексное число с i в мнимой части создает желаемое поведение за счет некоторого риска будущей несовместимости, поскольку оно вставляет специализацию шаблона в std:: пространство имен.

0 голосов
/ 14 февраля 2011

Нет действительно аккуратного способа сделать это. Мое предложение было бы просто бросить iostreams и написать что-то более C-like вместо этого. Вероятно, будет быстрее писать, быстрее читать и быстрее выполнять.

...