why are we adding and subtracting '0' here? [duplicate] - c++

This question already has answers here:
Why does subtracting '0' in C result in the number that the char is representing?
(8 answers)
Closed 10 months ago.
while solving a leetcode challange , I stumbled upon various solutions that were adding and subtracting '0' for successful submission and I have no idea why . any help? I mostly do linked list and array so this problem is quite new to me .
class Solution {
public:
string addBinary(string a, string b) {
string result;
int i=a.size()-1;
int j=b.size()-1;
int carry = 0;
while(i>=0 || j>=0|| carry)
{
if(i>=0)
{ carry += a[i] - '0';//like here
i--;}
if(j>=0)
{ carry += a[j] - '0';//here
j--;
}
result += (carry%2 + '0'); //and here as well
carry = carry/2;
}
reverse(result.begin(),result.end());
return result;
}
};

In C++, '0' is a character literal.
The fundamental reason why/how a[i] - '0' works is through promotion. This is because:
arithmetic operators do not accept types smaller than int as arguments, and integral promotions are automatically applied after lvalue-to-rvalue conversion, if applicable
In particular when you wrote:
a[i]-'0'
This means
both a[i] and '0' will be promoted to an int. And so the result will be an int.
Let's looks at some example for more clarifications:
char c1 = 'E';
char c2 = 'F';
int result = c1 + c2;
Here both c1 and c2 will be promoted to an int. And the result will be an int. In particular, c1 will become(promoted to) 69 and c2 will become(promoted to) 70. And so result will be 69 + 70 which is the integer value 139.
This also makes the program more portable than using magic numbers.
Also note that the C++ Standard (2.3 Character sets) guarantees that:
...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.
For example, say we have:
std::string str = "123";
int a = str[0] - '0'; //the result of str[0] - '0' is guaranteed to be the integer 1
int b = str[1] - '0'; //the result of str[1] - '0' is guaranteed to be the integer 2
int c = str[2] - '0'; //the result of str[2] - '0' is guaranteed to be the integer 3
Lets consider the statement int a = str[0] - '0';:
Here both str[0] and 0 will be promoted to int. And the final result that is used to initialize variable a on the left hand side will be the result of subtraction of those two promoted int values on the right hand side. Moreover, the result is guaranteed to be the integer 1.
Similarly, for statement int b = str[1] - '0';:
Here both str[1] and 0 will be promoted to int. And the final result that is used to initialize variable b on the left hand side will be the result of subtraction of those two promoted int values on the right hand side. Moreover, the result is guaranteed to be the integer 2.
And similarly for variable c.

It seems to be converting strings' characters to its numeric values. For instance, if you define "char c = '0';", you had indeed stored the ASCII code (or equivalent string encoding) of the char '0' in variable c, not the value zero itself. So to get the actual numeric value out of the ASCII code, you have to subtract by the ASCII code from the char '0'.
Remember that strings are a sequence of numeric values, i.e., integers representing characters, using the ASCII Table or equivalent, depending on the string encoding being used (Unicode, etc...).
Please note the actual characters' numeric values will depending on the actual encoding being used. The most known and basic Encoding is probably ASCII, which does not support languages other than the original english. For international purposes, the most common nowadays is UNICODE UTF-8, which uses basically the same codes used by ASCII for plain English usual characters, but other more complicated encodings exist.
And, as correctly noted by Anoop Rana in the other answer to this question, the C++ standard guarantees the numeric values will be in a sequence in any encoding. So, by using this technique, you avoid magic numbers that would make your code work just with specific encodings.
Here goes a didactic code that may help:
#include <iostream>
#include <string>
using namespace std;
int main()
{
const string str = "5";
cout << "char: " << str << endl;
cout << "ASCII char's value: " << (int)str[0] << endl;
cout << "ASCII char's value of the character '0' is: " << ((int)'0') << endl;
cout << "Value represented by the ASCII code " << str[0] <<
" is the binary value " << (int)str[0] << "-" << ((int)'0') <<
"=" << (str[0] - '0') << endl;
return 0;
}
The output is:
char: 5
ASCII char's value: 53
ASCII char's value of the character '0' is: 48
Value represented by the ASCII code 5 is the binary value 53-48=5
The ASCII table code can be consulted here:
https://www.asciitable.com/
By the way, I think there may be a bug in your code, since parameter b is not being used. Maybe the second 'if' should be taking the value of b instead of a?

Related

Totally unrelated result when multiplying two integers?

