I have an assignment which requires me to do the following,
Character is the superclass of Digit and Object is a superclass of Character.
Overload the operator + for the class Character, so that it can add two objects of type Character.
Override the operator + in the Digit class, so that it adds the numeric value of two digits and delivers the digit that we get if we finally apply “modulo 10”.
(Example ‘5’ + ‘6’ = ‘1’ // 5 + 6 = 11 % 10 = 1)
I have tried to code them out and have different solutions to it. I have made comments in my code and hope someone can answer my questions in the comments.
class Character : public Object {
protected:
char ch;
char getChar() {
return this->ch;
}
char setChar(char in) {
this->ch = in;
}
public:
//Why must I put Character&? What is the purpose of &?
Character operator+(const Character& in) {
Character temp;
temp.ch = this->ch + in.ch;
return temp;
}
};
class Digit : public Character {
public:
//Can i use the commented code instead?
/*
int a, b, c;
Digit operator+(Digit& in){
Digit temp;
temp.c = (in.a + in.b) % 10;
return temp;
}
*/
Digit operator+(const Digit& in) {
Digit tmp;
//Can some one explain what is this?
tmp.ch = (((this->ch - '0') + (in.ch - '0')) % 10) + '0';
return tmp;
}
};
//Why must I put Character&? What is the purpose of &?
& - reference. operator+ overloading works on two arguments, first one is passed implicitly, while the second one is passed by reference
//Can i use the commented code instead?
/*
int a, b, c;
Digit operator+(Digit& in){
Digit temp;
temp.c = (in.a + in.b) % 10;
return temp;
}
*/
you cannot use this code. you need to pass by 'const', which guarantee's immutability of second argument
//Can some one explain what is this?
tmp.ch = (((this->ch - '0') + (in.ch - '0')) % 10) + '0';
takes an ascii representation of digit, extracts it's numeric value, adds the numeric value and converts back to ascii representation of sum.
Why must I put Character&? What is the purpose of &?
It means the parameter is taken by reference/pointer and the object is not copied.
Can i use the commented code instead?
This code uses uninitialized variables, so it will not work.
//Can some one explain what is this?
ch - '0' is a well known hack to get the value of the ascii representation of a number
% 10:
if the result exceeds 10, substract 10 (modulo operator)
'+ '0':
convert to ascii representation
//Why must I put Character&? What is the purpose of &?
This causes the character to be passed in by reference, a requirement of the operator overloading. Read up on passing by value and passing by reference.
tmp.ch = (((this->ch - '0') + (in.ch - '0')) % 10) + '0';
When confused by a line try to break it down. I assume you can follow the assignment at the start of the line so let's look at the expression following the equals:
(((this->ch - '0')
Read the ASCII value for the char from this. Subtract from that the ASCII value for '0'. This works because ascii has ascending values. See http://www.asciitable.com/ and look for the numbers in the table.
This gives you an integer from 0->9 corresponding to the incoming ASCII character.
+ (in.ch - '0'))
This uses the same trick to extract the decimal value from the incoming value.
% 10)
Adding two numbers from 0 to 9 can easily give you a number >9, which cannot be represented as a single ASCII character. This is the remainder operator and gets rid of everything except the first digit of the answer, i.e. 0->9 is all that remains.
+ '0';
Finally it adds '0' back onto the resulting integer to convert it back into ASCII.
Related
I am asking about the job of minus and plus notation on string , in this situation specifically :
Solver(string s) {
for (unsigned int i = 0; i < s.length(); i++) {
grid[i] = (int) (s[i] - '0'); // the minus here will remove 0's of string or not ?
}
}
int main() {
Solver ss(
(string) "850002400" + // the plus here will combine all strings together like Java or not ?
(string) "720000009" +
(string) "004000000" +
(string) "000107002" +
(string) "305000900" +
(string) "040000000" +
(string) "000080070" +
(string) "017000000" +
(string) "000036040"
);
}
operator+ for string concatenates them – as you discovered already. But there's no operator- for strings!
Have a close look, you are not subtracting from the string (s - '0'), but from the character s[i]. This won't remove the character from the string, but instead calculate a new value based on the character's value minus the value of zero character (which has a value of 48, in ASCII and compatible, at least – not the value null!). As digits are guaranteed to be contiguous by C++ standard (just like in C as well), you can reliably calculate decimal digits from characters that way.
This works for bases smaller than 10, too, but not larger ones, as next characters used for representation don't follow the decimal digits directly (and you might have to distinguish upper and lower case letters).
Side note: You don't need the cast to int: as type char is smaller in size than int, both operands will be promoted to int implicitly, so actually the calculation is done in int anyway and the result remains int...
string - C++ Reference
http://www.cplusplus.com/reference/string/string/
As is said in link above, the operator+ means "Concatenate strings".
If you want to CLIP the string, you can use the s.substr() function.
grid[i] = (int) (s[i] - '0')
the the minus in code means transform the 'char' to 'int'. For example,
string s="425";
char c = s[0]; //c='4';
int value = c-'0'; //value=4 it is a number
It is not the function of string, just a utilization of ASCII.
The function stoi(s[i]) can realize the same thing.
Subtracting '0' from any character of digit will return the integer value of that digit.
char seven = '7';
int value = (int)(seven - '0');
cout<<value<<endl;
Output:
7
In your example - was used to convert a character grid(1D) to integer grid(1D).
On the other hand, + sign between two or more string type data represent concatenation of string.
string s = "abc" + "def";
cout<<s<<endl;
Output:
abcdef
I am working on a little c++ project that receives a char array input from the user. Depending on the value, I am converting it to an int. I understand there are better ways of doing this but I thought I'd try to convert it through ASCII to allow other uses later on. My current code for the conversion is:-
int ctoi(char *item){
int ascii, num = 0;
ascii = static_cast<int>(item[0]);
if(ascii >= 49 && ascii <=57){
num = ascii - 48;
}else{
return 0;
}
ascii = static_cast<int>(item[1]);
if(ascii >= 48 && ascii <=57){
num = num * 10;
num = num + (ascii - 48);
}else{
return 0;
}
return num;
}
It receives a input into the char array item[2] in the main function and passes this to the conversion function above. The function converts the first char to ASCII then the decimal value of the ASCII to num if its between 1 and 9, then it converts the second char to ASCII, if it is between 0 and 9, it times the value in num by 10 (move along one unit) and adds the decimal value of the ASCII value. At any point it may fail, it returns the value 0 instead.
When I cout the function after receiving a value and run this code in a console, it works fine for single digit numbers (1 - 9), however when I try to use a double digit number, it repeats digits such as for 23, it will output 2233.
Thanks for any help.
I wonder how you're reading the input into a two-character array. Note that it's customary to terminate such strings with a null character, which leaves just one for the actual input. In order to read a string in C++, use this code:
std::string s;
std::cin >> s;
Alternatively, for a whole line, use this:
std::string line;
getline(std::cin, line);
In any case, these are basics explained in any C++ text. Go and read one, it's inevitable!
I have a char a[] of hexadecimal characters like this:
"315c4eeaa8b5f8aaf9174145bf43e1784b8fa00dc71d885a804e5ee9fa40b16349c146fb778cdf2d3aff021dfff5b403b510d0d0455468aeb98622b137dae857553ccd8883a7bc37520e06e515d22c954eba5025b8cc57ee59418ce7dc6bc41556bdb36bbca3e8774301fbcaa3b83b220809560987815f65286764703de0f3d524400a19b159610b11ef3e"
I want to convert it to letters corresponding to each hexadecimal number like this:
68656c6c6f = hello
and store it in char b[] and then do the reverse
I don't want a block of code please, I want explanation and what libraries was used and how to use it.
Thanks
Assuming you are talking about ASCII codes. Well, first step is to find the size of b. Assuming you have all characters by 2 hexadecimal digits (for example, a tab would be 09), then size of b is simply strlen(a) / 2 + 1.
That done, you need to go through letters of a, 2 by 2, convert them to their integer value and store it as a string. Written as a formula you have:
b[i] = (to_digit(a[2*i]) << 4) + to_digit(a[2*i+1]))
where to_digit(x) converts '0'-'9' to 0-9 and 'a'-'z' or 'A'-'Z' to 10-15.
Note that if characters below 0x10 are shown with only one character (the only one I can think of is tab, then instead of using 2*i as index to a, you should keep a next_index in your loop which is either added by 2, if a[next_index] < '8' or added by 1 otherwise. In the later case, b[i] = to_digit(a[next_index]).
The reverse of this operation is very similar. Each character b[i] is written as:
a[2*i] = to_char(b[i] >> 4)
a[2*i+1] = to_char(b[i] & 0xf)
where to_char is the opposite of to_digit.
Converting the hexadecimal string to a character string can be done by using std::substr to get the next two characters of the hex string, then using std::stoi to convert the substring to an integer. This can be casted to a character that is added to a std::string. The std::stoi function is C++11 only, and if you don't have it you can use e.g. std::strtol.
To do the opposite you loop over each character in the input string, cast it to an integer and put it in an std::ostringstream preceded by manipulators to have it presented as a two-digit, zero-prefixed hexadecimal number. Append to the output string.
Use std::string::c_str to get an old-style C char pointer if needed.
No external library, only using the C++ standard library.
Forward:
Read two hex chars from input.
Convert to int (0..255). (hint: sscanf is one way)
Append int to output char array
Repeat 1-3 until out of chars.
Null terminate the array
Reverse:
Read single char from array
Convert to 2 hexidecimal chars (hint: sprintf is one way).
Concat buffer from (2) to final output string buffer.
Repeat 1-3 until out of chars.
Almost forgot to mention. stdio.h and the regular C-runtime required only-assuming you're using sscanf and sprintf. You could alternatively create a a pair of conversion tables that would radically speed up the conversions.
Here's a simple piece of code to do the trick:
unsigned int hex_digit_value(char c)
{
if ('0' <= c && c <= '9') { return c - '0'; }
if ('a' <= c && c <= 'f') { return c + 10 - 'a'; }
if ('A' <= c && c <= 'F') { return c + 10 - 'A'; }
return -1;
}
std::string dehexify(std::string const & s)
{
std::string result(s.size() / 2);
for (std::size_t i = 0; i != s.size(); ++i)
{
result[i] = hex_digit_value(s[2 * i]) * 16
+ hex_digit_value(s[2 * i + 1]);
}
return result;
}
Usage:
char const a[] = "12AB";
std::string s = dehexify(a);
Notes:
A proper implementation would add checks that the input string length is even and that each digit is in fact a valid hex numeral.
Dehexifying has nothing to do with ASCII. It just turns any hexified sequence of nibbles into a sequence of bytes. I just use std::string as a convenient "container of bytes", which is exactly what it is.
There are dozens of answers on SO showing you how to go the other way; just search for "hexify".
Each hexadecimal digit corresponds to 4 bits, because 4 bits has 16 possible bit patterns (and there are 16 possible hex digits, each standing for a unique 4-bit pattern).
So, two hexadecimal digits correspond to 8 bits.
And on most computers nowadays (some Texas Instruments digital signal processors are an exception) a C++ char is 8 bits.
This means that each C++ char is represented by 2 hex digits.
So, simply read two hex digits at a time, convert to int using e.g. an istringstream, convert that to char, and append each char value to a std::string.
The other direction is just opposite, but with a twist.
Because char is signed on most systems, you need to convert to unsigned char before converting that value again to hex digits.
Conversion to and from hexadecimal can be done using hex, like e.g.
cout << hex << x;
cin >> hex >> x;
for a suitable definition of x, e.g. int x
This should work for string streams as well.
the operator int() function converts the string to an int
class mystring
{
private:
chat str[20];
public:
operator int() // i'm assuming this converts a string to an int
{
int i=0,l,ss=0,k=1;
l = strlen(str)-1;
while(l>=0)
{
ss=ss+(str[l]-48)*k;
l--;
k*=10;
}
return(ss);
}
}
int main()
{
mystring s2("123");
int i=int(s2);
cout << endl << "i= "<<i;
}
So what's the logic behind operator int() ? What's the 48 in there? Can someone explain to me the algorithm behind the conversion from string to int.
Yes this converts a string to an integer. 48 is the ASCII value for '0'. If you subtract 48 from an ASCII digit you'll get the value of the digit (ex: '0' - 48 = 0, '1' - 48 = 1, ..). For each digit, your code calculates the correct power of 10 by using k (ranges between 1...10^{ log of the number represented by the input string}).
It does indeed convert a string to an integer. The routine assumes that all characters are decimal digits (things like minus sign, space, or comma will mess it up).
It starts with the ones place and moves through the string. For each digit, it subtracts off the ASCII value of '0', and multiplies by the current place value.
This does indeed convert the string to an integer. If you look at an ascii table the numbers start at the value 48. Using this logic (and lets say the string "123") the while loop will do:
l=2
ss=0+(51-48)*1
so in this case ss = 3
next loop we get
l=1
ss=3+(50-48)*10
so ss = 23
next loop
l=0
ss=23+(49-48)*100
so ss= 123
The loop breaks and we return an integer of value 123.
Hope this helps!
I'm wondering what sort of algorithm could be used to take something like "4.72" into a float data type, equal to
float x = 4.72;
scanf, operator>> for istreams, and strtof would be the obvious choices.
There is also atof, but, like atoi, it lacks a way to tell you there was an error in the input, so it's generally best to avoid both.
For C++ you can use boost::lexical_cast:
std::string str( "4.72" );
float x = boost::lexical_cast< float >( str );
For C you can use sscanf:
char str[]= "4.72";
float x;
sscanf( str, "%f", &x );
For C++ This is the algorithm I use:
bool FromString(const string& str, double& number) {
std::istringstream i(str);
if (!(i >> number)) {
// Number conversion failed
return false;
}
return true;
}
I used atof() in the past for the conversion, but I found this problematic because if no valid conversion can be made, it will return (0.0). So, you would not know if it failed and returned zero, or if the string actually had "0" in it.
For C strtod() and C99 friends strtof() and strtold() (description on same link) already have that algorithm implemented.
If you are having problems writing your own, post your code and specific questions about it.
As you've asked for an algorithm, not a method, here is my explanation for a simple algorithm (and an implementation in C):
Initialize 4 integer variables, one for the value before dot, one for the after part, one for the power of the mantissa, one for the sign. Let's say, f, m, d, sign = 1.
First look for + or - sign at the beginning. If there are no sign characters or + sign then continue. If the first character is -, then sign = -1.
Then, read an integer value into f until a . or NULL character.
If you end up with a dot character, then start reading the mantissa part as in the previous step into m. But this time also multiply d by 10 with each digit.
In the end, return sign*(f + (float) m/d). The casting makes sure the division is done in floating-points and the type of the expression is float.
I guess, reading the code might be easier. So here is the code:
float atof(char *s)
{
int f, m, sign, d=1;
f = m = 0;
sign = (s[0] == '-') ? -1 : 1;
if (s[0] == '-' || s[0] == '+') s++;
for (; *s != '.' && *s; s++) {
f = (*s-'0') + f*10;
}
if (*s == '.')
for (++s; *s; s++) {
m = (*s-'0') + m*10;
d *= 10;
}
return sign*(f + (float)m/d);
}
You can use boost:lexical_cast
http://www.boost.org/doc/libs/1_44_0/libs/conversion/lexical_cast.htm
I assume you want an actual algorithm, not a library function that already does it. I don't have time to write and test actual code, but here is what I would do:
Initialize a float that will be used as an accumulator to 0.
Figure out where the decimal place is in the string, this will let you know what "column" each of the digits is (i.e. 100s, 10s, 1s, 1/10ths, etc).
Start at the beginning of the string.
Take that digit, convert to an int (trivially done by subtracting 0x30 from the ASCII value)
Multiply the value by the place column (for the first digit in your example, that would be 4 * 1 == 4, for the next digit 7 * 0.1 == 0.7).
Add the result to the accumulator
Repeat from step 4 for each remaining digit.
The accumulator now contains your result.
Due to the roundoff of converting between base 10 and base 2 in every iteration of this loop, the result you get from this algorithm may not be the closest possible binary representation to the original value. I don't really know of a good way to improve it though... perhaps someone else can chime in with that.
The atof() function can be helpful.
http://www.cplusplus.com/reference/clibrary/cstdlib/atof/
From cplusplus.com: "stringstream provides an interface to manipulate strings as if they were input/output streams."
You can initialize a stringstream with your string then read a float from the stringstream using operator>> just like you would with cin.
Here is an example:
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
int main() {
string s = "4.72";
stringstream sstrm(s);
float x;
sstrm >> x;
cout << x << endl;
}