C++ input operator overload ">>" - c++

I have a rational number class is made up of two integers: num, the nominator, and den, the denominator.
The following operator is supposed to read the rational number from a stream.
istream& operator >> (istream& Is, rational& r) {
char c; //Test char.
double n; //Could be either the numerator of the fraction or the antiperiod of the repeating decimal number.
Is >> n;
int i = 0;
for (; n*10-pow(10, i+1) < 1 && int(n) != 0; i++) {
n *= 10;
}
for (; int(n*10) % 10; i++) {
n *= 10;
}
n /= pow(10, i);
if (i == 0) {
r.num = n;
Is >> ws;
c = Is.peek();
if (c == '/') {
c = Is.get();
Is >> r.den;
} else {
r.den = 1;
}
r.normalize(); //This function normalizes the fraction.
} else {
Is >> ws;
c = Is.peek();
if (c == 'p' || c == 'P') {
int p; //Period of the repeating decimal number.
c = Is.get();
Is >> p;
vector<int> a = genFrac(n, p); //This function returns the fraction which express the decimal repeating number. It returns a "vector<int>" with the nominator at index 1 e denominator at index 0.
r.num = a[1];
r.den = a[0];
} else {
i = 0;
for (; n*10-pow(10, i+1) < 1 && int(n) != 0; i++) {
n *= 10;
}
for (; int(n*10) % 10 != 0; i++) {
n *= 10;
}
int pot10 = pow(10, i);
r.num = n;
r.den = pot10;
}
r.normalize();
}
return Is;
}
I wrote this code to implement the input of my "rational" class.
I modified it from the one written in my C++ book in order to make possible the input of decimal numbers, including repeating ones.
It should be able to handle these types of input:
9/8
9
9.87
1.p3 (= 1.3333333333)
But it doesn't work, not even the part I copied from the book.
Can anyone help me?

I think I'd write this somewhat differently1.
Unless you really need to do otherwise, I'd start by reading an entire "chunk" of input (i.e., all the characters up to the next white space), then sort out how that's supposed to represent a number, and call a separate function for each possible representation:
std::istream &operator>>(std::istream &is, rational &r) {
std::string temp;
Is >> temp;
if (temp.find('/') != std::string::npos)
r = cvt_fraction(temp, Is);
else if (temp.find_first_of("pP") != std::string::npos)
r = cvt_repeating(temp, Is);
else if (temp.find('.') != std::string::npos)
r = cvt_float(temp, Is);
else
r = cvt_int(temp, Is);
return Is;
}
I've passed the istream to each for two reasons: first, so if they find garbage in the input, they can set the stream's fail bit. Second, so if they really do need to read more input, they can (but I'd be a little surprised if that's ever really needed).
It seems to me that each of those conversion functions should be fairly trivial: if I'm starting from the fact that a string should be digits "/" digits or `digits "p" digits", doing a conversion is generally going to be pretty simple -- specifically, simple enough that I think just about anybody can probably glance at the code and sort out what each piece is supposed to do.
I honestly don't mean to be nasty, but if I was maintaining code, and ran across your operator>>, I would have one of two possible reactions: if it apparently had a bug, replace it immediately. Otherwise, put it on the "technical debt" list, and replace it as soon as possible. The simple fact is that as it stands right now, it takes a fair amount of study to even be sure what input formats are supposed to be supported, not to mention which part of the code handles each, or how the whole thing is supposed to work together to produce a meaningful result.

The issue mentioned in the comment (the p not appearing in the c=is.peek() statement) comes from the fact that the p is actually stored in ws (it is stored there in is >> ws).
The above code also contains no mention of ws, but I assume it is a char.

Related

Converting decimal to binary using exponents

