Okay so I'm trying to implement a calculator on C++ that can process numbers of any size, for which I made a class named "bignum", so I'm not restrained by C++ default variables. The >> operator is supposed to read my input, parse what's read into an infix notation and then solve it. To parse the string I'm using Shunting Yard's method.
I was able able to solve the Segmentation Fault issues and it runs perfectly but I noticed I'm having memory problems with Valgrind:
==765== HEAP SUMMARY:
==765== in use at exit: 2 bytes in 1 blocks
==765== total heap usage: 10 allocs, 9 frees, 74,880 bytes allocated
==765==
==765== 2 bytes in 1 blocks are definitely lost in loss record 1 of 1
==765== at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==765== by 0x10E5A8: bignum::operator=(bignum const&) (bignum.cc:544)
==765== by 0x110590: operator>>(std::istream&, bignum&) (bignum.cc:916)
==765== by 0x10BB50: main (main.cc:110)
==765==
==765== LEAK SUMMARY:
==765== definitely lost: 2 bytes in 1 blocks
==765== indirectly lost: 0 bytes in 0 blocks
==765== possibly lost: 0 bytes in 0 blocks
==765== still reachable: 0 bytes in 0 blocks
==765== suppressed: 0 bytes in 0 blocks
==765==
==765== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
The >> operator implementation that calls = operator:
// Input operator
istream& operator >> (istream &is, bignum &result)
{
// Using de Shunting Yard's method
stack<char> operations;
queue<string> output;
string input;
// Pass the input to a string
getline(is, input);
// In case my string is empty
if(input.empty())
return is;
// Parse the string
for(size_t i = 0; i < input.size(); i++)
{
if(isblank(input[i])){}
// If a number is identified
else if(isdigit(input[i]))
{
size_t pos = i++;
size_t len = 1;
while(isdigit(input[i]))
{
len++;
i++;
}
i--;
output.push(input.substr(pos, len));
}
// If there's a minus sign
else if(input[i] == '-')
{
size_t j = i;
while(j != 0 && isblank(input[--j])){}
// I've got a subtraction
if(isdigit(input[j]) || input[j] == ')')
{
if(!operations.empty())
{
while(operations.top() == '-' || operations.top() == '+' || operations.top() == '*' || operations.top() == '/')
output.push(string{operations.pull()});
}
operations.push(input[i]);
}
// I've got a negative sign
else
output.push(string{"s"});
}
else if(input[i] == '+')
{
size_t j = i;
while(j != 0 && isblank(input[--j])){}
// I've got an addition
if(isdigit(input[j]) || input[j] == ')')
{
if(!operations.empty())
{
while(operations.top() == '-' || operations.top() == '+' || operations.top() == '*' || operations.top() == '/')
output.push(string{operations.pull()});
}
operations.push(input[i]);
}
// If there's a positive sign I do nothing
}
else if(input[i] == '*' || input[i] == '/')
{
if(!operations.empty())
{
while(operations.top() == '*' || operations.top() == '/')
output.push(string{operations.pull()});
}
operations.push(input[i]);
}
// If there's an opening parenthesis
else if(input[i] == '(')
operations.push(input[i]);
// If there's a closing parenthesis
else if(input[i] == ')')
{
if(operations.empty())
{
cout << "Syntax Error" << endl;
return is;
}
while(!operations.empty() && operations.top() != '(')
output.push(string{operations.pull()});
if(!operations.empty())
operations.pull();
else
{
cout << "Syntax Error" << endl;
return is;
}
}
}
if(!operations.empty())
{
if(operations.top() == '(' && output.empty())
{
cout << "Syntax Error" << endl;
return is;
}
else
{
if(output.empty())
{
cout << "Syntax Error" << endl;
return is;
}
else
{
while(!operations.empty())
output.push(string{operations.pull()});
}
}
}
// I solve the output
string aux;
short_t sign = 0;
stack<bignum> numbers;
while(!output.empty())
{
aux = output.pull();
if(isdigit(aux[0]))
{
numbers.push(bignum(aux, sign));
sign = 0;
}
else if(aux[0] == 's')
sign++;
else if(aux[0] == '+')
{
if(numbers.length() < 2)
{
cout << "Syntax Error" << endl;
return is;
}
result = numbers.pull();
result = numbers.pull() + result;
numbers.push(result);
}
else if(aux[0] == '-')
{
if(numbers.length() < 2)
{
cout << "Syntax Error" << endl;
return is;
}
result = numbers.pull();
result = numbers.pull() - result;
numbers.push(result);
}
else if(aux[0] == '*')
{
if(numbers.length() < 2)
{
cout << "Syntax Error" << endl;
return is;
}
result = numbers.pull();
result = numbers.pull() * result;
numbers.push(result);
}
else if(aux[0] == '/')
{
if(numbers.length() < 2)
{
cout << "Syntax Error" << endl;
return is;
}
result = numbers.pull();
result = numbers.pull() / result;
numbers.push(result);
}
}
if(!numbers.empty())
result = numbers.pull();
else
{
cout << "Syntax Error" << endl;
return is;
}
return is;
}
My = operator:
// Constructor por copia
bignum& bignum::operator = (const bignum &right)
{
// Verifico si los bignum a igualar son distintos
if(&right != this)
{
// Borro el puntero de this
delete[] digits;
// En caso de que right este apuntando a NULL
if(!right.digits)
{
type = STANDARD;
digits = NULL;
size = 0;
sign = 0;
}
else
{
type = right.type;
digits = new short_t[right.size];
size = right.size;
sign = right.sign;
// Copio los valores del arreglo right en this
for(size_t i = 0; i < size; i++)
digits[i] = right.digits[i];
}
}
// Devuelvo un puntero a mi bignum this
return *this;
}
My class bignum:
class bignum
{
private:
multiplication_algorithm_t type;
short_t *digits;
short_t sign;
size_t size;