#include <iostream>
using std::cout;
using std::endl;
int main(void) {
std::string fx = "6x^2+6x+4";
int part1 = fx[0] * fx[3];
cout << fx[0] << endl;
cout << fx[3] << endl;
cout << part1;
}
So I have this string and fx[0] and fx[3] are obviously integers: when I print them to the console they print out just fine; however, part1 (their multiplication) equals some totally unrelated number? Can anyone help?
Here is the output:
6
2
2700
Your fx[0] and fx[3] variables are of type char (which is an integer type in C++). However, the actual values in those two elements of your fx string will be representations of the digits, 6 and 2, not the numerical values of those digits.
Very often, those representations will be ASCII codes (but that's not required); however, what is required is that the representations of the digits 0 thru 9 have contiguous, sequential values. Thus, by subtracting the value of the digit, 0, we can convert to their numerical representations.
In your case, the following line will do the conversion:
int part1 = (fx[0]-'0') * (fx[3]-'0');
The reason why you see the correct values when printing fx[0] and fx[3] is because the version of the cout << operator that takes a char argument is designed to print the represented character (not its 'ASCII' code); however, the cout << operator for an int type (like your part1) will print the actual value represented internally. (Try changing one of your lines to cout << (int)fx[0] << endl; to see the difference.)
P.S. Don't forget the #include <string> header – some implementations do that implicity inside the <iostream> header, but don't rely on that!
well, first of all, string::operator[] returns a char... then, a char can be casted to an int, and the cast works checking the ID in the ASCII table (in your case)
In ASCII, the ID of "6" and "2" are respectively 54 and 52 (you can check it here for example)... so your program is taking the two char, casting them to int, and multiplying them (54 * 50 = 2700)
If you need to interpret those as the integer value they represent, you can check this answer:
int val = '6' - '0'; // val == 6
Characters are values representing glyphs from some representation, usually the ASCII table. The numeric value of a character is not the same as the glyph that is printed on the screen. To convert a numeric-looking char to an actual "0-based" numeric value, subtract '0' from your char value.
(fx[3]-'0']) will be the numeric value of character represented at position 3.
You are multiplying character types. so the characters '6' and '2' will converted to its integer values 54 and 50 respectively then multiplication is applied. This works based on C++ type conversion rule. Then you will get 2,700. Try the modified sample code
#include <iostream>
using std::cout;
using std::endl;
int main(void) {
std::string fx = "6x^2+6x+4";
int part1 = fx[0] * fx[3];
cout << fx[0] << endl;
cout << fx[3] << endl;
cout << part1;
cout << std::endl;
cout << (int)fx[0] << " " << (int)fx[3] << std::endl;
}
And the results
6
2
2700
54 50

Joining two characters in c++