I was asked to write code for converting a decimal to its binary form. I have tried several different ways but doesn't gives me the order i need. So i am currently stuck on how to proceed.
I have tried by normally finding the binary comparison but it gives me in the incorrect order, lets say the correct order is 1001100, i just get 0011001. and i have no way of changing the order. I am not allowed to use any other library other than iostream, cmath and string. I am now trying to simply find the conversion using the exponent 2^exponent.
This is what i currently have:
int num, exp,rem;
string biNum;
cout<<"Enter decimal number: "<<endl;
cin>>num;
for (exp = 0; pow(2, exp) < num; exp++) {
}
while (num > 0) {
rem = num % (int) pow(2, exp);
if (rem != 0) {
biNum = biNum + '1';
} else {
biNum = biNum + '0';
}
exp--;
}
cout<<biNum;
return 0;
}
I am currently receiving no result at all.
Here is an example that collects the bits in Least Significant Bit (LSB):
//...
while (num > 0)
{
const char bit = '0' + (num & 1);
biNum += bit;
num = num >> 1;
}
Explanation
The loop continues until the num variable is zero. There is no point in adding extra zeros unless you really want them.
The (num & 1) expression returns 1 if the bit is 1, or 0 if the bit is 0.
This is then added to the character 0 to produce either '0' or '1'.
The variable is declared as const since it won't be modified after declaration (definition).
The newly created character is appended to the bit string.
Finally, the num is right shifted by one bit (because that bit was already processed).
There are many other ways to collect the bits in Most Significant Bit (MSB) order. Those ways are left for the OP and the reader. :-)
Here you go. This outputs the bits in the right order:
#include <iostream>
#include <string>
int main ()
{
unsigned num;
std::string biNum;
std::cin >> num;
while (num)
{
char bit = (num & 1) + '0';
biNum.insert (biNum.cbegin (), bit);
num >>= 1;
}
std::cout << biNum;
return 0;
}
Live demo
You can use a recursive function to print the result in reverse order, avoiding using a container/array, like so:
void to_binary(int num) {
int rem = num % 2;
num = (num - rem) / 2;
if (num < 2){
std::cout << rem << num;
return;
}
to_binary(num);
std::cout << rem;
}
int main()
{
to_binary(100);
}

how to calculate polynomial (x^2^2^2^2+x^2^2^2)

