How do I convert a char to an unsigned int?

D

DeMarcus

Hi!

How do I convert a char or wchar_t to an int in a proper and portable way?

If I do this

char wickedChar = 'Æ';
unsigned int myInt = c;

then myInt is a very big number, it's the sign bit of wickedChar that
does that.

Maybe I could do something like

unsigned int myInt = (unsigned char)c;

but the problem is that this is a template so I don't know if it's going
to be a char or wchar_t (or even something else).

How can I convert the char (or wchar_t) to an unsigned int in a portable
way?


Thanks,
Daniel
 
D

DeMarcus

If that's your concern, provide the appropriate specializations for your
template.

Basically it's something like this.

#ifdef SOME_FLAG
typedef boost::match_results<string::const_iterator> MyMatch;
#else
typedef boost::match_results<wstring::const_iterator> MyMatch;
#endif

// More about boost::match_results can be found here.
// http://www.cs.brown.edu/~jwicks/boost/libs/regex/doc/match_results.html


void fnc( const MyMatch& match )
{
unsigned int charToInt = match[0].str()[0];
// ...
}

I did like this, which compiles and seems to work...

void fnc( const MyMatch& match )
{
unsigned int charToInt =
(unsigned MyMatch::char_type)match[0].str()[0];
// ...
}

.... but is it proper and portable C++ to cast like that?
 
A

Alf P. Steinbach /Usenet

* DeMarcus, on 25.10.2010 13:36:
If that's your concern, provide the appropriate specializations for your
template.

Basically it's something like this.

#ifdef SOME_FLAG
typedef boost::match_results<string::const_iterator> MyMatch;
#else
typedef boost::match_results<wstring::const_iterator> MyMatch;
#endif

// More about boost::match_results can be found here.
// http://www.cs.brown.edu/~jwicks/boost/libs/regex/doc/match_results.html


void fnc( const MyMatch& match )
{
unsigned int charToInt = match[0].str()[0];
// ...
}

I did like this, which compiles and seems to work...

void fnc( const MyMatch& match )
{
unsigned int charToInt =
(unsigned MyMatch::char_type)match[0].str()[0];
// ...
}

... but is it proper and portable C++ to cast like that?

At first sight this seems like meaningless technobabble.

"#ifdef" can't be used to decide on template specialization, "unsigned" can't be
used to alter a named type, and I haven't heard of boost:match_results.

But perhaps you could explain what you're doing and present some /valid/ code?


Cheers,

- Alf
 
B

Bo Persson

DeMarcus said:
void fnc( const MyMatch& match )
{
unsigned int charToInt = match[0].str()[0];
// ...
}

I did like this, which compiles and seems to work...

void fnc( const MyMatch& match )
{
unsigned int charToInt =
(unsigned MyMatch::char_type)match[0].str()[0];
// ...
}

... but is it proper and portable C++ to cast like that?

No, it's not!

Why don't you define a separate function ToInt, and overload that for
the character types you need?


Bo Persson
 
D

DeMarcus

DeMarcus said:
void fnc( const MyMatch& match )
{
unsigned int charToInt = match[0].str()[0];
// ...
}

I did like this, which compiles and seems to work...

void fnc( const MyMatch& match )
{
unsigned int charToInt =
(unsigned MyMatch::char_type)match[0].str()[0];
// ...
}

... but is it proper and portable C++ to cast like that?

No, it's not!

Why don't you define a separate function ToInt, and overload that for
the character types you need?


Bo Persson

You mean something like this?

unsigned int ToInt( char c )
{
unsigned int i = (unsigned char)c;
return i;
}

unsigned int ToInt( wchar_t c )
{
unsigned int i = (unsigned wchar_t)c;
return i;
}
 
D

DeMarcus

* DeMarcus, on 25.10.2010 13:36:
DeMarcus writes:

Hi!

How do I convert a char or wchar_t to an int in a proper and portable
way?

If I do this

char wickedChar = 'Æ';
unsigned int myInt = c;

then myInt is a very big number, it's the sign bit of wickedChar that
does that.

Maybe I could do something like

unsigned int myInt = (unsigned char)c;

but the problem is that this is a template so I don't know if it's
going to be a char or wchar_t (or even something else).

If that's your concern, provide the appropriate specializations for your
template.

Basically it's something like this.

#ifdef SOME_FLAG
typedef boost::match_results<string::const_iterator> MyMatch;
#else
typedef boost::match_results<wstring::const_iterator> MyMatch;
#endif

// More about boost::match_results can be found here.
//
http://www.cs.brown.edu/~jwicks/boost/libs/regex/doc/match_results.html


