在升级到OS X 10.9.4之前,我有以下代码在OS X中工作 这是代码:
#include <iostream>
#include <sstream>
int main() {
// Buffer to be read
const char* buffer = "0 3";
std::cout << "buffer: '" << buffer << "'\n";
size_t len = 3;
std::istringstream iss;
iss.clear();
iss.rdbuf()->pubsetbuf((char*)buffer, len);
// Did iss got a hold of buffer?
std::cout << "str: '" << iss.str() << "'\n";
}
这个想法很简单,而且已经asked了。我希望能够从现有字符串中读取并从中读取而无需复制其内容。正如我已经提到的,此代码在OS X 10.9.4中没有给出正确的输出。
我猜这是为什么会这样,因为正如post中提到的那样pubsetbuf
的实现没有做任何事情。
我的问题是:有没有办法在每台机器上取得理想的效果?为了正确设置内部缓冲区,我需要做什么?
如果不清楚,我希望得到以下结果:
buffer: '0 3'
str: '0 3'
我在我的机器中获得的当前输出是
buffer: '0 3'
str: ''
意味着istringstream
中的内部缓冲区未设置。
答案 0 :(得分:2)
您可以编写自己的:
,而不是篡改std :: istringstream#include <algorithm>
#include <ostream>
// BasicInputSequenceBuffer
// ============================================================================
template < typename Char, typename Traits = std::char_traits<Char> >
class BasicInputSequenceBuffer
: public std::basic_streambuf<Char, Traits>
{
// Types
// =====
private:
typedef std::basic_streambuf<Char, Traits> Base;
public:
typedef typename Base::char_type char_type;
typedef typename Base::int_type int_type;
typedef typename Base::pos_type pos_type;
typedef typename Base::off_type off_type;
typedef typename Base::traits_type traits_type;
typedef const char_type* pointer;
typedef std::size_t size_type;
// Construction
// ============
public:
BasicInputSequenceBuffer(pointer data, size_type size) {
// These casts are safe (no modification will take place):
char* begin = const_cast<char_type*>(data);
char* end = const_cast<char_type*>(data + size);
this->setg(begin, begin, end);
}
// Stream Buffer Interface
// =======================
protected:
virtual std::streamsize showmanyc();
virtual std::streamsize xsgetn(char_type*, std::streamsize);
virtual int_type pbackfail(int_type);
// Utilities
// =========
protected:
int_type eof() { return traits_type::eof(); }
bool is_eof(int_type ch) { return ch == eof(); }
};
// Get Area
// ========
template <typename Char, typename Traits>
std::streamsize
BasicInputSequenceBuffer<Char, Traits>::showmanyc() {
return this->egptr() - this->gptr();
}
template <typename Char, typename Traits>
std::streamsize
BasicInputSequenceBuffer<Char, Traits>::xsgetn(char_type* p, std::streamsize n) {
std::streamsize result = std::min(n, this->egptr() - this->gptr());
std::copy(this->gptr(), this->gptr() + result, p);
this->gbump(result);
return result;
}
template <typename Char, typename Traits>
typename BasicInputSequenceBuffer<Char, Traits>::int_type
BasicInputSequenceBuffer<Char, Traits>::pbackfail(int_type ch) {
if(is_eof(ch)) {
if(this->eback() != this->gptr()) {
this->gbump(-1);
return traits_type::to_int_type(*this->gptr());
}
}
return eof();
}
typedef BasicInputSequenceBuffer<char> InputSequenceBuffer;
// BasicInputSequence
//=============================================================================
template < typename Char, typename Traits = std::char_traits<Char> >
class BasicInputSequence
: public std::basic_istream<Char, Traits>
{
// Types
// =====
private:
typedef std::basic_istream<Char, Traits> Base;
public:
typedef typename Base::char_type char_type;
typedef typename Base::int_type int_type;
typedef typename Base::pos_type pos_type;
typedef typename Base::off_type off_type;
typedef typename Base::traits_type traits_type;
private:
typedef BasicInputSequenceBuffer<Char, Traits> buffer_type;
public:
typedef typename buffer_type::pointer pointer;
typedef typename buffer_type::size_type size_type;
// Construction
// ============
public:
explicit BasicInputSequence(pointer data, size_type size)
: Base(&m_buf), m_buf(data, size)
{}
private:
buffer_type m_buf;
};
typedef BasicInputSequence<char> InputSequence;
#include <iostream>
int main() {
const char* buffer = "0 3";
InputSequence stream(buffer, 3);
std::string a;
std::string b;
stream >> a >> b;
std::cout << "str: '" << a << ' ' << b << "'\n";
return 0;
}
答案 1 :(得分:1)
您可以实现一个流缓冲区,它接受您要用作缓冲区的一系列字符。然后用一个方便的输入流包装它:
#include <iostream>
#include <sstream>
#include <vector>
struct raw_char_buffer : std::streambuf
{
explicit raw_char_buffer(const char* const begin,
const char* const end)
: buffer(begin, end)
{
this->setg(buffer.data(), buffer.data(),
buffer.data() + buffer.size());
}
private:
std::vector<char> buffer;
};
struct raw_char_istream : virtual raw_char_buffer
, std::istream
{
explicit raw_char_istream(const char* const begin,
const char* const end)
: raw_char_buffer(begin, end)
, std::istream(this)
{
}
std::string str() const {
return std::string(this->eback(), this->egptr());
}
};
int main()
{
const char* p = "Hello World";
raw_char_istream os(p, p + 11);
std::string s;
os >> s;
std::cout << "s = " << s << '\n';
std::cout << "str() = " << os.str() << '\n';
}