ios::uppercase does not work

M

Markus Dehmann

My ios::uppercase (and others) seems not to work.

#include <iostream>
using namespace std;
int main(){
int num = 45;
cout.setf(ios::hex | ios::showbase | ios::uppercase);
cout << "number " << num << endl;
return 0;
}

Shouldn't the output be
NUMBER 0X2D ???

Compiled with my g++ 3.3.1, the output is just a very boring
number 45

How can I get an uppercase output?

Thanks
Markus
 
R

Russell Hanneken

Markus said:
My ios::uppercase (and others) seems not to work.

How do you know ios::uppercase doesn't work, if you're not outputting
letters?
#include <iostream>

You should also have

#include <ios>

For the ios flags, and

#include <ostream>

for endl.
using namespace std;
int main(){
int num = 45;
cout.setf(ios::hex | ios::showbase | ios::uppercase);

Setting the ios::hex flag doesn't unset the ios::dec flag, and if more than
one base flag is set, decimal is used as the base. You could add this line:

cout.unsetf(ios::dec);

Or you could use manipulators instead:

cout << hex << showbase << uppercase << number << num << endl;
 
S

SaltPeter

Markus Dehmann said:
My ios::uppercase (and others) seems not to work.

#include <iostream>
using namespace std;
int main(){
int num = 45;
cout.setf(ios::hex | ios::showbase | ios::uppercase);
cout << "number " << num << endl;
return 0;
}

Shouldn't the output be
NUMBER 0X2D ???

You need to toggle the std::ios bits as mentioned in Russell's post. Done
with std::ios::basefield flag and the 2 arguement setf.
Try:

#include <iostream>

int main()
{
int num = 45;
std::cout.setf( std::ios::hex, std::ios::basefield);
std::cout.setf( std::ios::showbase );
std::cout.setf( std::ios::uppercase );
std::cout << "number " << num << std::endl;
return 0;
}

number 0X2D
 
M

Markus Dehmann

You need to toggle the std::ios bits as mentioned in Russell's post. Done
with std::ios::basefield flag and the 2 arguement setf.
Try:

#include <iostream>

int main()
{
int num = 45;
std::cout.setf( std::ios::hex, std::ios::basefield);
std::cout.setf( std::ios::showbase );
std::cout.setf( std::ios::uppercase );
std::cout << "number " << num << std::endl;
return 0;
}

number 0X2D

Thanks. I was actually most interested in a general uppercase output
("NUMBER"). So, how can I print a lowercase string uppercase?

std::string test = "number";
std::cout << std::ios::uppercase << test; // want NUMBER, but don't get it

Markus
 
J

John Harrison

Thanks. I was actually most interested in a general uppercase output
("NUMBER"). So, how can I print a lowercase string uppercase?

std::string test = "number";
std::cout << std::ios::uppercase << test; // want NUMBER, but don't get it

Convert your string to uppercase first, or write a streambuf wrapper that
does that for you.

There is no manipulator that will do that for you, presumably because
uppercase is a locale specific concept.

john
 
S

Siemel Naran

John Harrison said:
Convert your string to uppercase first, or write a streambuf wrapper that
does that for you.

There is no manipulator that will do that for you, presumably because
uppercase is a locale specific concept.

Isn't it a bug of the implementation that it does not respect the uppercase
flag in printing strings and const char arrays? Or maybe we have to imbue
some locale in the cout before printing?
 
J

John Harrison

Siemel Naran said:
get

Isn't it a bug of the implementation that it does not respect the uppercase
flag in printing strings and const char arrays? Or maybe we have to imbue
some locale in the cout before printing?

ios::uppercase affects only integers printed in hexadecimal and the exponent
of floating point numbers printed in scientific notation.

I don't think locales are meant to be used for this purpose. A locale could
specify *how* to convert from uppercase to lowercase but I think it would be
stretching the meaning of a locale to make it actually do that conversion.

If I had to do this a lot I would write a streambuf wrapper. This is only
minimally tested, and probably needs fleshing out to be a complete
implementation.

#include <streambuf>
#include <iostream>
#include <cctype>
using namespace std;

class ToUpperStreamBuf : public streambuf
{
public:
ToUpperStreamBuf(streambuf* wrapped) : _wrapped(wrapped)
{
}

protected:
int_type overflow(int_type ch)
{
if (traits_type::not_eof(ch))
ch = _wrapped->sputc(toupper(traits_type::to_char_type(ch)));
return ch;
}


int sync()
{
return _wrapped->pubsync();
}

private:
streambuf* _wrapped;
};

int main()
{
// replace cout stream buffer
streambuf* old_buf = cout.rdbuf();
ToUpperStreamBuf toupper_buf(old_buf);
cout.rdbuf(&toupper_buf);

// now cout will print in uppercase
cout << "hello\n";

// restore cout stream buffer
cout.rdbuf(old_buf);
}

john
 
S

Siemel Naran

John Harrison said:
ios::uppercase affects only integers printed in hexadecimal and the exponent
of floating point numbers printed in scientific notation.

The standard says in the chapter on Input/output library: "replaces certain
lowercase letters with their uppercase equivalents in generated output".
Could they be any more vague? But the chapter on locales says the flag is
only used in num_get and num_put, that is for integers.
I don't think locales are meant to be used for this purpose. A locale could
specify *how* to convert from uppercase to lowercase but I think it would be
stretching the meaning of a locale to make it actually do that conversion.

If I had to do this a lot I would write a streambuf wrapper. This is only
minimally tested, and probably needs fleshing out to be a complete
implementation.

#include <streambuf>
#include <iostream>
#include <cctype>
using namespace std;

class ToUpperStreamBuf : public streambuf
{
public:
ToUpperStreamBuf(streambuf* wrapped) : _wrapped(wrapped)
{
}

What is variable 'wrapped' for? OK, I get it, so you can use this class
with a filebuf, iostreambuf, streambuf, etc.
protected:
int_type overflow(int_type ch)
{
if (traits_type::not_eof(ch))
ch = _wrapped->sputc(toupper(traits_type::to_char_type(ch)));
return ch;
}

Don't you have to uppercase all the chars in [eback(), egptr()) too? I'd
then call _wrapped->overflow(ch). Also, the streambuf has a locale in it so
one could call getloc(), then toupper(c, loc).
int sync()
{
return _wrapped->pubsync();
}

private:
streambuf* _wrapped;
};

One should probably forward all virtual functions to _wrapped. An
alternative design pattern I've used for this sort of thing is templates.

template <class Streambuf>
class ToUpperStreamBuf : public Streambuf {
public:
typedef typename Streambuf::int_type int_type;
ToUpperStreamBuf();
protected:
int_type overflow(int_type ch);
};

But wait! There's a problem because we don't know the type of cout.rdbuf(),
as it's implementation defined, and usually some special class derived from
streambuf.
int main()
{
// replace cout stream buffer
streambuf* old_buf = cout.rdbuf();
ToUpperStreamBuf toupper_buf(old_buf);
cout.rdbuf(&toupper_buf);

// now cout will print in uppercase
cout << "hello\n";

// restore cout stream buffer
cout.rdbuf(old_buf);
}

The stream method seems too big for most purposes, and forces uppercase all
the time. How about writing a class-style manipulator, which I've used in
the past?

class ToUpper {
public:
ToUpper(const char *);
private:
some data variable here;
};

std::eek:stream& operator<<(std::eek:stream&, ToUpper);

It would be nice if in istream and ostream they had a virtual function that
returned a sentry object, and the default behavior would be to return the
sentry as they currently have (that for istream ignores whitespace). Then
users of derived ostreams could change the virtual function to return a
sentry class derived from the base class one. Presumably it would do
additional processing. One minor problem: the sentry's copy constructer is
private.

class myostream : public std::eek:stream {
public:
class mysentry : public std::eek:stream::sentry { ... };
virtual /*override*/
mysentry getsentry() const;
};

What do you think of this design pattern in general?
 
J

John Harrison

I didn't look at the standard but my compilers documentation which derives
from dinkunware. Its normally pretty reliable.
The standard says in the chapter on Input/output library: "replaces certain
lowercase letters with their uppercase equivalents in generated output".
Could they be any more vague? But the chapter on locales says the flag is
only used in num_get and num_put, that is for integers.
I don't think locales are meant to be used for this purpose. A locale could
specify *how* to convert from uppercase to lowercase but I think it
would
be
stretching the meaning of a locale to make it actually do that conversion.

If I had to do this a lot I would write a streambuf wrapper. This is only
minimally tested, and probably needs fleshing out to be a complete
implementation.

#include <streambuf>
#include <iostream>
#include <cctype>
using namespace std;

class ToUpperStreamBuf : public streambuf
{
public:
ToUpperStreamBuf(streambuf* wrapped) : _wrapped(wrapped)
{
}

What is variable 'wrapped' for? OK, I get it, so you can use this class
with a filebuf, iostreambuf, streambuf, etc.
protected:
int_type overflow(int_type ch)
{
if (traits_type::not_eof(ch))
ch = _wrapped->sputc(toupper(traits_type::to_char_type(ch)));
return ch;
}

Don't you have to uppercase all the chars in [eback(), egptr()) too? I'd
then call _wrapped->overflow(ch).

_wrapped->overflow is protected, so can't be called here.
Also, the streambuf has a locale in it so
one could call getloc(), then toupper(c, loc).

Agreed, although there are two streambuf. I think I would use the wrapped
streambuf and ignore the wrapper.
One should probably forward all virtual functions to _wrapped.

Agreed, imbue -> pubimbue (use the locale in the wrapped streambuf),
seekoff -> pubseekoff, seekpos ->pubseekpos (support positioning if the
wrapped streambuf does) etc. etc.
An
alternative design pattern I've used for this sort of thing is templates.

template <class Streambuf>
class ToUpperStreamBuf : public Streambuf {
public:
typedef typename Streambuf::int_type int_type;
ToUpperStreamBuf();
protected:
int_type overflow(int_type ch);
};

But wait! There's a problem because we don't know the type of cout.rdbuf(),
as it's implementation defined, and usually some special class derived from

The stream method seems too big for most purposes, and forces uppercase all
the time. How about writing a class-style manipulator, which I've used in
the past?

class ToUpper {
public:
ToUpper(const char *);
private:
some data variable here;
};

std::eek:stream& operator<<(std::eek:stream&, ToUpper);

Seems reasonable. I was assuming that the OP wanted to force a stream to
output everything in uppercase.
It would be nice if in istream and ostream they had a virtual function that
returned a sentry object, and the default behavior would be to return the
sentry as they currently have (that for istream ignores whitespace). Then
users of derived ostreams could change the virtual function to return a
sentry class derived from the base class one. Presumably it would do
additional processing. One minor problem: the sentry's copy constructer is
private.

class myostream : public std::eek:stream {
public:
class mysentry : public std::eek:stream::sentry { ... };
virtual /*override*/
mysentry getsentry() const;
};

What do you think of this design pattern in general?

Not sure, storing the sentry in the stream might have some implications.
What about multithreading for instance? Also there would still be a need for
a sentry object on the stack (to ensure exception safety). Presumably the
sentry on the stack would call methods in the sentry stored in the stream.
In fact I wouldn't use the term sentry for the object stored in the stream.
Perhaps a simpler method would be to have virtual methods on the stream
called prolog and epilog. The sentry can call these methods in its ctor and
dtor.

john
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top