void fnc( const MyMatch& match )
{
unsigned int charToInt = match[0].str()[0];
// ...
}

I did like this, which compiles and seems to work...

void fnc( const MyMatch& match )
{
unsigned int charToInt =
(unsigned MyMatch::char_type)match[0].str()[0];
// ...
}

... but is it proper and portable C++ to cast like that?

At first sight this seems like meaningless technobabble.

"#ifdef" can't be used to decide on template specialization, "unsigned"
can't be used to alter a named type, and I haven't heard of
boost:match_results.

But perhaps you could explain what you're doing and present some /valid/
code?


Cheers,

- Alf


#include <iostream>

typedef char MySignedChar;

int main()
{
MySignedChar c = 200;

// When doing this I get a very big number.
unsigned int i = c;

std::cout << "Char to int: " << i << std::endl;

// When doing this I get the number I want.
unsigned int i2 = (unsigned MySignedChar)c;

std::cout << "Char to int again: " << i2 << std::endl;

return 0;
}


The boost::match_results can be found here.
http://www.cs.brown.edu/~jwicks/boost/libs/regex/doc/match_results.html

I'm using it like this.

wstring myFormat( const boost::wsmatch& what )
{
uint32 charToInt = (unsigned wsmatch::char_type)what[0].str()[0];
std::cout << charToInt << std::endl;

// ... create replacement ...
return replacement;
}

wstring encode( const wstring& text )
{
const boost::wregex expression( "[^a-zA-Z0-9]" );

return boost::regex_replace( text, expression, myFormat );
}

If there's a better way to do search-and-replace, preferably with
something C++0x compliant, I'm interested in that.
 
A

Alf P. Steinbach /Usenet

* DeMarcus, on 26.10.2010 09:27:
* DeMarcus, on 25.10.2010 13:36:
On 10/25/2010 01:05 PM, Sam wrote:
DeMarcus writes:

Hi!

How do I convert a char or wchar_t to an int in a proper and portable
way?

If I do this

char wickedChar = 'Æ';
unsigned int myInt = c;

then myInt is a very big number, it's the sign bit of wickedChar that
does that.

Maybe I could do something like

unsigned int myInt = (unsigned char)c;

but the problem is that this is a template so I don't know if it's
going to be a char or wchar_t (or even something else).

If that's your concern, provide the appropriate specializations for your
template.


Basically it's something like this.

#ifdef SOME_FLAG
typedef boost::match_results<string::const_iterator> MyMatch;
#else
typedef boost::match_results<wstring::const_iterator> MyMatch;
#endif

// More about boost::match_results can be found here.
//
http://www.cs.brown.edu/~jwicks/boost/libs/regex/doc/match_results.html


void fnc( const MyMatch& match )
{
unsigned int charToInt = match[0].str()[0];
// ...
}

I did like this, which compiles and seems to work...

void fnc( const MyMatch& match )
{
unsigned int charToInt =
(unsigned MyMatch::char_type)match[0].str()[0];
// ...
}

... but is it proper and portable C++ to cast like that?

At first sight this seems like meaningless technobabble.

"#ifdef" can't be used to decide on template specialization, "unsigned"
can't be used to alter a named type, and I haven't heard of
boost:match_results.

But perhaps you could explain what you're doing and present some /valid/
code?


Cheers,

- Alf


#include <iostream>

typedef char MySignedChar;

int main()
{
MySignedChar c = 200;

// When doing this I get a very big number.
unsigned int i = c;

std::cout << "Char to int: " << i << std::endl;

// When doing this I get the number I want.
unsigned int i2 = (unsigned MySignedChar)c;

std::cout << "Char to int again: " << i2 << std::endl;

return 0;
}

Well, as I wrote, you cannot use "unsigned" to alter a named type.

g++ just warns about (perhaps one can instruct it to treat that warning as an
error), while msvc and Comeau diagnose it as error, as is proper:


<g++>
x.cpp: In function 'int main()':
x.cpp:7: warning: overflow in implicit constant conversion
x.cpp:15: warning: long, short, signed or unsigned used invalidly for 'type name'
<g++>

<msvc>
x.cpp
x.cpp(7) : warning C4309: 'initializing' : truncation of constant value
x.cpp(15) : error C2146: syntax error : missing ')' before identifier 'MySignedChar'
x.cpp(15) : error C2059: syntax error : ')'
x.cpp(15) : error C2275: 'MySignedChar' : illegal use of this type as an expression
x.cpp(3) : see declaration of 'MySignedChar'
x.cpp(15) : error C2146: syntax error : missing ';' before identifier 'c'
<msvc

