2016-07-04 4 views
1
私は今、私はこのコード

ASIO ::ストリームバッファへのstd :: IStreamの新しいライン

asio::error_code ec; 
auto bytes_transferred = asio::read_until(socket, buffer, '\n', ec); 

if(!ec) 
{ 
    buffer.commit(bytes_transferred); 
    std::istream line(&buffer); 
    // use line 
    buffer.consume(bytes_transferred); 
} 
に持つまではistream

として(ASIO_STANDALONE付き)ASIO ::ソケットから読み出されたデータを使用する必要が

を破棄

私が直面している問題は、read_untilによって破棄されないので、'\n'がistreamの最後に表示されることです。

宣言は

tcp::socket socket; 
asio::streambuf buffer; 

は、だから私は、ストリームを構築するときに「\ n」の文字を無視する必要があります。

if(!ec) 
{ 
    // Ignore the last char ('\n') 
    std::string line = std::string(asio::buffers_begin(buffer), 
            asio::buffers_begin(buffer) + bytes_transferred - 1); 
    std::stringstream ss(line); 
    // use line 
    buffer.consume(bytes_transferred); 
} 

で(私はこの質問efficient copy of data from boost::asio::streambuf to std::stringで見たように)私が試したしかし、これは以下のコンパイルエラー

In instantiation of ‘struct asio::detail::buffers_iterator_types<asio::basic_streambuf<>, char>’: 
lib/asio/asio/buffers_iterator.hpp:77:46: required from ‘class asio::buffers_iterator<asio::basic_streambuf<>, char>’ 
file.h:58:78: required from here 
lib/asio/asio/buffers_iterator.hpp:60:5: error: no type named ‘value_type’ in ‘class asio::basic_streambuf<>’ 
    { 
    ^
lib/asio/asio/buffers_iterator.hpp: In instantiation of ‘class asio::buffers_iterator<asio::basic_streambuf<>, char>’: 
file.h:58:78: required from here 
lib/asio/asio/buffers_iterator.hpp:455:43: error: no type named ‘const_iterator’ in ‘class asio::basic_streambuf<>’ 
    typename BufferSequence::const_iterator begin_; 

と常に不足しているタイプに文句いくつか他の人を作り出します。 私はかなり新しいC++ですが、このメッセージは私にとっては謎めいています。さらに、私は同じデータの3つのコピーをバッファに格納します。ストリーム)

私の問題の可能な解決方法はありますか?

答えて

2

ここにはいくつかのアプローチがありますが、istreamの使い方について知らずに良いアドバイスをするのは難しいです。

このコードについての1つのことは、istreamの最後に改行があることを絶対確実に知っていることです。取ることができるコードパスはありません(I/Oエラー以外は早めにキャッチします)。

結果として、\nが存在し、無視することを期待するコードを書くのは簡単です。

可能な場合は、明らかにバッファコピーを避けたいと考えています。

あなたは文字列に全体のstreambufをコピーしたい場合は、あなたがこのみてください:あなたは文字列を解析するために探している場合はもちろん

auto buf = buffer.data(); /* where buffer is your asio::streambuf */ 
auto s = std::string(boost::asio::buffer_cast<const char*>(buf), 
        boost::asio::buffer_size(buf) - 1); /* remove the newline */ 

は、数字などのIStreamのうち、その後事実最後に改行があっても問題ありません。これはデフォルトでは無視される空白です。

このミニプログラムでは、このことを示しています。

#include <boost/asio.hpp> 
#include <sstream> 
#include <iomanip> 
#include <iostream> 


int main() 
{ 
    std::ostringstream oss; 

    oss << 10 << std::quoted("Hello\" World") << '\n'; 
    auto payload = oss.str(); 

    boost::asio::streambuf sb; 
    std::ostream otmp(&sb); 
    otmp.write(payload.data(), payload.size()); 

    // streambuf now contains string with newline 

    std::string s; 
    int i; 
    std::istream itmp(&sb); 
    itmp >> i >> std::quoted(s); 

    std::cout << i << std::endl; // expect 10 
    std::cout << s << std::endl; // expect Hello" World 
} 
+0

1の空白を無視してはistreamの使用に関連するサンプルと余分なマイルを行くため。驚くばかりの新しく言及したことについての功績は、もちろん引用されています。 – sehe

+0

バッファは新しい行で終わることが保証されています。私はistreamを使ってそれを解析しますが、バリデーションの一部は解析の終わりにistreamが空であることです( 'と' \ t 'のみが末尾の文字として受け入れられます)ので、改行。 –

+0

@sehe私は次の質問が精神との効率的な構文解析であると感じています。 –

1

バッファーイテレーターは、streambufを使用していないとみなします。あなたが完全に動作するバッファ(シーケンス)を受け取ることができる場合。

std::string line; 
// Ignore the last char ('\n') 
std::copy_n(std::istreambuf_iterator<char>(&buffer), bytes_transferred - 1, back_inserter(line)); 

Live On Coliru

  • iostreamの空白を認識機能(のようなstd::getlineと:

    しかし、あなたはおそらくちょうど

    1. たstreambufイテレータを使用することができます、がデフォルトで有効になります)。

  • 関連する問題