2011-04-12 22 views
6

私は独自のostreamを作成する研究を行っており、それに伴ってostreamのバッファを処理するstreambufも用意されています。私は実際にそのほとんどが動作している、私は(< <)私のストリームに挿入して文字列を問題なく取得できます。私は、仮想関数xsputnを実装することでこれを行います。しかし、もし私が(< <)文字列の代わりにfloatまたはintをストリームに入力すると、xsputnは決して呼び出されません。ostreamを継承し、streambufの問題xsputnとオーバーフローの問題

私はコードを歩いていて、ストリームがdo_putを呼び出していて、次にf_putが呼び出され、最終的にフロートを1文字ずつバッファに入れようとしていることがわかります。バッファをスペースなしで残してフロートとintのデータを取得すると、仮想関数overflow(int c)の実装を呼び出すことができます。

ここに問題があります。フロートがいつバッファに置かれたのかを知る必要があります。別の言い方をすると、特定の値がストリームされたときにオーバーフローが最後に呼び出されたときを知る必要があります。なぜなら、xsputnは私のために機能します。だから私はそれをバッファにコピーして、バッファがいっぱいになるのを待つ関数に呼び出すことができます。

私は、出力をキャッシュして、各入力値(< <)ごとに一度にすべてを送信する必要があるという点で、ostreamデザインを悪用しています。

とにかく私は別の方法で撮影していることを再確認します。私はちょうど間違った方法でそれについて行っている非常に良いチャンスがあります。

継承されたostreamとstreambufを使用して値を入力できるようにして、自分の型変換を処理できるようにしたい場合、その情報を他のオブジェクトにフェッチして、 streambufに(?のために)。そのオブジェクトは高価なI/Oを持っているので、一度にデータ1文字を送信したくない。

ご迷惑をおかけして申し訳ございません。そして、あなたの時間をありがとう。

答えて

13

おおよそ のように聞こえていますが、あなたがしていることはあまり明確ではありません。ちょうど確かめてください:あなたのostreamには便利なコンストラクタがあり、streambuf、 デストラクタ、そしてrdbufから の正しいタイプのバッファを作成してインストールすることができます。その場合: streambufxsputnを定義することが純粋に最適化です。 定義する必要のある主要機能はoverflowです。最も簡単な の実装では、overflowはただ1文字を取り、 はそれをシンクに出力します。それ以外のものはすべて最適化です: たとえば、setpを使用してバッファを設定できます。 この場合、overflowは、バッファが で満杯になったとき、またはフラッシュが要求されたときにだけ呼び出されます。この場合、 出力バッファにも同様に入力する必要があります( アドレスを取得するにはpbasepptrを使用してください)。 (streambuf基底クラスはそうoverflowは、すべての文字を呼びかけ なり、長さ0のバッファを作成するために ポインタを初期化します。)あなたは (非常に)特定の場合に上書きすることができますその他の機能:

imbue:もしを何らかの理由でロケールが必要です。( 現在の文字エンコーディングはロケールの一部です)

setbuf:クライアントコードでバッファを指定できるようにする。 (IMHO、通常 ですが、あなたは特別な の要件があります)

seekoff:シークのサポート。私は の私のstreambufの中でこれを使ったことはありませんでした。だから、 の標準を読むことができる以上の情報を与えることはできません。

sync:フラッシュ時に呼び出され、 バッファ内の文字をシンクに出力する必要があります。 setpと決して電話しないと(つまり、 のバッファはありません)、常に同期しています。これはノーオペレーションにすることができます。 overflowまたはuflowはこれを呼び出すことができますが、どちらも という別の機能を呼び出すことができます。 (syncuflowの唯一の違いについてバッファ がある場合uflowにのみ呼び出され、バッファが空の場合に呼び出されることはないということです。クライアントコードは、ストリームをフラッシュした場合 syncが呼び出されます。)

私自身のストリームを書くときは、性能が の場合を除き、私はそれを単純なままにして、ただoverflowを上書きします。パフォーマンスはバッファを指示 た場合、私は通常、別のwrite(address, length) 機能に フラッシュにバッファを、コードを入れて、線に沿ってoverflowsyncを実装しますの :一般

int MyStreambuf::overflow(int ch) 
{ 
    if (pbase() == NULL) { 
     // save one char for next overflow: 
     setp(buffer, buffer + bufferSize - 1); 
     if (ch != EOF) { 
      ch = sputc(ch); 
     } else { 
      ch = 0; 
     } 
    } else { 
     char* end = pptr(); 
     if (ch != EOF) { 
      *end ++ = ch; 
     } 
     if (write(pbase(), end - pbase()) == failed) { 
      ch = EOF; 
     } else if (ch == EOF) { 
      ch = 0; 
     } 
     setp(buffer, buffer + bufferSize - 1); 
    } 
    return ch; 
} 

int sync() 
{ 
    return (pptr() == pbase() 
      || write(pbase(), pptr() - pbase()) != failed) 
     ? 0 
     : -1; 
} 

、私はしませんよあなたのクライアント コードが長い文字列をたくさん出力している場合は、便利かもしれませんがxsputnで気になります。このような 何かトリックを行う必要があります:私は、私が知りたい、今やっているものを基本的に

streamsize xsputn(char const* p, streamsize n) 
{ 
    streamsize results = 0; 
    if (pptr() == pbase() 
      || write(pbase(), pptr() - pbase()) != failed) { 
     if (write(p, n) != failed) { 
      results = n; 
     } 
    } 
    setp(buffer, buffer + bufferSize - 1); 
    return results; 
} 
+0

オーバーフローが呼ばれることになるだろう、または時に最後にされた回数を伝えるために、とにかく存在する場合でありますチャーが来ています。例として、私がmystream << 1.3f;私は文字 '1'と ''を取得します。その後 '3'しかし、私は予想通りにいくつの文字を知る方法がないstreabufの中に。そして、私は3を取得した後、私はバッファ上で動作したい(それが準備ができていることを知らせる別のオブジェクトに呼び出す) –

+2

コードは、クライアントコードが何をしようとしているか、または何回が呼び出される予定です。あなたができることは、 'ostream'に' unitbuf'をセットすることです:これは、( 'sentry'オブジェクトのデストラクタの)' operator << 'の終わりに 'sync'を呼び出すことになります。 'sync'でバッファー上で動作します。 –

+0

aha!それはまさに私が必要なものです!これを答えにすると、まだ投票はできませんが、十分な担当者がいたら、私は戻ってきます。どうもありがとうございます。 –