<comeau>
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 7: warning: integer conversion resulted in a change of sign
MySignedChar c = 200;
^

"ComeauTest.c", line 15: error: expected a ")"
unsigned int i2 = (unsigned MySignedChar)c;
^


OK, thanks.

I'm using it like this.

wstring myFormat( const boost::wsmatch& what )
{
uint32 charToInt = (unsigned wsmatch::char_type)what[0].str()[0];
std::cout << charToInt << std::endl;

// ... create replacement ...
return replacement;
}

wstring encode( const wstring& text )
{
const boost::wregex expression( "[^a-zA-Z0-9]" );

return boost::regex_replace( text, expression, myFormat );
}

If there's a better way to do search-and-replace, preferably with something
C++0x compliant, I'm interested in that.

This latter question depends on your criterion for "better", and exactly what
you're doing.

However, for the conversion to "unsigned" consider


typedef unsigned char UChar;

inline unsigned asUnsigned( char c ) { return UChar( c ); }
inline unsigned asUnsigned( wchar_t c ) { return unsigned( c ); }

STATIC_ASSERT( sizeof( unsigned ) >= sizeof( wchar_t ) );

where STATIC_ASSERT might be e.g. BOOST_STATIC_ASSERT.


Cheers & hth.,

- Alf
 
D

DeMarcus

* DeMarcus, on 26.10.2010 09:27:
* DeMarcus, on 25.10.2010 13:36:
On 10/25/2010 01:05 PM, Sam wrote:
DeMarcus writes:

Hi!

How do I convert a char or wchar_t to an int in a proper and portable
way?

If I do this

char wickedChar = 'Æ';
unsigned int myInt = c;

then myInt is a very big number, it's the sign bit of wickedChar that
does that.

Maybe I could do something like

unsigned int myInt = (unsigned char)c;

but the problem is that this is a template so I don't know if it's
going to be a char or wchar_t (or even something else).

If that's your concern, provide the appropriate specializations for
your
template.


Basically it's something like this.

#ifdef SOME_FLAG
typedef boost::match_results<string::const_iterator> MyMatch;
#else
typedef boost::match_results<wstring::const_iterator> MyMatch;
#endif

// More about boost::match_results can be found here.
//
http://www.cs.brown.edu/~jwicks/boost/libs/regex/doc/match_results.html


void fnc( const MyMatch& match )
{
unsigned int charToInt = match[0].str()[0];
// ...
}

I did like this, which compiles and seems to work...

void fnc( const MyMatch& match )
{
unsigned int charToInt =
(unsigned MyMatch::char_type)match[0].str()[0];
// ...
}

... but is it proper and portable C++ to cast like that?

At first sight this seems like meaningless technobabble.

"#ifdef" can't be used to decide on template specialization, "unsigned"
can't be used to alter a named type, and I haven't heard of
boost:match_results.

But perhaps you could explain what you're doing and present some /valid/
code?


Cheers,

- Alf


#include <iostream>

typedef char MySignedChar;

int main()
{
MySignedChar c = 200;

// When doing this I get a very big number.
unsigned int i = c;

std::cout << "Char to int: " << i << std::endl;

// When doing this I get the number I want.
unsigned int i2 = (unsigned MySignedChar)c;

std::cout << "Char to int again: " << i2 << std::endl;

return 0;
}

Well, as I wrote, you cannot use "unsigned" to alter a named type.

g++ just warns about (perhaps one can instruct it to treat that warning
as an error), while msvc and Comeau diagnose it as error, as is proper:


<g++>
x.cpp: In function 'int main()':
x.cpp:7: warning: overflow in implicit constant conversion
x.cpp:15: warning: long, short, signed or unsigned used invalidly for
'type name'
<g++>

<msvc>
x.cpp
x.cpp(7) : warning C4309: 'initializing' : truncation of constant value
x.cpp(15) : error C2146: syntax error : missing ')' before identifier
'MySignedChar'
x.cpp(15) : error C2059: syntax error : ')'
x.cpp(15) : error C2275: 'MySignedChar' : illegal use of this type as an
expression
x.cpp(3) : see declaration of 'MySignedChar'
x.cpp(15) : error C2146: syntax error : missing ';' before identifier 'c'
<msvc

<comeau>
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 7: warning: integer conversion resulted in a change
of sign
MySignedChar c = 200;
^

"ComeauTest.c", line 15: error: expected a ")"
unsigned int i2 = (unsigned MySignedChar)c;
^


