문제

수업을 정의하고 싶습니다 MyStream 하도록 하다:

MyStream myStream;
myStream << 1 << 2 << 3 << std::endl << 5 << 6 << std::endl << 7 << 8 << std::endl;

출력을 제공합니다

[blah]123
[blah]56
[blah]78

기본적으로 나는 [blah]가 앞쪽에 삽입 된 다음 매번 삽입되기를 원합니다. 종료되지 않습니다 std::endl?

여기서 어려움은 논리 관리가 아니라 취급을 감지하고 과부하시키는 것입니다. std::endl. 이 작업을 수행하는 우아한 방법이 있습니까?

감사!

편집 : 논리 관리에 대한 조언이 필요하지 않습니다. 인쇄를 감지/과부하시키는 방법을 알아야합니다. std::endl.

도움이 되었습니까?

해결책

당신이해야 할 일은 자신의 스트림 버퍼를 작성하는 것입니다.
스트림 버퍼가 플러시되면 출력 문자와 스트림 내용을 접두사합니다.

std :: endl이 다음을 일으키기 때문에 다음은 작동합니다.

1) 스트림에 ' n'을 추가하십시오.
2) 스트림에서 flush ()를 호출합니다
2a) 스트림 버퍼에서 pubsync ()를 호출합니다.
2B) 이것은 가상 메소드 Sync ()라고합니다.
2c)이 가상 방법을 무시하여 원하는 작업을 수행하십시오.

#include <iostream>
#include <sstream>

class MyStream: public std::ostream
{
    // Write a stream buffer that prefixes each line with Plop
    class MyStreamBuf: public std::stringbuf
    {
        std::ostream&   output;
        public:
            MyStreamBuf(std::ostream& str)
                :output(str)
            {}
            ~MyStreamBuf() {
                if (pbase() != pptr()) {
                    putOutput();
                }
            }

        // When we sync the stream with the output. 
        // 1) Output Plop then the buffer
        // 2) Reset the buffer
        // 3) flush the actual output stream we are using.
        virtual int sync() {
            putOutput();
            return 0;
        }
        void putOutput() {
            // Called by destructor.
            // destructor can not call virtual methods.
            output << "[blah]" << str();
            str("");
            output.flush();
        }
    };

    // My Stream just uses a version of my special buffer
    MyStreamBuf buffer;
    public:
        MyStream(std::ostream& str)
            :std::ostream(&buffer)
            ,buffer(str)
        {
        }
};


int main()
{
    MyStream myStream(std::cout);
    myStream << 1 << 2 << 3 << std::endl << 5 << 6 << std::endl << 7 << 8 << std::endl;
}

> ./a.out
[blah]123 
[blah]56 
[blah]78
>

다른 팁

오버로드 된 연산자 MyStream 클래스는 이전에 인쇄 된 Token-Was-Endl 플래그를 설정해야합니다.

그런 다음 다음 객체가 인쇄되면 [blah] 그 앞에 삽입 할 수 있습니다.

std::endl 참조를 취하고 반환하는 기능입니다 std::ostream. 그것을 감지하려면 스트림으로 이동하려면 과부하가 필요합니다. operator<< 귀하의 유형과 그러한 기능 사이 :

MyStream& operator<<( std::ostream&(*f)(std::ostream&) )
{
    std::cout << f;

    if( f == std::endl )
    {
        _lastTokenWasEndl = true;
    }

    return *this;
}

원칙적으로 닐과 동의했다.

버퍼의 동작을 변경하려고합니다. 왜냐하면 그것은 ioStream을 확장하는 유일한 방법이기 때문입니다. endl 이렇게합니다 :

flush(__os.put(__os.widen('\n')));

widen 단일 문자를 반환하면 문자열을 거기에 넣을 수 없습니다. put 전화 putc 가상 기능이 아니며 때로는 overflow. 당신은 가로 채울 수 있습니다 flush, 버퍼를 호출합니다 sync. 모든 Newline 캐릭터가 그대로 가로 채고 변경해야합니다. overflowED 또는 수동으로 sync에드와 스트링으로 변환하십시오.

재정의 버퍼 클래스를 디자인하는 것은 귀찮은 일입니다 basic_streambuf 버퍼 메모리에 직접 액세스 할 수 있습니다. 이것은 당신이 쉽게 I/O 요청을 기존에 전달하지 못하게합니다. basic_streambuf. 사지로 나가 스트림 버퍼 클래스를 알고 파생한다고 가정해야합니다. (cin 그리고 cout 사용이 보장되지 않습니다 basic_filebuf, 내가 알 수있는 한.) 그럼, 그냥 추가 virtual overflow 그리고 sync. (§27.5.2.4.5/3 및 27.5.2.4.2/7 참조) 대체를 수행하려면 추가 공간이 필요할 수 있으므로 미리 할당하도록주의하십시오.

- 또는 -

새로운 것을 선언하십시오 endl 자신의 네임 스페이스 또는 더 나은, 호출되지 않은 조작자 endl 조금도!

동작을 수정하려고 시도하는 대신 std::endl, 작업을 수행하기 위해 필터링 스트림 부프를 만들어야 할 것입니다. 제임스 칸 제가 있습니다 예시 각 출력 라인의 시작 부분에서 타임 스탬프를 삽입하는 방법을 보여줍니다. 각 라인에서 원하는 접두사로 변경하려면 약간의 수정 만 필요합니다.

나는 기능 포인터를 사용합니다. C에 익숙하지 않은 사람들에게는 끔찍하게 들리지만 대부분의 경우 훨씬 더 효율적입니다. 예는 다음과 같습니다.

#include <iostream>

class Foo
{
public:
    Foo& operator<<(const char* str) { std::cout << str; return *this; }
    // If your compiler allows it, you can omit the "fun" from *fun below.  It'll make it an anonymous parameter, though...
    Foo& operator<<(std::ostream& (*fun)(std::ostream&)) { std::cout << std::endl; }
} foo;

int main(int argc,char **argv)
{
    foo << "This is a test!" << std::endl;
    return 0;
}

당신이 정말로 원한다면 당신이 endl의 주소를 확인하여 다른 공허/무효 함수를 얻지 못한다는 것을 확인할 수 있지만 대부분의 경우 그만한 가치가 없다고 생각합니다. 도움이되기를 바랍니다.

당신은 바꿀 수 없습니다 std::endl - 이름이 알 수 있듯이 C ++ 표준 라이브러리의 일부이며 동작이 고정되어 있습니다. 스트림 자체의 동작 자체가 선 끝을받을 때 변경해야합니다. 개인적으로, 나는 이것이 노력의 가치가 있다고 생각하지 않았을 것입니다. 그러나이 지역으로 모험을하고 싶다면 책을 읽는 것이 좋습니다. 표준 C ++ ioStreams 및 로케일.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top