473,395 Members | 1,996 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

no setw for istreams?

edd
Hello all,

I'm trying to put together some code that reads 3 adjacent pairs of hex
digits from an istream. Each hex digit pair represents a non-negative
integer.

For example I would like to extract 1, 255 and 18 from 01ff12 (as the
components of a simple RGB colour, in my application).

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.
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?

Why is it that no equivalent to setw exists for istreams?

Kind Regards,

Edd

Dec 25 '06 #1
10 2236

ed*@nunswithguns.net wrote:
Hello all,

I'm trying to put together some code that reads 3 adjacent pairs of hex
digits from an istream. Each hex digit pair represents a non-negative
integer.

For example I would like to extract 1, 255 and 18 from 01ff12 (as the
components of a simple RGB colour, in my application).

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.
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?

Why is it that no equivalent to setw exists for istreams?

Kind Regards,

Edd
There are a number of ways to approach the issue, and this is not
neccessarily the best way.
You could teach the computer how to count with hex char pairs.
Extracting two chars from a std::istringstream or std::istream& is
dandy but that will get you an ascii translation, not what you need.
The Hex class's const_char_array ctor takes 3 chars, not 2 (because of
null termination).
The cvt(...) function converts each hex digit to an unsigned equivalent
while the ctor(s) init lists take care of calculating the final
unsigned result. Any hex digit that falls out of range generates an
exception.
This should be a portable solution. But that remains to be seen.

#include <iostream>
#include <ostream>
#include <string>
#include <stdexcept>

class Hex
{
char m_16c; // left hex digit * 16
char m_c; // right hex digit
unsigned m_n; // result
public:
Hex(const char (& array)[3]) // ctor, char array[3] by ref
: m_16c(array[0]), m_c(array[1]),
m_n(16*cvt(m_16c) + cvt(m_c)) { }
Hex(std::string& s) // ctor, a string of 2 chars, others ignored
: m_16c(s[0]), m_c(s[1]),
m_n(16*cvt(m_16c) + cvt(m_c)) { }
Hex(const Hex& copy) // copy ctor
{
m_16c = copy.m_16c;
m_c = copy.m_c;
m_n = copy.m_n;
}
// member functions
unsigned cvt(const char c) const
{
if(c >= '0' && c <= '9')
{
return c - '0';
} else if(c >= 'a' && c <= 'f')
{
return 10 + (c - 'a');
} else if(c >= 'A' && c <= 'F')
{
return 10 + (c - 'A');
} else
{
throw std::runtime_error("Hex out of range.");
}
}
// friend operators
friend std::ostream&
operator<<(std::ostream& os, const Hex& r_h)
{
return os << r_h.m_n;
}
};

int main()
{
try {
// testing hex pairs
Hex h255("ff");
std::cout << h255 << std::endl;
Hex h16("10");
std::cout << h16 << std::endl;
Hex h0A("0A");
std::cout << h0A << std::endl;

// parsing a buffer
std::string buffer("ff100a");
std::string red(buffer, 0, 2); // substr
Hex r(red);
std::cout << "r: " << r << std::endl;
std::string green(buffer, 2, 2);
Hex g(green);
std::cout << "g: " << g << std::endl;
std::string blue(buffer, 4, 2);
Hex b(blue);
std::cout << "b: " << b << std::endl;
}
catch(std::exception& r_e)
{
std::cerr << "Error: " << r_e.what();
std::cerr << std::endl;
}
}

/*
255
16
10
r: 255
g: 16
b: 10
*/

Note how the std::string buffer in main() is substringed and loaded
into individual Hex variables.
Imagine a Colour class with 3 Hex members (r, g and b), appropriate
ctors and operator overloads and even a filereader function.
You could open a file with std::ifstream and use std::getline to load
that buffer one line at a time.

Dec 26 '06 #2
edd

Salt_Peter wrote:
There are a number of ways to approach the issue, and this is not
neccessarily the best way.
You could teach the computer how to count with hex char pairs.
Extracting two chars from a std::istringstream or std::istream& is
dandy but that will get you an ascii translation, not what you need.
The Hex class's const_char_array ctor takes 3 chars, not 2 (because of
null termination).
The cvt(...) function converts each hex digit to an unsigned equivalent
while the ctor(s) init lists take care of calculating the final
unsigned result. Any hex digit that falls out of range generates an
exception.
This should be a portable solution. But that remains to be seen.
[ generous code snipped ]

Many thanks for you reply. I had come up with something equally long
winded. I was hoping that istreams would provide a way of doing this
simply as the task appears appropriate for their job description.

