Hello Edd!
ed*@nunswithguns.net wrote:
I was hoping to find something like std::setw for istreams and use it
in combination with std::hex so that I could read 2 hex digits at a
time, but as far as I can tell no such entity exists in the C++
standard library.
It is not readily there but it can be built relatively easily into
a suitable num_get facet (code see below).
Is there a neat and tidy way of doing what I want, or am I going to
have to do something nasty like put each digit pair in to its own
buffer and stream-extract/strtoul the numbers from there?
I would prefer something like the num_get facet described
above...
Why is it that no equivalent to setw exists for istreams?
I don't know about the reasons but those I'd consider to be
most likely could be seen as an insult on some of the more
active committee members. Thus, I'm keeping them for
myself...
Good luck, Denise!
--- CUT HERE ---
#include <iostream>
#include <iomanip>
#include <locale>
class width_num_get:
public std::num_get<char>
{
struct countbuf:
std::streambuf
{
countbuf(std::istreambuf_iterator<charbeg,
std::istreambuf_iterator<charend, int count):
m_beg(beg), m_end(end), m_count(count)
{
}
int underflow()
{
if (this->m_beg == this->m_end || this->m_count == 0)
return traits_type::eof();
--this->m_count;
this->m_buffer = *this->m_beg++;
this->setg(&m_buffer, &m_buffer, &m_buffer + 1);
return traits_type::not_eof(this->m_buffer);
}
std::istreambuf_iterator<charm_beg, m_end;
int m_count;
char m_buffer;
};
private:
iter_type
do_get(iter_type it, iter_type end, std::ios_base& fmt,
std::ios_base::iostate& state, long& val) const
{
return this->get_template(it, end, fmt, state, val);
}
iter_type
do_get(iter_type it, iter_type end, std::ios_base& fmt,
std::ios_base::iostate& state, unsigned short& val) const
{
return this->get_template(it, end, fmt, state, val);
}
iter_type
do_get(iter_type it, iter_type end, std::ios_base& fmt,
std::ios_base::iostate& state, unsigned int& val) const
{
return this->get_template(it, end, fmt, state, val);
}
iter_type
do_get(iter_type it, iter_type end, std::ios_base& fmt,
std::ios_base::iostate& state, unsigned long& val) const
{
return this->get_template(it, end, fmt, state, val);
}
template <typename T>
iter_type
get_template(iter_type it, iter_type end, std::ios_base& fmt,
std::ios_base::iostate& state, T& val) const
{
if (fmt.width() == 0)
return this->std::num_get<char>::do_get(it, end, fmt, state,
val);
countbuf sbuf(it, end, fmt.width(0));
this->std::num_get<char>::do_get(std::istreambuf_iterat or<char>(&sbuf),
std::istreambuf_iterator<char>(),
fmt, state, val);
state &= ~std::ios_base::eofbit;
return sbuf.m_beg;
}
};
int main()
{
std::cin.imbue(std::locale(std::locale(), new width_num_get));
for (short val; std::cin >std::hex >std::setw(2) >val; )
std::cout << "value: 0x" << std::hex << val << "\n";
}