I am fairly new to C++ and i have some trouble in understanding character subtraction in c++.
I had this code intially
char x='2';
x-='0';
if(x) cout << "More than Zero" << endl;
This returned More than Zero as output so to know the value of x i tried this code.
char x='2';
x-='0';
if(x) cout << x << endl;
And i am getting null character(or new line) as output.
Any help is appreciated.
According to the C++ Standard (2.3 Character sets)
...In both the source and execution basic character sets, the value of
each character after 0 in the above list of decimal digits shall be
one greater than the value of the previous.
So the codes of adjacent digits in any character set differ by 1.
Thus in this code snippet
char x='2';
x-='0';
if(x) cout << x << endl;
the difference between '2' and '0' (the difference between codes that represent these characters; for example in ASCII these codes are 0x32 and 0x30 while in EBCDIC they are 0xF2 and 0xF0 correspondingly) is equal to 2.
You can check this for example the following way
if(x) cout << ( int )x << endl;
or
if(x) cout << static_cast<int>( x ) << endl;
If you just write
if(x) cout << x << endl;
then the operator << tries to output x as a printable character image of the value 2 because x is of type char.
In C/C++ characters are stored as 8-bit integers with ASCII encoding. So when you do x-='0'; you're subtracting the ASCII value of '0' which is 48 from the ASCII value of '2' which is 50. x is then equal to 2 which is a special control character stating STX (start of text), which is not printable.
If you want to perform arithmetic on characters it's better to subtract '0' from every character before any operation and adding '0' to the result. To avoid problems like running over the range of the 8bit value I'd suggest to cast them on ints or longs.
char x = '2';
int tempVal = x - '0';
/*
Some operations are performed here
*/
x = tempValue % 10 + '0';
// % 10 - in case it excedes the range reserved for numbers in ASCII
cout << x << endl;
It's much safer to perform these operations on larger value types, and subtracting the '0' character allows you to perform operations independent on the ASCII encoding like you'd do with casual integers. Then you add '0' to go back to the ASCII encoding, which alows you to print a number.
You are substracting 48 (ascii char '0') to the character 50 (ascii '2')
50 - 48 = 2
if (x) ' true
In C++, characters are all represented by an ASCII code (see http://www.asciitable.com/)
I guess that doing :
'2' - '0'
is like doing
50 - 48 = 2
According to the ASCII table, the ASCII code 2 stands for start of text, which is not displayed by cout.
Hope it helps.
So what your code is doing is the following:
x = '2', which represents 50 as a decimal value in the ASCII table.
then your are basically saying:
x = x - '0', where zero in the ASCII table is represented as 48 in decimal, which equates to x = 50 - 48 = 2.
Note that 2 != '2' . If you look up 2(decimal) in the ASCII table that will give you a STX (start of text). This is what your code is doing. So keep in mind that the subtraction is taking place on the decimal value of the char.
Related
I have an example:
int var = 5;
char ch = (char)var;
char ch2 = var+48;
cout << ch << endl;
cout << ch2 << endl;
I had some other code. (char) returned wrong answer, but +48 didn't. When I changed ONLY (char) to +48, then my code got corrected.
What is the difference between converting int to char by using (char) and +48 (ASCII) in C++?
char ch=(char)var; has the same effect as char ch=var; and assigns the numeric value 5 to ch. You're using ASCII (supported by all modern systems) and ASCII character code 5 represents Enquiry 'ENQ' an old terminal control code. Perhaps some old timer has a clue what it did!
char ch2 = var+48; assigns the numeric value 53 to ch2 which happens to represent the ASCII character for the digit '5'. ASCII 48 is zero (0) and the digits all appear in the ASCII table in order after that. So 48+5 lands on 53 (which represents the character '5').
In C++ char is a integer type. The value is interpreted as representing an ASCII character but it should be thought of as holding a number.
Its numeric range is either [-128,127] or [0,255]. That's because C++ requires sizeof(char)==1 and all modern platforms have 8 bit bytes.
NB: C++ doesn't actually mandate ASCII, but again that will be the case on all modern platforms.
PS: I think its an unfortunate artifact of C (inherited by C++) that sizeof(char)==1 and there isn't a separate fundamental type called byte.
A char is simply the base integral denomination in c++. Output statements, like cout and printf map char integers to the corresponding character mapping. On Windows computers this is typically ASCII.
Note that the 5th in ASCII maps to the Enquiry character which has no printable character, while the 53rd character maps to the printable character 5.
A generally accepted hack to store a number 0-9 in a char is to do: const char ch = var + '0' It's important to note the shortcomings here:
If your code is running on some non-ASCII character mapping then characters 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9 may not be laid out in order in which case this wouldn't work
If var is outside the 0 - 9 range this var + '0' will map to something other than a numeric character mapping
A guaranteed way to get the most significant digit of a number independent of 1 or 2 is to use:
const auto ch = to_string(var).front()
Generally char represents a number as int does. Casting an int value to char doesn't provide it's ASCII representation.
The ASCII codes as numbers for digits range from 48 (== '0') to 58 (== '9'). So to get the printable digit you have to add '0' (or 48).
The difference is that casting to char (char) explicitly converts the digit to a char and adding 48 do not.
Its important to note that an int is typically 32 bit and char is typically 8 bit. This means that the number you can store in a char is from -127 to +127(or 0 to 255-(2^8-1) if you use unsigned char) and in an int from −2,147,483,648 (−231) to 2,147,483,647 (231 − 1)(or 0 to 2^32 -1 for unsigned).
Adding 48 to a value is not changing the type to char.
int main()
{
string s;
cout << "enter the string :" << endl;
cin >> s;
for (int i = 0; i < s.length(); i++)
s[i] ^= 32;
cout << "modified string is : " << s << endl;
return 0;
}
I saw this code which converts uppercase to lowercase on stackoverflow.
But I don't understand the line s[i] = s[i]^32.
How does it work?
^= is the exclusive-or assignment operator. 32 is 100000 in binary, so ^= 32 switches the fifth bit in the destination. In ASCII, lower and upper case letters are 32 positions apart, so this converts lower to upper case, and also the other way.
But it only works for ASCII, not for Unicode for example, and only for letters. To write portable C++, you should not assume the character encoding to be ASCII, so please don't use such code. #πάντα ῥεῖs answer shows a way to do it properly.
How does it work?
Let's see for ASCII value 'A':
'A' is binary 1000001
XORed with 32 (binary 100000)
yields any value where the upper character indicating bit isn't set:
1000001
XOR
100000
= 1100001 == 'a' in ASCII.
Any sane and portable c or c++ application should use tolower():
int main()
{
string s;
cout<<"enter the string :"<<endl;
cin>>s;
for (int i=0;i<s.length();i++) s[i] = tolower( (unsigned char)s[i] );
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cout<<"modified string is : "<<s<<endl;
return 0;
}
The s[i]=s[i]^32 (cargo cult) magic, relies on ASCII table specific mapping to numeric char values.
There are other char code tables like e.g. EBCDIC
, where the
s[i]=s[i]^32
method miserably fails to retrieve the corresponding lower case letters.
There's a more sophisticated c++ version of converting to lower case characters shown in the reference documentation page of std::ctype::tolower().
In C++, like its predecessor C, a char is a numeric type. This is after all how characters are represented on the hardware and these languages don't hide that from you.
In ASCII, letters have the useful property that the difference between an uppercase and a lowercase letter is a single binary bit: the 5th bit (if we start numbering from the right starting at 0).
Uppercase A is represented by the byte 0b01000001 (0x41 in hex), and lowercase a is represented by the byte 0b01100001 (0x61 in hex). Notice that the only difference between uppercase and lowercase A is the fifth bit. This pattern continues from B to Z.
So, when you do ^= 32 (which, incidentally, is 2 to the 5th power) on a number that represents an ASCII character, what that does is toggle the 5th bit - if it is 0, it becomes 1, and vice versa, which changes the character from upper to lower case and vice versa.
If I want to compile the following code:
int x = 8;
int y = 17;
char final[2];
final[0] = (char) x;
final[1] = (char) y%10;
cout << final[0] << final[1] << endl;
It shows nothing. I don't know why? So how can I successfully convert it?
(char)8 is not '8', but the ASCII value 8 (the backspace character). To display the character 8 you can add it to '0':
int x = 8;
int y = 17;
char final[2];
final[0] = '0' + x;
final[1] = '0' + (y%10);
cout << final[0] << final[1] << endl;
As per your program you are printing char 8, and char 7.
They are not printable. In fact they are BELL and Backspace characters respectively.
Just run you program and redirect it to a file.
Then do an hexdump, you will see what is printed.
./a.out > /tmp/b
hd /tmp/b
00000000 08 07 0a |...|
00000003
What you need to understand is that in C++, chars are numbers, just like ints, only in a smaller range. When you cast the integer 8 to char, C++ thinks you want a char holding the number 8. If we look at our handy ASCII table, we can see that 8 is BS (backspace) and 7 is BEL (which sometimes rings a bell when you print it to a terminal). Neither of those are printable, which is why you aren't seeing anything.
If you just want to print the 87 to standard output, then this code will do that:
cout << x << (y%10) << endl;
If you really need to convert it chars first, then fear not, it can still be done. I'm not much of a C++ person, but this is the way to do it in C:
char final[2];
snprintf(final, sizeof final, "%d%d", x, y % 10);
(See snprintf(3))
This code treats the 2-char array as a string, and writes the two numbers you specified to it using a printf format string. Strings in C normally end with a NUL byte, and if you extended the array to three chars, the final char would be set to NUL. But because we told snprintf how long the string is, it won't write more chars than it can.
This should also work in C++.
I've created a sudoku game in which you will enter the row number then the column number. I set an if else condition that only numbers 1-9 will be entered. I used getch function instead of cin after entering a number to avoid using the enter button.
But when I enter 1 in row, it won't accept it and it prints the number 49. I've researched about it and learned that getch function is for get character and if you enter 1, it will translate to '1' which is equivalent of 49 in integer. I've found a solution by using getch() -'0' instead of only getch();
It works but I can't seem to understand the explanation about how it works. Can someone explain it how the getch() -'0' works?
Here's where I used the getch() -'0':
cout << "Enter row: "; row = getch() -'0';
if(row > 9 || row < 1) {
cout << "Rows 1 to 9 only!" << endl;
Sleep(1000);
system("cls");
loop -= 1;
} else {
cout << row << "\nEnter column: "; column = getch() -'0';
if(column > 9 || column < 1) {
cout << "Columns 1 to 9 only!" << endl;
Sleep(1000);
system("cls");
loop -= 1;
}
getch() will get the value of a char and translate that to its int value. Which is why you get 49.
Now if chars have int values and 1 is 49, imagine subtracting the int value of 0 away from that. The numbers are in order from 0-9, so if one has 49, then zero has 48. So you are saying, get this int value (1 = 49) and subtract away 0's int value (48), 49-48 = 1.
This works for all char's which represent numbers. Ex: 8 - '0' == 56 - 48 = 8.
This trick is relying on the fact that the encoding for the numbers 0-9 are in order in the character sequence, in ASCII they are the values 48-57. So if the character '4' is typed, it will return 52, and you can convert that to the number via 52 - 48 = 4. The danger of course is that someone will enter a non-number - you need to check carefully for error.
Its similiar as you write
int k=getch() //stores ascii value of the entered character
As the ascii value of character '0' is 48 so if you substract k by 48 u will get the corresponding entered number
similiar thing happens here---
getch()-'0'
getch() returns the ascii code for the pressed key.
The ascii codes for the number 0..9 are contiguous, 0 = 48, 1 = 49, 2 = 50, and so on.
The C/C++ compiler converts a single-quoted character into its ascii code, so '0' compiles to 48.
getch() - '0' is subtracting the ascii code offset of the digits range from the typed number, yielding the offset of the pressed digit from 0. 0 is at offset 0, 1 is at offset 1, 2 is at offset 2, and so on.
Note that you are not subtracting 0 but '0'. This is a big difference because '0' is a char so when you subtract it, you are implicitly converting it to an int value which is 48 in ASCII. So you are basically reading in values that are "indexes" to chars in the ASCII table, then subtracting the index of the first char you care about to get relative "indexes". Your if statement should take care of any invalid chars including letters and symbols so this should work fine.
Is the code below converting a character into its ASCII value?.
I faced a piece of code while studying evaluation of postfix operation,where it says "the expression converts a single digit character in C to its numerical value".?
int x=getch();
int c=x-'0'; /*does c have the ASCII value of x?*/
printf("%d",c);
No, it's converting the ASCII value to a number >= 0.
Let's say you type '1'. getch() will return 49 which is the ASCII value of '1'. 49 - '0' is the same as 49 - 48 (48 being the ASCII value for '0'). Which gives you 1.
Note that this code is broken if you enter a character that is not a number.
E.g. if you type 'r' it will print 'r' - '0' = 114 - 48 = 66
(Ref.)
No, it's giving the numeric value of a digit. So '5' (53 in ASCII) becomes 5.
Is the code below converting a character into its ASCII value?
It isn't. It's doing the opposite (converting an ASCII value to the numerical value) and it only works for decimal digits.
To print the ascii value all you need to do is :
int x=getch();
printf("%d",x);
If you are sure that you only want to accept integers as input then you need to put some constraints to the input before proceeding to process them.
int x = getch();
if (x >='0' || x <= '9') {
int c = x - '0'; // c will have the value of the digit in the range 0-9
. . .
}
Any character(in your case numbers) enclosed within single quotes is compiled to its ASCII value. The following line in the snippet above translates to,
int c=x-'0'; ---> int c= x-48; //48 is the ASCII value of '0'
When the user inputs any character to your program, it gets translated to integer as follow,
If x = '1', ASCII of '1' = 49, so c= 49-48 = 1
If x = '9', ASCII of '9' = 57, so c= 57-48 = 9 and so on.