OK, thanks.

I'm using it like this.

wstring myFormat( const boost::wsmatch& what )
{
uint32 charToInt = (unsigned wsmatch::char_type)what[0].str()[0];
std::cout << charToInt << std::endl;

// ... create replacement ...
return replacement;
}

wstring encode( const wstring& text )
{
const boost::wregex expression( "[^a-zA-Z0-9]" );

return boost::regex_replace( text, expression, myFormat );
}

If there's a better way to do search-and-replace, preferably with
something
C++0x compliant, I'm interested in that.

This latter question depends on your criterion for "better", and exactly
what you're doing.

Basically I want to do search-and-replace, preferably using
std::tr1::regex. With "better" I mean something compliant to
std::tr1::regex since, as I understand (correct me if I'm wrong), there
are some things with boost::regex that won't go into std::tr1::regex.

I think it's some legacy thing called boost xpressive.

http://www.boost.org/doc/libs/1_40_...t_xpressive.user_s_guide.string_substitutions

However, for the conversion to "unsigned" consider


typedef unsigned char UChar;

inline unsigned asUnsigned( char c ) { return UChar( c ); }
inline unsigned asUnsigned( wchar_t c ) { return unsigned( c ); }

STATIC_ASSERT( sizeof( unsigned ) >= sizeof( wchar_t ) );

where STATIC_ASSERT might be e.g. BOOST_STATIC_ASSERT.


Cheers & hth.,

- Alf

Thanks!
 
B

Bo Persson

DeMarcus said:
DeMarcus said:
void fnc( const MyMatch& match )
{
unsigned int charToInt = match[0].str()[0];
// ...
}

I did like this, which compiles and seems to work...

void fnc( const MyMatch& match )
{
unsigned int charToInt =
(unsigned MyMatch::char_type)match[0].str()[0];
// ...
}

... but is it proper and portable C++ to cast like that?

No, it's not!

Why don't you define a separate function ToInt, and overload that
for the character types you need?


Bo Persson

You mean something like this?

unsigned int ToInt( char c )
{
unsigned int i = (unsigned char)c;
return i;
}

unsigned int ToInt( wchar_t c )
{
unsigned int i = (unsigned wchar_t)c;
return i;
}

Yes, except that wchar_t already is unsigned (and that you cannot add
or remove signedness - it really should have been unsigned_char to be
regular and avoid keywords that look like two words).


Bo Persson
 
B

Bo Persson

Pete said:
Yes, except that wchar_t already is unsigned (and that you cannot
add or remove signedness - it really should have been
unsigned_char to be regular and avoid keywords that look like two
words).

wchar_t does not have to be unsigned. It has to have "[t]he same
size, signedness, and alignment requirements as one of the other
integral types...".

Right. I just haven't seen a case where it was signed.

And you still cannot ask for an unsigned version, even if it is
signed.


Bo Persson
 
Ö

Öö Tiib

Pete said:
On 2010-10-26 13:22:22 -0400, Bo Persson said:
wchar_t does not have to be unsigned. It has to have "[t]he same
size, signedness, and alignment requirements as one of the other
integral types...".

Right. I just haven't seen a case where it was signed.

And you still cannot ask for an unsigned version, even if it is
signed.

#include <limits>
#include <boost/static_assert.hpp>
BOOST_STATIC_ASSERT( !std::numeric_limits<wchar_t>::is_signed );
 
J

James Kanze

Pete said:
On 2010-10-26 13:22:22 -0400, Bo Persson said:
Yes, except that wchar_t already is unsigned (and that you cannot
add or remove signedness - it really should have been
unsigned_char to be regular and avoid keywords that look like two
words).
wchar_t does not have to be unsigned. It has to have "[t]he same
size, signedness, and alignment requirements as one of the other
integral types...".
Right. I just haven't seen a case where it was signed.

I think it's signed more often than it is unsigned. Logically,
one would expect it to have the same signedness as char, so
promotions would conserve the value. (Of course, logically, one
would expect plain char to always be unsigned, so you could use
it directly as an argument to the functions in <ctype.h>. But
for histerical^H^H^H^H^H^Horical reasons, it's more often signed
than not.)

On 32 bit systems where wchar_t is 16 bit, it might generally be
unsigned. On 32 bit systems where wchar_t is 32 bits (the
majority, I think), it will almost certainly be signed, so that
wint_t can also be 32 bits.
 

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

Forum statistics

Threads
473,994
Messages
2,570,222
Members
46,810
Latest member
Kassie0918

Latest Threads

Top