I want to calculate (x^2^2^2^2+x^2^2^2) result should be [x^256+x^16]..but i am unable to do this completely..i also have written a code which is working for first half(before '+') but in other half it fails to do it...
#include<iostream>
#include<string>
#include <algorithm>
#include<sstream>
using namespace std;
int main()
{
string a;
cin >> a;
string s1 = "^";
string::size_type foud;
foud = a.find(s1);
int i = foud;
int flag = 0;
i++;
while (foud != std::string::npos)
{
flag = 0;
cout << i <<"I"<< endl;
while (flag != 1 && i < a.length())
{
if (a[i] == '(' || a[i] == '+' || a[i] == '-' || a[i] == ')')
{
flag++;
cout << "terminator" << endl;
}
else if (a[i] == '^')
{
/*int j = (int)(a[i - 1]);
j = j - 48;
int k = (int)(a[i + 1]);
k = k - 48;
i = k + 1;
int power =0;
power = pow(j, k);
;*/
int j = i;
int k = i;
k--;
j++;
string bcknumber;
while (a[k] != '^' && a[k] != '(' && a[k] != '+' && a[k] != '-' && a[k] != ')')
{
bcknumber = bcknumber + a[k];
k--;
}
cout << bcknumber << endl;
reverse(bcknumber.begin(), bcknumber.end());
cout << bcknumber << endl;
int BK;
BK = stoi(bcknumber);
int FD;
string frdnum;
while (a[j] != '^'&&a[j] != '\0' && a[j] != '(' && a[j] != '+' && a[j] != '-' && a[j] != ')')
{
frdnum = frdnum + a[j];
j++;
}
FD = stoi(frdnum);
int resil = pow(BK, FD);
frdnum.clear();
stringstream s;
string res;
s << resil;
res = s.str();
if (i == 15)
{
a.replace(14, 15, res);
}
else
{
a.replace(i - bcknumber.length(), i + frdnum.length(), res);
}
i--;
bcknumber.clear();
}
else
i++;
}
foud = a.find("^", foud + 1);
i = foud;
i++;
}
cout << a << endl;
system("pause");
}
This is not a trivial problem. You want to build an infix calculator (a + b). A prefix calculator (+ a b) or a postfix calculator (a b +) are simpler, since there are no ambiguities at all. An infix calculator can have a lot of them, depending on the degree of freedom you want the user to have.
In the problem you're exposing, one is tempted to say: well, if there is an operator next to the second operand, then I have to accumulate the last result and operate with that and the next operation. However, there are problems like precedence which will not be deal with with that approach.
I would start creating a prefix calculator. It is a lot easier:
calculate():
opr = match operator
op1 = match operand
if op1 is operator:
back
op1 = calculate
op2 = match operand
if op2 is operator:
back
op2 = calculate
return calc(opr, op1, op2)
Once you have mastered that, then there is the possibility to start with an infix calculator.
One thing to do in the last algorithm would be to change it to avoid recursion, for example.
This is a good exercise, enjoy it. Hope this helps.
This smells like homework/assignment so I will not provide code...
As I see it you want just string parser to string replacing the power part. I am assuming You still do not understand the power math or are wrongly writing/interpreting representation of the string. For example:
x^2^2^2^2 =
(((x^2)^2)^2)^2 =
(((x.x)^2)^2)^2 =
((x.x).(x.x))^2)^2 =
((x.x.x.x))^2)^2 =
((x.x.x.x).(x.x.x.x))^2 =
(x.x.x.x.x.x.x.x)^2 =
(x.x.x.x.x.x.x.x).(x.x.x.x.x.x.x.x) =
(x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x) =
x^16
And not yours x^256. You can not add parenteses where you want they must be placed according to order of math operations otherwise the resulting equation will not match the input string !!!. In case you got defined different parse rules for your parser then in standard math then you need to define them in the Question.
Now how to approach this:
read string
I would start with constant hard-coded string instead of typing it all the time while programing/debugin over and over (as many students do ... I saw few times people typing 5x5 matrix on each build :) ... which is insane)
When the program works only then use the cin reading... as you already do
detect which part of the string is power exponent
exponent=1
Search the string for first ^ and remember the start position i0 if not found goto #4.
Now depending on what follows:
If number multiply exponent by it.
If ^ skip it and goto to #2
if neither stop
Of coarse if you should support parentes then it will be much much more complicated and you need to decode the whole thing which is not trivial which you should also mention in the Question.
replace original exponent string with computed string (if computable)
so the computed string will be "^"<<exponent or "^"+exponent depends on what kind of string arithmetics you using ....
output string
with cout or whatever as you already do

Extraction operator causing my program to exit?

I'm a usual lurker but this is my first post! I understand you guys like detail so I will do my best. I will appreciate whatever input anyone has.
I am working on an overloading the extraction operator for an object with a dynamic array of digits. The console input will have leading white space, then an int, then anything after. I need to ignore white space, extract the int, and then leave the rest alone. Easy right?
Here is an example of code I found online:
istream & operator >> (istream &m, MyInt & p)
{
int x = 0;
p.currentLength = 0;
while ((m.peek() == '\n') || (m.peek() == '\0') ||
(m.peek() == '\t') || (m.peek() == ' '))
{
m.get();
}
while ((m.peek() >= '0') && (m.peek() <= '9'))
{
if (p.currentLength >= p.maxSize)
{
p.grow();
}
m >> p.theNumber[x];
x++;
p.currentLength++;
}
m.get();
// reverse the order (i.e. - 123 to 321)
char * temp = new char[p.maxSize];
for (int y = 0; y < p.currentLength; y++)
{
temp[y] = p.theNumber[p.currentLength - 1 - y];
}
delete [] p.theNumber;
p.theNumber = temp;
return m;
}
Now, I understand this method may work, however to me, that seems like an extremmeelly inefficient method. For a trillion digit number, Grow() would reallocate the array a trillion times! Perhaps this is not as bad as I think it is?
My current method has been using seekg() and peek() and get(). Like so:
istream& operator >> (istream& is, MyInt& z)
{
int i = 0, j = 0;
// check if next char is white
while (is.peek() == 38)
{
j++;
is.seekg(j); // skip if white
}
while (isdigit(is.peek()))
{
i++;
is.seekg(j + i);
if (!is.peek())
{
is.clear();
break;
}
}
is.seekg(j);
z.length = i;
z.digits = new int[i + 1];
for (i = 0; i < z.length; i++)
{
z.digits[i] = C2I(is.get());
}
return is;
}
Also, here is my main:
int main()
{
MyInt B;
cout << "\n\nChange B to what num? ---> ";
cin >> B;
cout << "B is now: " << B;
char c;
cout << "\n\n\n\n\nEnter char to exit : ";
cin >> c;
return 0;
}
For the life of me I can not find what is causing my program to exit. The last output seems to say, 'B is now: -1'
I believe the this means the << B failed. I have B initialized to 0 currently, and the rest of my code has presented no other issues. It's private member data only include the pointer and a length (num of digits). Also C2I() is a function that converts '0' through '9' to 0 through 9.
A big issue for me is I am fairly new to parsing, so I don't have very eloquent ways to test this, or other ideas.
Again I appreciate everything you guys do. I have already learned a great deal from browsing here!

