char to int conversion - what's happening here? - c++

I want to convert a char value to an int. I am playing with following code snippets:
#include <iostream>
using namespace std;
int main() {
char a = 'A';
int i = (int)a;
//cout<<i<<endl; OUTPUT is 65 (True)
char b = '18';
int j = b;
//cout<<j<<endl; OUTPUT is 56 (HOW?)
char c = 18;
int k = c;
//cout<<c<<endl; OUTPUT is empty
//cout<<k<<endl; OUTPUT is 18 (Is this a valid conversion?)
return 0;
}
I want the third conversion, and I got correct output i.e 18. But is this a valid conversion? Can anyone please explain the above outputs and their strategies?

char a = 'A';
int i = (int)a;
The cast is unnecessary. Assigning or initializing an object of a numeric type to a value of any other numeric type causes an implicit conversion.
The value stored in i is whatever value your implementation uses to represent the character 'A'. On almost all systems these days (except some IBM mainframes and maybe a few others), that value is going to be 65.
char b = '18';
int j = b;
A character literal with more than one character is of type int and has an implementation-defined value. It's likely that the value will be '1'<<8+'8', and that the conversion from char to int drop the high-order bits, leaving '8' or 56. But multi-character literals are something to be avoided. (This doesn't apply to escape sequences like '\n'; though there are two characters between the single quotes, it represents a single character value.)
char c = 18;
int k = c;
char is an integer type; it can easily hold the integer value 18. Converting that value to int just preserves the value. So both c and k are integer variables whose valie is 18. Printing k using
std::cout << k << "\n";
will print 18, but printing c using:
std::cout << c << "\n";
will print a non-printable control character (it happens to be Control-R).

char b = '18';
int j = b;
b, in this case a char of '18' doesn't have a very consistent meaning, and has implementation-dependent behaviour. In your case it appears to get translated to ascii value 56 (equivalent to what you would get from char b = '8').
char c = 18;
int k = c;
c holds character value 18, and it's perfectly valid to convert to an int. However, it might not display very much if you display as a character. It's a non-printing control character.

Related

how to I Convert a particular character Integer Element To Integer? [duplicate]