In fact, I'm not sure your code is entirely portable. If I'm not
mistaken it appears that you're assuming that all character sets have
alphabetical glyphs with contiguous values (i.e. they could do
aAbBcCdD... as far as I'm aware).

But it just goes to show how stupidly tricky such a problem is. I
really am going to have to peel the characters off in to 2-digit
buffers and read from those :/

Kind regards,

Edd

Dec 26 '06 #3
ed*@nunswithguns.net wrote:
Hello all,

I'm trying to put together some code that reads 3 adjacent pairs of hex
digits from an istream. Each hex digit pair represents a non-negative
integer.

For example I would like to extract 1, 255 and 18 from 01ff12 (as the
components of a simple RGB colour, in my application).

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.
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?

Why is it that no equivalent to setw exists for istreams?
How about reading all six digits as one number from the stream,
using std::hex and then extracting the three components using
the modulo operation?

That would save you the two-digit buffer but probably you
would run into little/big-endian issues.

HTH,
- J.
Dec 26 '06 #4
ed*@nunswithguns.net wrote:
Hello all,

I'm trying to put together some code that reads 3 adjacent pairs of hex
digits from an istream. Each hex digit pair represents a non-negative
integer.

For example I would like to extract 1, 255 and 18 from 01ff12 (as the
components of a simple RGB colour, in my application).

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.
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?

Why is it that no equivalent to setw exists for istreams?

Kind Regards,

Edd
Hello,

Another approach may be to use std::sscanf from <cstdio>:

#include <cstdio>
#include <iostream>
int main()
{
const char* hex("01ff12");
unsigned int R,G,B;
const int n(std::sscanf(hex,"%2x%2x%2x",&R,&G,&B));
if(3!=n)
std::cerr<<n<<" items assigned, it is supposed to be 3.\n";
else
std::cout<<"R="<<R<<",G="<<G<<",B="<<B<<'\n';
}

On my implementation this gives:
R=1,G=255,B=18
Sincerely,

Peter Jansson
http://www.p-jansson.com/
http://www.jansson.net/
Dec 27 '06 #5
edd
Hi Peter,

Peter Jansson wrote:
Hello,

Another approach may be to use std::sscanf from <cstdio>:

#include <cstdio>
#include <iostream>
int main()
{
const char* hex("01ff12");
unsigned int R,G,B;
const int n(std::sscanf(hex,"%2x%2x%2x",&R,&G,&B));
if(3!=n)
std::cerr<<n<<" items assigned, it is supposed to be 3.\n";
else
std::cout<<"R="<<R<<",G="<<G<<",B="<<B<<'\n';
}

On my implementation this gives:
R=1,G=255,B=18
Thanks very much for your response. That's certainly the most concise
way of doing things. However, I'm doing this in a teaching context and
I really don't want to start preaching about the benefits of the type
safety in C++ and then use code that ignores them.

The other niggle is that the interface to the function in the example
code takes an std::istream reference. So before using sscanf I'd have
to read the 6 characters in to a buffer, checking each was a hex digit
before reading the next in order to stay true to how the pre-defined
istream extraction operators work.

Would it be possible to write a custom manipulator to do something like
setw for istreams?

I guess I'm just a bit frustrated that this is one of those times where
I'll have to admit that C++ is deficient in some sense, even though the
task isn't really all that complicated.

Edd

Dec 29 '06 #6
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";
}

Dec 30 '06 #7
edd
Hello Denise,

Denise Kleingeist wrote:
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...
Fair enough :)

[ generous code snipped ]

Thanks so much for your code, Denise! I have never used facets before
(explicitly) so I have to admit I don't fully understand it yet. I'm
doing some more reading now!

I'm not sure that code of such a technical nature will make it in to
the teaching notes, but I'm very happy to see that there is a C++
solution! Perhaps I'll include it as an appendix.

At any rate, thank you very much for taking the time to put that
together!

Kind regards,

Edd

Dec 30 '06 #8
"Denise Kleingeist" <de***************@googlemail.comwrote in message
news:11**********************@v33g2000cwv.googlegr oups.com...
>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...
Probably just as well. In this particular case, the committee did
something rather revolutionary -- it codified existing practice.
Between 1990 and 1997 nobody seems to have complained that the
iostreams package developed in the 1980s was deficient in this
regard, so oddly enough the committee did nothing to change it.

Go figure.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Dec 30 '06 #9
Hello P.J.!
P.J. Plauger wrote:
"Denise Kleingeist" <de***************@googlemail.comwrote in message
news:11**********************@v33g2000cwv.googlegr oups.com...
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...