Find the reverse of a number (ex : 2500 reverse 0025) without the help of string or character

Is there any technique for finding the reverse when there are zeros at the end.
While following the algorithm of %10 technique the result is 52. And the 0's are missing.
I have got the reverse by just printing the reminders (with 0's). But I am not satisfied as I wish to display the answer as the value in a variable.
Kindly tell me is there any technique to store a value 005 to a variable and also to display 005 (please don't use String or Character or array).
Numbers are stored as binary 0 and 1 and so they always have leading 0's which are chopped off. e.g. a 64-bit integer has 64-bit bits, always and when it is printed these leading 0's are dropped.
You need to know how many leading zeros you want to keep and only use that many when you print. i.e. you can record how many leading zeros there were in a normal number without encoding it e.g. by adding a 1 at the start. i.e. 0052 is recorded as 10052 and you skip the first digit when you print.
If you need to store a single value you can do the following. I use do/while so that 0 becomes 10 and is printed as 0. The number 0 is the one place where not all leading zeros are dropped (as it would be empty otherwise)
This appears to be the solution you want and it should be basically the same in C or C++
static long reverse(long num) {
long rev = 1; // the 1 marks the start of the number.
do {
rev = rev * 10 + num % 10;
num /= 10;
} while(num != 0);
return rev;
}
// make the reversed number printable.
static String toStringReversed(long num) {
return Long.toString(num).substring(1);
}
long l = reverse(2500); // l = 10052
An alternative is to print the digits as you go and thus not need to store it.
e.g.
static void printReverse(long l) {
do {
System.out.print(l % 10);
l /= 10;
} while(l != 0);
}
or you can have the input record the number of digits.
static void printReverse(long l, int digits) {
for(int i = 0; i < digits; i++) {
System.out.print(l % 10);
l /= 10;
}
}
// prints leading zero backwards as well
printReverse(2500, 6); // original number is 002500
prints
005200
You cannot represent an integer with leading zeros as a single integer variable, that information is simply not part of the way bits are allocated in an integer. You must use something larger, i.e. a string or an array of individual (small integer) digits.
You can't store them in a simple integer variable because in binary format
00101 is same as 000101 which is same as 101 which only results into 5. The convertion between a decimal number and binary numbers don't consider leading zeroes so it is not possible to store leading zeroes with the same integer variable.
You can print it but you can't store the leading zeroes unless you use array of ints...
int num = 500;
while(num > 0)
{
System.out.print(num%10);
num = num/10;
}
Alternatively you can store the count of leading zeroes as a separate entity and combine them when ever you need to use. As shown below.
int num = 12030;
boolean leading=true;
int leadingCounter = 0;
int rev = 0;
while(num > 0)
{
int r = num%10;
if(r == 0 && leading == true)
leadingCounter++;
else
leading = false;
rev = rev*10 + r;
num = num/10;
}
for(int i = 1; i <= leadingCounter ; i++)
System.out.print("0");
System.out.println(rev);
I think the accepted answer is a good one, in that it both refutes the parts of the question that are wrong and also offers a solution that will work. However, the code there is all Java, and it doesn't expose the prettiest API. Here's a C++ version that based on the code from the accepted answer.
(Ha ha for all my talk, my answer didn't reverse the string! Best day ever!)
After going back to school and getting a degree, I came up with this answer: it has the makes the somewhat dubious claim of "not using strings" or converting any values to string. Can't avoid characters, of course, since we are printing the value in the end.
#include <ostream>
#include <iostream>
class ReverseLong {
public:
ReverseLong(long value) {
long num = value;
bool leading = true;
this->value = 0;
this->leading_zeros = 0;
while (num != 0) {
int digit = num % 10;
num = num / 10;
if (leading && digit == 0) {
this->leading_zeros += 1;
} else {
this->value = this->value * 10 + digit;
leading = false;
}
}
};
friend std::ostream & operator<<(std::ostream& out, ReverseLong const & r);
private:
long value;
int leading_zeros;
};
std::ostream & operator<<(std::ostream& out, ReverseLong const & r) {
for (int i =0; i < r.leading_zeros; i++) {
out << 0;
}
out << r.value;
return out;
};
int main () {
ReverseLong f = ReverseLong(2500); // also works with numbers like "0"!
std::cout << f << std::endl; / prints 0052
};

A cleaner way to convert a string to int after checking for hex prefix?

This little exercise is meant to get a string from the user that could be decimal, hexadecimal, or octal. 1st I need to identify which kind of number the string is. 2nd I need to convert that number to int and display the number in its proper format, eg:
cout <<(dec,hex,oct, etc)<< number;
Here's what I came up with. I'd like a simpler, cleaner way to write this.
string number = "";
cin >> number;
string prefix = "dec";
char zero = '0';
char hex_prefix = 'x';
string temp = "";
int value = 0;
for(int i =0; i<number.size();++i)
{
if(number[0] == zero)//must be octal or hex
{
if (number[0] == zero && number[1] == hex_prefix ) //is hex
{
prefix = "hex";
for(int i = 0; i < (number.size() - 2); ++i)
{
temp[i] = number[i+2];
}
value = atoi(temp.c_str());
}
//... code continues to deal with octal and decimal
You are checking number[0] twice, that's the first most obvious problem.
The inner if already checks both number[0] and number[1], I don't see the point of the outer one.
The outermost loop is also hard to understand, do you expect non-hex data before the number, or what? Your question could be clearer on how the expected input string looks.
I think the cleanest would be to ignore this, and push it into existing (library) code that can parse integers in any base. In C I would recommend strtoul(), you can of course use that in C++ too.
You have two inner loop with same value integer this could be a conflict problem in your code. I suggest you look at the isdigit and islower methods in the c++ library and take advantage of those methods to accomplish your task. isdigit & islower
Good Luck
This is prints the number after deleting the hex prefix, otherwise return 0:
#include<iostream>
#include<cmath>
#include<stdlib.h>
using namespace std;
int main(){
string number = "";
cin >> number;
string prefix = "dec";
char zero = '0';
char hex_prefix = 'x';
string temp = "";
int value = 0;
if (number.size()>=2 && number[0] == zero && number[1] == hex_prefix ) //is hex
{
prefix = "hex";
for(int i = 0; i < (number.size() - 2); ++i)
{
temp[i] = number[i+2];
}
value = atoi(temp.c_str());
}
cout<<value;
return 0;
}
This partial solution that I found is as clean as possible, but it doesn't report the format of the integer:
int string_to_int(std::string str)
{
std::istringstream stream;
stream.unsetf(std::ios_base::dec);
int result;
if (stream >> result)
return result;
else
throw std::runtime_error("blah");
}
...
cout << string_to_int("55") << '\n'; // prints 55
cout << string_to_int("0x37") << '\n'; // prints 55
The point here is stream.unsetf(std::ios_base::dec) - it unsets the "decimal" flag that is set by default. This format flag tells iostreams to expect a decimal integer. If it is not set, iostreams expect the integer in any base.