How do I convert a char to an int in C and C++?
Depends on what you want to do:
to read the value as an ascii code, you can write
char a = 'a';
int ia = (int)a;
/* note that the int cast is not necessary -- int ia = a would suffice */
to convert the character '0' -> 0, '1' -> 1, etc, you can write
char a = '4';
int ia = a - '0';
/* check here if ia is bounded by 0 and 9 */
Explanation:
a - '0' is equivalent to ((int)a) - ((int)'0'), which means the ascii values of the characters are subtracted from each other. Since 0 comes directly before 1 in the ascii table (and so on until 9), the difference between the two gives the number that the character a represents.
Well, in ASCII code, the numbers (digits) start from 48. All you need to do is:
int x = (int)character - 48;
Or, since the character '0' has the ASCII code of 48, you can just write:
int x = character - '0'; // The (int) cast is not necessary.
C and C++ always promote types to at least int. Furthermore character literals are of type int in C and char in C++.
You can convert a char type simply by assigning to an int.
char c = 'a'; // narrowing on C
int a = c;
char is just a 1 byte integer. There is nothing magic with the char type! Just as you can assign a short to an int, or an int to a long, you can assign a char to an int.
Yes, the name of the primitive data type happens to be "char", which insinuates that it should only contain characters. But in reality, "char" is just a poor name choice to confuse everyone who tries to learn the language. A better name for it is int8_t, and you can use that name instead, if your compiler follows the latest C standard.
Though of course you should use the char type when doing string handling, because the index of the classic ASCII table fits in 1 byte. You could however do string handling with regular ints as well, although there is no practical reason in the real world why you would ever want to do that. For example, the following code will work perfectly:
int str[] = {'h', 'e', 'l', 'l', 'o', '\0' };
for(i=0; i<6; i++)
{
printf("%c", str[i]);
}
You have to realize that characters and strings are just numbers, like everything else in the computer. When you write 'a' in the source code, it is pre-processed into the number 97, which is an integer constant.
So if you write an expression like
char ch = '5';
ch = ch - '0';
this is actually equivalent to
char ch = (int)53;
ch = ch - (int)48;
which is then going through the C language integer promotions
ch = (int)ch - (int)48;
and then truncated to a char to fit the result type
ch = (char)( (int)ch - (int)48 );
There's a lot of subtle things like this going on between the lines, where char is implicitly treated as an int.
(This answer addresses the C++ side of things, but the sign extension problem exists in C too.)
Handling all three char types (signed, unsigned, and char) is more delicate than it first appears. Values in the range 0 to SCHAR_MAX (which is 127 for an 8-bit char) are easy:
char c = somevalue;
signed char sc = c;
unsigned char uc = c;
int n = c;
But, when somevalue is outside of that range, only going through unsigned char gives you consistent results for the "same" char values in all three types:
char c = somevalue;
signed char sc = c;
unsigned char uc = c;
// Might not be true: int(c) == int(sc) and int(c) == int(uc).
int nc = (unsigned char)c;
int nsc = (unsigned char)sc;
int nuc = (unsigned char)uc;
// Always true: nc == nsc and nc == nuc.
This is important when using functions from ctype.h, such as isupper or toupper, because of sign extension:
char c = negative_char; // Assuming CHAR_MIN < 0.
int n = c;
bool b = isupper(n); // Undefined behavior.
Note the conversion through int is implicit; this has the same UB:
char c = negative_char;
bool b = isupper(c);
To fix this, go through unsigned char, which is easily done by wrapping ctype.h functions through safe_ctype:
template<int (&F)(int)>
int safe_ctype(unsigned char c) { return F(c); }
//...
char c = CHAR_MIN;
bool b = safe_ctype<isupper>(c); // No UB.
std::string s = "value that may contain negative chars; e.g. user input";
std::transform(s.begin(), s.end(), s.begin(), &safe_ctype<toupper>);
// Must wrap toupper to eliminate UB in this case, you can't cast
// to unsigned char because the function is called inside transform.
This works because any function taking any of the three char types can also take the other two char types. It leads to two functions which can handle any of the types:
int ord(char c) { return (unsigned char)c; }
char chr(int n) {
assert(0 <= n); // Or other error-/sanity-checking.
assert(n <= UCHAR_MAX);
return (unsigned char)n;
}
// Ord and chr are named to match similar functions in other languages
// and libraries.
ord(c) always gives you a non-negative value – even when passed a negative char or negative signed char – and chr takes any value ord produces and gives back the exact same char.
In practice, I would probably just cast through unsigned char instead of using these, but they do succinctly wrap the cast, provide a convenient place to add error checking for int-to-char, and would be shorter and more clear when you need to use them several times in close proximity.
Use static_cast<int>:
int num = static_cast<int>(letter); // if letter='a', num=97
Edit: You probably should try to avoid to use (int)
int num = (int) letter;
check out Why use static_cast<int>(x) instead of (int)x? for more info.
I have absolutely null skills in C, but for a simple parsing:
char* something = "123456";
int number = parseInt(something);
...this worked for me:
int parseInt(char* chars)
{
int sum = 0;
int len = strlen(chars);
for (int x = 0; x < len; x++)
{
int n = chars[len - (x + 1)] - '0';
sum = sum + powInt(n, x);
}
return sum;
}
int powInt(int x, int y)
{
for (int i = 0; i < y; i++)
{
x *= 10;
}
return x;
}
It sort of depends on what you mean by "convert".
If you have a series of characters that represents an integer, like "123456", then there are two typical ways to do that in C: Use a special-purpose conversion like atoi() or strtol(), or the general-purpose sscanf(). C++ (which is really a different language masquerading as an upgrade) adds a third, stringstreams.
If you mean you want the exact bit pattern in one of your int variables to be treated as a char, that's easier. In C the different integer types are really more of a state of mind than actual separate "types". Just start using it where chars are asked for, and you should be OK. You might need an explicit conversion to make the compiler quit whining on occasion, but all that should do is drop any extra bits past 256.
I recomend to use the following function:
/* chartoint: convert char simbols to unsigned int*/
int chartoint(char s[])
{
int i, n;
n = 0;
for (i = 0; isdigit(s[i]); ++i){
n = 10 * n + (s[i] - '0');
}
return n;
}
The result of function could be checked by:
printf("char 00: %d \r\n", chartoint("00"));
printf("char 01: %d \r\n", chartoint("01"));
printf("char 255: %d \r\n", chartoint("255"));
Presumably you want this conversion for using functions from the C standard library.
In that case, do (C++ syntax)
typedef unsigned char UChar;
char myCppFunc( char c )
{
return char( someCFunc( UChar( c ) ) );
}
The expression UChar( c ) converts to unsigned char in order to get rid of negative values, which, except for EOF, are not supported by the C functions.
Then the result of that expression is used as actual argument for an int formal argument. Where you get automatic promotion to int. You can alternatively write that last step explicitly, like int( UChar( c ) ), but personally I find that too verbose.
Cheers & hth.,
I was having problems converting a char array like "7c7c7d7d7d7d7c7c7c7d7d7d7d7c7c7c7c7c7c7d7d7c7c7c7c7d7c7d7d7d7c7c2e2e2e" into its actual integer value that would be able to be represented by `7C' as one hexadecimal value. So, after cruising for help I created this, and thought it would be cool to share.
This separates the char string into its right integers, and may be helpful to more people than just me ;)
unsigned int* char2int(char *a, int len)
{
int i,u;
unsigned int *val = malloc(len*sizeof(unsigned long));
for(i=0,u=0;i<len;i++){
if(i%2==0){
if(a[i] <= 57)
val[u] = (a[i]-50)<<4;
else
val[u] = (a[i]-55)<<4;
}
else{
if(a[i] <= 57)
val[u] += (a[i]-50);
else
val[u] += (a[i]-55);
u++;
}
}
return val;
}
Hope it helps!
For char or short to int, you just need to assign the value.
char ch = 16;
int in = ch;
Same to int64.
long long lo = ch;
All values will be 16.
Use "long long" instead a "int" so it works for bigger numbers. Here the elegant solution.
long long ChardToint(char *arr, size_t len){
int toptenf=1;
long long toptenLf=10000000LL;
long long makeintf=3000000000000;
makeintf= 0LL;
int holdNumberf=0;
for(int i=len-1;i>=0 ;i--){
switch(arr[i]){
case '0':
holdNumberf=0;
break;
case '1':
holdNumberf=1;
break;
case '2':
holdNumberf=2;
break;
case '3':
holdNumberf=3;
break;
case '4':
holdNumberf=4;
break;
case '5':
holdNumberf=5;
break;
case '6':
holdNumberf=6;
break;
case '7':
holdNumberf=7;
break;
case '8':
holdNumberf=8;
break;
case '9':
holdNumberf=9;
break;
default:
holdNumberf=0;
}
if(toptenf>=10000000){
makeintf=makeintf+holdNumberf*toptenLf;
toptenLf=toptenLf*10;
}else{
makeintf=makeintf+holdNumberf*toptenf;
toptenf=toptenf*10;
}
}
return makeintf;
}
int charToint(char a){
char *p = &a;
int k = atoi(p);
return k;
}
You can use this atoi method for converting char to int. For more information, you can refer to this http://www.cplusplus.com/reference/cstdlib/atoi/ , http://www.cplusplus.com/reference/string/stoi/.

How to convert unsigned char to unsigned int in c++?

I have the following piece of code:
const unsigned char *a = (const unsigned char *) input_items;
input_items is basically the contents of a binary file.
Now a[0] = 7, and i want to convert this value to unsigned int. But when I do the following:
unsigned int b = (unsigned int) a[0];
and print both of these values, I get:
a[0] = 7
b = 55
Why does b not contain 7 as well? How do I get b = 7?
I think I see the problem now: You print the value of the character as a character:
unsigned char a = '7';
std::cout << a << '\n';
That will print the character '7', with the ASCII value 55.
If you want to get the corresponding integer value for the digit character, you can rely on that all digit characters must be consecutively encoded, starting with zero and ending with nine. Which means you can subtract '0' from any digit character to get its integer value:
unsigned char a = '7';
unsigned int b = a - '0';
Now b will be equal to the integer value 7.

How could I cast a c++ unsigned char variable to a char variable while keeps its value

Sorry, I have gone through my code and find the place where my problem actually lies.
I hope to cast number in c++ approach. The original variable is unsigned char which I stored in a char variable a. Now I need to cast this a to double while keeping its original unsigned value. How could I do this ?
Edit:
I didn't expect my problem should be so confusing. Here is a brief example
unsigned char a;
double b;
a = 140;
char c = static_cast<char>(a);
b = static_cast<double>(c);
std::cout << b << std::endl;
This prints a result of -116, but what I actually hopes is a double 140. How could I do this then ?
Edit v2:
The scene is like this: I read 1024 bytes from a file with fstream. The 1024 bytes contains int numbers as well as unsigned char numbers. These unsigned char numbers I mean to cast to double types. I simplly read all of them to a std::vector<char> array, and then I need to unpack these numbers. Some part of them are to be cast to double and I met my problem here.
If my problem is brought by abuse of c++, what is the correct way to handle this task please ?
This works:
b = static_cast<double>(static_cast<unsigned char>(c));
or:
b = static_cast<unsigned char>(c);
or:
b = c < 0 ? c + 256 : c;
In c++, char max number is 127, in the assign: char a = 128; you actually get char Min value, which is -128, what means that 140 will give you a result of -116. To solve this use unsigned char, that have max value of 255. Look at the table of the types Max/Min value that in the link.
https://msdn.microsoft.com/en-us/library/7fh3a000.aspx
unsigned char a = 140;
int b = a;
cout << b << endl; // 140
When you store the value of 140 in a char variable it will be out of the range of -128 to +127 for the character.
The value of 140 is converted to -119 The mechanism for this is dependent on the implementation.
The value of -119 is then converted to double and displayed as -119 in double.
What you can do is directly cast the unsigned char numbers to double. This will solve your range issues.
unsigned char a;
a = 140;
b = static_cast<double>(a);
std::cout << b << std::endl;

How to use char data type as a number rather than a character?

When I use the char datatype to add two numbers, I get the sum of the ASCII code of the characters and not the numbers itself. When I researched on the internet, various sites say that the char type can indeed be used to handle one byte numbers. But in reality, I get the sum of ASCII values. Why is this happening? Below is just a sample code which illustrates the problem:
uint8_t rows,cols; //uint8_t is just a typedef for char
cin >> rows;
cout << rows + 1 << endl;
When people talk about "one-byte numbers", they're talking about 8-bit values, ranging from -128 to 127 for a char, or 0 to 255 for an unsigned char, also known as octets. These can be converted directly to larger integer types and to floats:
char eight_bit = 122;
float floating_point = eight_bit; // = 122.0
If you're trying to convert a digit value such as '1' into the numeric value it represents, there's stoi:
#include <string>
int ctoi(char c) {
std::string temp;
temp.push_back(c);
return std::stoi(temp);
}
Chars store the ASCII equivalent of a character as an integer.
For example
char value = 'A' // == int 65
It's best you use a short integer to store numbers, but if you really want to, you can do something like this;
char value1 = '2';
char value2 = '5';
char sum = (value1 + value2) - '0'; // int value of sum would be 7
When you use char, you use signed 8 bit data type (mostly).
And you get "sum of ASCII" only because std::cout is programmed to display char as ASCII character.
Try
cout << stratic_cast<int16_t>(rows) + 1 << endl;
And you will see that you get the 'number' rather than an 'ASCII character'.
NOTE
uint8_t is not (or probably should not be) char since char is defined as signed data type while uint* stands for unsigned.

How to convert a hexadecimal value contained in a char (byte) to an integer?

I just want to know how to convert an hexadecimal value contained in a char (byte) into an integer. I want to convert the color buffer from a .bmp file which is of course in hexadecimal and convert it in integers.
For example :
char rgb_hexa[3] = {0xA8, 0xF4, 0xD3};
After conversion :
int rgb_int[3] = {168, 244, 211};
I always tried to use strtol but it seems to only works with char *. I tried to do the following test but it does not work :
char src_hexa_red = 0xA8;
char src_hexa_green = 0xF4;
char src_hexa_blue = 0xD3;
std::cout << "R=" << strtol(&src_hexa_red, (char**)NULL, 16) << ", G="
<< strtol(&src_hexa_green, (char**)NULL, 16) << ", B="
<< strtol(&src_hexa_blue, (char**)NULL, 16) << std::endl;
Does anyone can help me please ?
Thanks in advance for your help.
A single char never contains hexadecimal. Nor decimal, for
that matter. Strictly speaking, a char contains an integral
value; the C++ standard requires it to use a binary
representation for the value. The value can be interpreted as
a character, but this is not always the case; there are contexts
where the integral value is used directly.
Hexadecimal and decimal are just ways of representing the value
in text format. They only have meaning when dealing with text.
for(int i = 0; i < 3; ++i)
rgb_int[i] = (unsigned char)rgb_hexa[i];
char is an integer type in C & C++ just like short, int and long. It's just the smallest integer type. Mostly, char is signed & the maximum which can fit is 127. So if the hex value was below or equal to 127, you wouldn't have to do anything. However, in this case the hex values you have are > 127 - hence you would have to cast them to unsigned to get the value you want.
Note that both the statements are identical to the compiler.
char rgb_hexa[3] = {0xA8, 0xF4, 0xD3};
char rgb_hexa[3] = {168, 244, 211};
You could have even used octal if you wanted
char rgb_hexa[3] = {0250, 0364, 0323};
It's all the same.
The values in the char array are already in a binary form, so you can cast them to an int, if you need them as such.
int v = (int)rgb_hexa[0];
You should be aware though that using signed char they will be sign extendend.
So 0xFA becomes 0xFFFFFFFA when converted to an int.
If you want to keep the values then you should use unsigned char and unsigned int which makes it 0x000000FA depending on how you want to use the values.
int v0 = (int)a[1]; <-- sign extended
unsigned int v1 = (unsigned int)a[1]; <-- sign extended
unsigned int v1 = (unsigned int)((unsigned char *)a)[1]; <-- not sign extended
You don't need to do any conversion because hexa/decimal are just ways to represent values.
For example 0xA8 in hexadecimal is the same value as 180 in decimal and 250 in octal. As in languages for example, "two", "deux" and "dois" represent all the same number (2).
In your case if you want to print the values do the following:
short y = (short) x & 0x00FF; // x is the char you want to print
cout << "Value (decimal): " << y;
cout << "Value (hexa): " << hex << y;
cout << "Value (oct): " << oct << y;
Why can't you do this
int main(int argc, char *argv[])
{
char rgb_hexa[3] = {0xA8, 0xF4, 0xD3};
int rgb_int[3] = {0,};
int i = 0;
for( i = 0 ; i < 3 ;i++)
rgb_int[i] = (unsigned char)rgb_hexa[i];
for( i = 0 ; i < 3 ;i++)
printf("%d ",rgb_int[i]);
return 0;
}
pretty straight forward ..
For type conversion, there is static_cast:
unsigned char source = 168; // note that this has for compiler same meaning as:
// unsigned char source = 0xA8; // because data is stored in binary anyway
unsigned int dest = static_cast<int>(source); // the conversion
std::cout << source << std::endl;
dest and source have same binary meaning, but they are of a different type.
I've used unsigned types, because signed char stores usually values from -127 to 127, see limits.