Reputation: 1
I am working on my homework. Aim is to implement class for operations over large integers(BigInt
).
Initialization: each object of class BigInt is constructed as a dynamical array. Members of array are digits of a string entered by user (in reversed order - it was easier for me this way to implement operations).
Specifications of class BigInt: relations between two BigInts (less, greater, equal), operations: addition, subtraction, multiplication. Relations, addition and subtraction work well. Problem is with multiplication.
Problem: when I test the program without multiplication, it works well. When I uncomment multiplication, program breaks after it writes the result of relations, addition and subtraction.
Error: debug assertion failed. When I enter Debug mode, I see that it calculates well until the line:
DELETE [] m;
I looked other questions about debug assertion, and realised that I can't delete object of class BigInt
with delete[] m
, because I already wrote that in my destructor. I tried with DELETE m
. When I do that, it prints out good result, but it breaks after the line:
cout << "before returing m" << endl;.
Error: again Debug Assertion failed, but this time added:
L buffer is too small.
When I enter Debug mode, it shows me that the breakpoint is in Deep Copy constructor, line:
strcpy_s(myDigits, myNumDigits, source.myDigits);
Now I don't know what to do, because it worked well with addition and subtraction (but I guess that in these operations deep copy constructor was never used).
So, the question I need answer to: where is a mistake, is it with using delete[]
, delete
or in implementation of deep copy constructor (or somewhere else)?
I am attaching my code. I don't want it to be difficult to review, so I will attach only the parts needed for the solution of my problem (part of code with constructors, destructor, multiplication). If you think that I should attach more, please tell me in comment.
Construction/Destruction:
BigInt::BigInt(string digits)
{
const char* s = digits.c_str();
int k;
int limit = 0;
myNumDigits = 0;
if (strlen(s) == 0)
{
mySign = positive;
//myDigits = new char[2];
myDigits = nullptr;
myNumDigits = 0;
cout << "Empty string!" << endl;
return;
}
if (digits[0] == '-')
{
mySign = negative;
limit = 1;
}
else
{
mySign = positive;
if (digits[0] == '+')
limit = 1;
}
const char*help = digits.c_str();
myDigits = new char[strlen(s) + 1 - limit];
// reversed order
for (k = strlen(help) - 1; k >= limit; k--)
{
if (!isdigit(digits[k]))
{
cout << "onlu digits and sign! " << endl;
exit(1);
}
AddSigDigit(digits[k] - '0'); //incrementation
}
myDigits[strlen(s) - limit] = '\0';
}
// Copy constructor -deep
BigInt::BigInt(const BigInt& source)
{
// can do shallow copy of a number
myNumDigits = source.myNumDigits;
//deep copy of array
if (source.myDigits)
{
myDigits = new char[myNumDigits + 1];
strcpy_s(myDigits, myNumDigits, source.myDigits); //BREAKPOINT!!!!!
myDigits[myNumDigits] = '\0';
}
else
myDigits = 0;
}
// move copy constructor
BigInt::BigInt(BigInt&&other) {
myNumDigits = other.myNumDigits;
myDigits = other.myDigits;
other.myNumDigits = 0;
other.myDigits = 0;//null pointer
}
BigInt::BigInt(Sign sign, int NumDig, char* sum) {
mySign = sign;
myNumDigits = NumDig;
myDigits = sum;
sum = 0;
}
BigInt::~BigInt() {
delete[] myDigits;
}
Help functions:
int BigInt::GetDigit(int k) const
{
if (0 <= k && k < NumDigits())
{
return myDigits[k] - '0';
}
return 0;
}
void BigInt::AddSigDigit(int value)
// adding value on place of most significant digit
{
myDigits[myNumDigits] = '0' + value;
myNumDigits++;
}
Multiplication:
BigInt BigInt::mul(const BigInt&num)const {
char* a =new char[num.myNumDigits+1];
strcpy(a, num.myDigits);
a[num.myNumDigits] = '\0';
cout << "a" << a << endl;
char* b = new char[myNumDigits + 1];
strcpy(b,myDigits);
b[myNumDigits] = '\0';
cout << "b" << b << endl;
string temp;
BigInt* m = new BigInt("0");
//cout << *m << endl;
unsigned int i;
for ( i = 0; i < strlen(a); i++) {
int carry = 0;
temp = string (i, '0');
unsigned int j;
for (j = 0; j < (int)strlen(b); j++) {
int pom;
pom = (a[i] - '0') * (b[j] - '0') + carry;
temp += ((char)(pom % 10 + '0'));
carry = pom / 10;
}
if (carry != 0)
temp += (carry + '0');
cout <<"temp unreversed in i. iteration" <<temp<<" " <<i << endl;
reverse(temp.begin(), temp.end());
cout << "temp reversed in i. iteration" << temp << " " << i << endl;
BigInt* n = new BigInt((*m).add(BigInt(temp.substr(cut(temp)))));
std::cout << "n in i. iteration " << *n<<"i."<<i<<endl;
delete m;
std::cout << " delete pass" << endl;
m = n;
n = nullptr;
}
cout << "before returing m" << endl;
return (*m); //BECAUSE OF THIS LINE THERE IS BREAKPOINT IN COPY CONSTRUCTOR
cout << "after returing m" << endl;
}
int BigInt::cut(const string& i)const {
int index = 0;
while (i[index] == '0' && index < i.size() - 1) index++;
return index;
}
Upvotes: 0
Views: 185
Reputation: 7923
The mul
code creates m
once, and delete
s it in the loop. Welcome to UB.
Upvotes: 1