2011-02-14 6 views
5

C++ 표준 라이브러리에 complex<> 템플릿이 있으며 오버로드 된 < < 연산자가 있으므로 (real_part, im_part) 형식으로 복소수를 출력합니다. 복소수에 대한 해당 연산자의 동작을 변경하여 출력 형식이 완전히 다른 것으로 변경되어야합니다. 특히, 결과는 real_part\tim_part 형식이어야합니다. 어떻게해야합니까?복소수 출력 형식 변경

+1

무엇에? 차갑게 전화 번호를 잘라내거나 '배'를 인쇄하기를 원할 때마다 지정해야합니다. – GManNickG

답변

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>으로 변환 할 수 있도록 암시 적 변환 생성자를 설정했기 때문입니다. 이렇게하면 vector< complex<T> >이있는 경우, 당신은 출력에

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

, 암시 적 변환 생성자가 래퍼로 complex<double>의 변환됩니다 호출하여 사용자 지정 코드를 사용하여 인쇄 할 수 있으며, 사용자 정의 코드가 수행된다는 것을 의미합니다 당신을 위해 인쇄.

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에 대한 참조를 저장하도록 다음과 같이

, 당신도, 클래스를 쓸 수 모든 복사는 랩퍼를 실제 complex 주위의 얇은 베니어로 만듭니다. (의도 한 말장난 없음). 원래의 오브젝트가 범위를 벗어나는 스코프 경계를 넘어서 이러한 오브젝트를 통과시키지 않도록했다면 매우 신중해야합니다. 그러나 원하는 경우 원하는대로 잘 수행 할 수 있습니다.

희망이 도움이됩니다.

+0

감사합니다. 그것은 내가 필요한 것입니다! – grzkv

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

+0

@templatetypedef : 필자는이 질문을 읽고 게시하기 몇 분 전에 내 대답을 입력하기 시작했으며, 이후 67 초 만 제출하십시오. 그게 문제 야? –

+0

@Fred Nurk- 대결이 아니 었습니다. 실제로 우리가 같은 대답으로 수렴했기 때문에 기뻤습니다 ... 이것은 아마도 정말 좋은 디자인이라는 것을 의미합니다! – templatetypedef

-1

실제로 그렇게 할 수있는 깔끔한 방법은 없습니다. 나의 제안은 단지 iostreams를 버리고 대신에 C와 비슷한 것을 쓸 것입니다. 쓰기가 빠르며 읽기가 빠르며 실행 속도가 빠릅니다.

+0

+1 : C++ 출력 형식 악취. Stroustrup이 모든 사람을 기쁘게 할 라이브러리를 작성하는 것이 쉽지 않다는 말로 시작하는 TC++ PL에서 입출력 스트림에 대한 소개를 기억합니다. 그것은 아마도 모두가 그것을 좋아할 것이라고 말함으로써 농담을 시작하는 것과 같습니다. – 6502

+0

@ 6502 : iostreams는 악취가 나는 것에 동의하지만이 유스 케이스는 실제로 깔끔합니다. –

+0

-1, std :: complex는'printf()'형식화가 고장난 전형적인 예입니다. – MSalters

1

complex<T>의 구체화에 대해서는 < < 호출 중에 강력한 typedef (boost가 버전 있음)를 사용하고 해당 유형으로 변환하십시오.해당 유형에 대해 < <을 재정의하십시오.

complex<T>의 변형에 대해 < <을 무시해야하는 경우 수명이 더 오래 걸릴 수 있습니다.