Probably just as well. In this particular case, the committee did
something rather revolutionary -- it codified existing practice.
This is indeed revolutionary! ... considering that IOStream was always
intended as a replacement for stdio and thus should have the same
power, including for the task of parsing input. Someone should have
noted that the existing practice was incomplete and inconsistent
(setw has an effect when reading to a char*).
Between 1990 and 1997 nobody seems to have complained that the
iostreams package developed in the 1980s was deficient in this
regard, so oddly enough the committee did nothing to change it.
There were definitely compaints about the absence of setw support
for istreams (e.g.
<http://groups.google.com/group/comp.std.c++/msg/3cb7faa13ef4d70c>).
Also, at this time there were many experts who strongly argued that
stdio should still be used in C++, e.g. because the efficiency of
widely used implementations of IOStreams was mediocre with
implementers publically arguing that it can't be done differently.
Thus,
many programmers did not use IOStreams and thus didn't realize the
true but correctable deficencies.

As things are for programming languages, the standardization is to
a fair extend setting up precedence on how to use a programming
language. This includes that things often go beyond existing practice
for the benefit of future ease of use. Supporting something like setw
to cover the capabilities of C's stdio input facilities would clearly
fall into this area.

Good luck, Denise!

Dec 30 '06 #10
"Denise Kleingeist" <de***************@googlemail.comwrote in message
news:11**********************@i12g2000cwa.googlegr oups.com...
Hello P.J.!
P.J. Plauger wrote:
>"Denise Kleingeist" <de***************@googlemail.comwrote in message
news:11**********************@v33g2000cwv.googleg roups.com...
>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...

Probably just as well. In this particular case, the committee did
something rather revolutionary -- it codified existing practice.

This is indeed revolutionary! ... considering that IOStream was always
intended as a replacement for stdio and thus should have the same
power, including for the task of parsing input. Someone should have
noted that the existing practice was incomplete and inconsistent
(setw has an effect when reading to a char*).
Perhaps someone should have, but nobody saw fit to tell the committee.
>Between 1990 and 1997 nobody seems to have complained that the
iostreams package developed in the 1980s was deficient in this
regard, so oddly enough the committee did nothing to change it.

There were definitely compaints about the absence of setw support
for istreams (e.g.
<http://groups.google.com/group/comp.std.c++/msg/3cb7faa13ef4d70c>).
So you think a comment in a newsgroup is sufficient to cause an
overworked committee to undertake a work item to do something
about it? Try spending some time on a standards committee and
see whether your perspective changes.
Also, at this time there were many experts who strongly argued that
stdio should still be used in C++, e.g. because the efficiency of
widely used implementations of IOStreams was mediocre with
implementers publically arguing that it can't be done differently.
I still argue that stdio should be used where it's superior, but
then I'm definitely a pragmatist among idealists in this regard.
Thus,
many programmers did not use IOStreams and thus didn't realize the
true but correctable deficencies.
And so the committee should have been prescient, in the absence
of concrete requests?
As things are for programming languages, the standardization is to
a fair extend setting up precedence on how to use a programming
language. This includes that things often go beyond existing practice
for the benefit of future ease of use. Supporting something like setw
to cover the capabilities of C's stdio input facilities would clearly
fall into this area.
Fine. And who took the trouble to point this out?

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Dec 30 '06 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Matthew David Hills | last post by:
If setw() is being used to limit how many characters are pulled from a stream, should the # of characters taken from the stream depend on whether the stream is being sent to a std::string or a...
0
by: Alex Vinokur | last post by:
Both function width() and manipulator setw() set field width for _next_ output operation. width() seems to be less handy because we should split a chain of <<. Is there any situation in which...
10
by: Mathieu Malaterre | last post by:
Hello, I am trying to get rid a of sprintf in a c++ code, but I tried in several ways and couldn't figure out how to change: uint16_t group, uint16_t element; sprintf(buffer, "%04x|%04x",...
2
by: tvn007 | last post by:
Below is my code: #include <string> #include <iostream> #include <iomanip> int main (void){ using namespace std; string name1 = "JOHN"; int id1 = 1234;
4
by: alternativa | last post by:
Hi, I'd like to obtain an output looking as follows: name number phone address Caroline 233 34234 White St. 12 Anna 929043 093284 Brown St. 325...
3
by: Jess | last post by:
Hello, I'm trying to use setw and width functions to set the padding spaces between numbers. The aim is to create two white spaces between two double e.g. "1.1 1.2". I did: streamsize s =...
2
by: fathi | last post by:
hello everyone, i am actually new to c++. my problem is i need to display information from a file but i don't know how to do so for more than 4 elements horizontally . my code: void...
5
by: Christian Johannes Charbula | last post by:
hi, does anybody know how i can get the information what width for a ostream is actually set? i want to do somthing like the following, and need a way to do something like stream.getw(). ...
16
by: Simonius | last post by:
Hello, I'm teaching myself C++ with Accelerated C++ by Andrew Koenig. I'm having a small problem with an exercise at page 73. Now I was wondering how I should do that with setw, easiest...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.