My requirement is to join two characters. For example
int main()
{
char c1 ='0';
char c2 ='4';
char c3 = c1+c2;
cout<< c3;
}
The value which I am expecting is 04. But what I am getting is d.
I know that char is single byte. My requirement is that in the single Byte of C3 is possible to merge/join/concat the c1,c2 and store the value as 04
A char is not a string. So you can first convert the first char to a string and than add the next ones like:
int main()
{
char c1 ='0';
char c2 ='4';
auto c3 = std::string(1,c1)+c2;
std::cout<< c3;
}
What is "magic" std::string(1,c1):
It uses the std::string constructor of the form: std::string::string (size_t n, char c);. So it "fills" the string with one single character of your given c1 which is the 0.
If you add chars you get the result of adding the numeric value of it which is:
int main() {
std::cout << (int)c1 << std::endl;
std::cout << (int)c2 << std::endl;
std::cout << (int)c1+c2 << std::endl;
std::cout << char(c1+c2) << std::endl;
}
The numeric value as int from 0 is 48, from 4 it is 52. Add both you get 100. And 100 is a d in ascii coding.
What you want is called a string of characters. There are many ways to create that in C++. One way you can do it is by using the std::string class from the Standard Library:
char c1 = '0';
char c2 = '4';
std::string s; // an empty string
s += c1; // append the first character
s += c2; // append the second character
cout << s; // print all the characters out
A char is no more than an integral type that's used by your C++ runtime to display things that humans can read.
So c1 + c2 is a instruction to add two numbers, and is an int type due to the rules of type conversions. If that's too big to fit into a char, then the assignment to c3 would have implementation-defined results.
If you want concatenation, then
std::cout << ""s + c1 + c2;
is becoming, from C++11's user defined literals, the idiomatic way of doing this. Note the suffixed s.
Each char in C (and C++) has the length of one byte. What you are doing is adding the actual byte values:
'0' = 0x30
'4' = 0x34
-> '0' + '4' = 0x30 + 0x34 = 0x64 = 'd'
If you want to concatenate those two you will need an array:
int main()
{
char c1 ='0';
char c2 ='4';
char c3[3] = {c1,c2,0}; // 0 at the end to terminate the string
cout<< c3;
return 0;
}
Note that doing those things with chars is C but not C++. In C++ you would use a string, just as Klaus did in his answer.
Basics first
In C++ and C, a string ends with '\0' which is called null character.
Presence of this null character at the end differentiates between a string and char array. Otherwise, both are contigous memory location.
While calculating string.length() not counting the null character at the end is taken care.
Joining/Concatenating two characters
If you join two character using + operator, then handling the null character in both strings end will be taken care.
But if you join two char with + operator and wish to see it as an string, it will not happen, because it has no null character at the end.
See the example below:
char c1 = 'a';
char c2 = 'b';
string str1 = c1 + c2;
cout << str1; // print some garbled character, as it's not valid string.
string str2; // null initialization
str2 = str2 + c1 + c2;
cout << str2; // prints ab correctly.
string s1 = "Hello";
string s2 = "World";
string str3 = s1 + s2;
cout << str3; //prints Hello World correctly.
string str4 = s1 + c1;
cout << str4; //prints Hello a correctly.
What you named "joining" is actually arithmetics on char types, which implicitly promotes them to int. The equivalent integer value for a character is defined by the ASCII table ('0' is 48, '4' is 52, hence 48 + 52 = 100, which finally is 'd'). You want to use std::string when concatenating textual variables via the + operator.
You can do somthing like that:
#include <vector>
#include <iostream>
using namespace std;
int main()
{
char a = '0';
char b = '4';
vector<char> c;
c.push_back(a);
c.push_back(b);
cout << c.data() << endl;
return 0;
}
Simple addition is not suitable to "combine" two characters, you won't ever be able to determine from 22 if it has been composed of 10 and 12, 11 and 11, 7 and 15 or any other combination; additionally, if order is relevant, you won't ever know if it has been 10 and 12 or 12 and 10...
Now you can combine your values in an array or std::string (if representing arbitrary 8-bit-data, you might even prefer std::array or std::vector). Another variant is doing some nice math:
combined = x * SomeFactorLargerThanAnyPossibleChar + y;
Now you can get your two values back via division and modulo calculation.
Assuming you want to encode ASCII only, 128 is sufficient; considering maximum values, you get: 127*128+127 == 127*129 == 2^14 - 1. You might see the problem with yourself, though: Results might need up to 14 bit, so your results won't fit into a simple char any more (at least on typical modern hardware, where char normally has eight bits only – there are systems around, though, with char having 16 bits...).
So you need a bigger data type for:
uint16_t combined = x * 128U + y;
//^^
Side note: if you use 256 instead, each of x and y will be placed into separate bytes of the two of uint16_t. On the other hand, if you use uint64_t and 127 as factor, you can combine up to 9 ASCII characters in one single data type. In any case, you should always use powers of two so your multiplications and divisions can be implemented as bitshifts and the modulo calculations as simple AND-operation with some appropriate mask.
Care has to be taken if you use non-ASCII characters as well: char might be signed, so to prevent unwanted effects resulting from sign extension when values being promoted to int, you need to yet apply a cast:
uint16_t combined = static_cast<uint8_t>(x) * 128U + static_cast<uint8_t>(y);
Since a basic char doesn't have operator+ to concatenate itself with another char,
What you need is a representation of a string literal using std::string as suggested by others
or in c++17, you can use string_view,
char array[2] = {'0', '4'};
std::string_view array_v(array, std::size(array));
std::cout << array_v; // prints 04
https://github.com/bite-rrjo/STG-char-v2/blob/main/stg.h
without external libraries it would be like this
#include "iostream"
#include "lib-cc/stg.h"
using namespace std;
int main(){
// sum two char
char* c1 = "0";
char* c2 = "4";
stg _stg;
_stg = c1;
_stg += c2;
cout << _stg() << endl;
// print '04'
}

Accessing array by char in C++

Usually, I access an array in C++ by the syntax foo[2], where 2 is the index of an array.
In the below code. I didn't understand how this code is giving output and access this array by index 'b', 'c'. I am confused it is array index or something else.
int count[256] = {0};
count['b'] = 2;
cout << count['b'] << endl; //output 2
cout << count['c'] << endl; //output 0
Output
2
0
Remember that in c++ characters are represented as numbers. Take a look at this ascii table. http://www.asciitable.com
According to this the character 'b' is represented 98 and 'c' as 99. Therefore what your program is really saying is...
int count[256] = {0};
count[98] = 2;
cout << count[98] << endl; //output 2
cout << count[99] << endl; //output 0
Also incase you don't know saying an array = {0} means zero initialize every value so that is why count['c'] = 0.
In C/C++ there is not 8 bit / 1 byte integer. We simply use the char type to represent a single (signed or unsigned) byte and you can even put signed and unsigned infront of the char type. Char really is just another int type which we happen to use to express characters. You can also do the following.
char b = 98;
char c = 99;
char diff = c - b; //diff is now 1
Type char is actually an integral type. Every char value represented by a character literal has an underlying integral value it corresponds to in a given code page, which is probably an ASCII table. When you do:
count['b'] = 2;
you actually do:
count[98] = 2;
as character 'b' corresponds to an integral value of 98, character 'c' corresponds to an integral value of 99 and so on. To illustrate, the following statement:
char c = 'b';
is equivalent of:
char c = 98;
Here c has the same underlying value, it's the representation that differs.
Because characters are always represented by integers in the computer, it can be used as array indices.
You can verify by this:
char ch = 'b';
count[ch] = 2;
int i = ch;
cout << i << endl;
cout << count[i] << endl;
Usually the output is 98 2, but the first number may vary depending on the encoding of your environment.

C++. Why std::cout << char + int prints int value?

Let's say, we have:
char x = 'a';
int y = 1;
So, if you run:
std::cout << x + y;
It prints 98 instead of 'b'. As i see from here
<<operator has only int parameter implementation.
From now on i have 2 questions:
After char + int operation what type is returned?
Why there is no char parameter implementation, but std::cout << x still works as expected and prints char value?
Thanks to Fefux, Bo Persson and Matti Virkkunen answers are:
From CPP Reference: Implicit conversions:
arithmetic operators do not accept types smaller than int as
arguments, and integral promotions are automatically applied after
lvalue-to-rvalue conversion, if applicable.
So return type of x + y is int.
std::cout has a operator<<(char) as a non-member.
As you probably know, C++ is backward compatible with C.
Both C & C++ treat chars like ints.
You may consider this a flaw of the language, but on the contrary, this is very handy.
Suppose you want to convert a capital letter to the corresponding small letter. Since any capital letter has an ASCII code 32 below the corresponding small letter, this is as simple as this:
char c = 'A';
std::cout << (char) (c + 32); // output: 'a'
Inversely you can convert from small letter to capital letter:
char c = 'a';
std::cout << (char) (c - 32); // output: 'A'

Why does my string get empty values appended to it when subtracting characters?

I am attempting to solve a problem from topcoder.com and it's driving me crazy. I am learning C++ after a long break from C and am having trouble with strings.
The purpose of the program is to decode a string of 0s and 1s that has gone through an encryption algorithm that consists of adding each adjacent digit to the digit in question.
So 010111 becomes 112232 (LSB and MSB are considered to have zeros next to them). Below is my algorithm to decode the string:
#include <string>
#include <vector>
#include <iostream>
using namespace std;
class BinaryCode {
public:
vector<string> decode(string message);
};
vector<string> BinaryCode::decode(string message) {
vector<string> decoded(2);
int i;
string myTempString;
myTempString.append("0");
myTempString.append(1,message[0] - myTempString[0]);
for(i=2; i<message.size(); i++) {
myTempString.append(1,message[i-1] - myTempString[i-1] - myTempString[i-2]);
}
decoded[0] = myTempString;
myTempString = "";
myTempString.append("1");
myTempString.append(1,message[0] - myTempString[0]);
for(i=2; i<message.size(); i++) {
myTempString.append(1, message[i-1] - myTempString[i-1] - myTempString[i-2]);
}
decoded[1] = myTempString;
return decoded;
}
int main () {
string message("123210122");
BinaryCode *code = new BinaryCode;
vector<string> result = code->decode(message);
cout << "Decoded strings are "+result[0]+" and "+result[1];
getchar();
return 0;
}
The output is nonsense:
Decoded strings are 01
This is just a guess, since you don't show what output you're getting, but it looks like you're doing math on the character values and ending up with characters in the control range. For example, '1' - '0' is not '1' (character 49), it is 1, or Control-A. This is not printable and will typically be invisible in the output. Similarly, '1' + '2' is 49 + 50, or 99, which is 'c'. C++ is not going to magically convert these characters to integers for you. Hopefully this will give you the information you need to fix your code.
A character is an 8-bit integral type. It has the special property that, when printed, it will appear as the character that matches the ASCII value that it contains.
For example:
int valueAsInt = 65;
char valueAsChar = valueAsInt;
std::cout << valueAsChar << "\n";
valueAsInt = 'A';
std::cout << valueAsInt << "\n";
A
65
Take the value of the character literal '0'. This corresponds to the ASCII value 48. '1' is 49, etc.
If you subtract 48 from 49, you get 1. But that's not what you're looking for.
The ASCII value 1 corresponds to a non-printable character, called "start of heading". It was once used on old printers as a sort of markup. It would not print, but it would modify how further characters are printed.
When you subtract one numeric character from another, you get a delta, not a printable character. To turn this delta back into a printable character, you have to add it to a base character:
char value = '5' - '3';
value += '0';
std::cout << "5 - 3 = " << value << "\n";
5 - 3 = 2
So, your code such as message[0] - myTempString[0] must be changed to message[0] - myTempString[0] + '0' in order to work the way you intend it to.