-1

In my homework I'm given

BigInteger::BigInteger(int val) {

and

BigInteger::BigInteger(string str) {

I'm supposed to implement two constructors to initialize a BigInteger object from an int value and a string storing an integer value. What I really need is just a step in the right direction for I just don't know how to start this.

It also mentions that this can be useful for it

void BigInteger::setDigit(int pos, char digit)
{
    if (pos >= size)
    { // not enough space
        int newSize = 1;
        while (newSize <= pos)
            newSize *= 2; // compute newSize as a power of 2      that is bigger than pos

        char* temp = digits; // store link to current digits

        digits = new char[newSize]; // allocate a new array
        memset(digits, 0, newSize); // and fill zeros

        if (temp != NULL) // if there are some current digits
            memcpy(digits, temp, nDigits); // copy them
        size = newSize;
    }

    digits[pos] = digit; // put the given digit at position pos

    if (pos >= nDigits) // update the number of digits!
        nDigits = pos + 1;
}

Here's the class definition

class BigInteger
{
private:
    char* digits; // the array storing digits
    int size; // the current size of digits array
    int nDigits; // the current number of digits

    void init(int size);
    void copy(const BigInteger &num);

public:
    BigInteger(); // Default constructor
    ~BigInteger(); // Default destructor

    BigInteger(int val); // Initialize a BigInteger with an integer value
    BigInteger(string str); // Initialize a BigInteger with a string storing a number

    BigInteger(const BigInteger &num); // Copy constructor
    BigInteger& operator=(const BigInteger &num); // Copy assignment operator

    int numberOfDigits() const
    {
        return nDigits;
    }
    char getDigit(int pos) const; // get the digit at position pos
    void setDigit(int pos, char digit); // set the digit at position pos

    void print(bool debug = true);
};

The Ultimate goal of the homework is to be able to compute 999! (1*2*3*....999)

Like I said a step in the right direction would be appreciated.

Here is the whole code:

#include"BigInteger.h"

BigInteger::BigInteger()
{
    digits = NULL; // Default constructor: storing nothing!
    size = 0;
    nDigits = 0;
}

BigInteger::~BigInteger()
{
    if (digits != NULL)
        delete[] digits;
    digits = NULL;
    size = 0;
    nDigits = 0;
}

void BigInteger::init(int size)
{
// Task 1. Allocate memory for digits and fill them as zeros
    digits = new char[size];
    for (int i = 0; i < size; i++)
    {
        digits[i] = 0;
    }

}

void BigInteger::copy(const BigInteger &num)
{
    size = num.size; // copy digits array size
    nDigits = num.nDigits; // copy number of digits
    digits = new char[size]; // allocate a new digits array with        the same size in num
    memcpy(digits, num.digits, size); // copy digits array
}

BigInteger::BigInteger(const BigInteger &num)
{ // Copy constructor
    copy(num);
}

BigInteger& BigInteger::operator=(const BigInteger &num)
{
    if (this != &num)
    { // not assign to the same object
        if (digits != NULL)
            delete[] digits; // release current digits array
        copy(num);
    }
    return *this;
}

BigInteger::BigInteger(int val)
{
// Task 2a. Construct a BigInteger from an int value

}

BigInteger::BigInteger(string str)
{
// Task 2b. Construct a BigInteger from a string.

}

char BigInteger::getDigit(int pos) const
{
    if (pos >= nDigits)
        return 0;
    else
        return digits[pos];
}

void BigInteger::setDigit(int pos, char digit)
{
    if (pos >= size)
    { // not enough space
        int newSize = 1;
        while (newSize <= pos)
            newSize *= 2; // compute newSize as a power of 2      that is bigger than pos

        char* temp = digits; // store link to current digits

        digits = new char[newSize]; // allocate a new array
        memset(digits, 0, newSize); // and fill zeros

        if (temp != NULL) // if there are some current digits
            memcpy(digits, temp, nDigits); // copy them
        size = newSize;
    }

    digits[pos] = digit; // put the given digit at position pos

    if (pos >= nDigits) // update the number of digits!
        nDigits = pos + 1;
}

BigInteger multiply(BigInteger &x, int y, int pos = 0)
{
    int nx = x.numberOfDigits();
    BigInteger z;
    int carry = 0;
    for (int i = 0; i < nx; i++)
    {
        carry += x.getDigit(i) * y;
        z.setDigit(pos++, carry % 10);
        carry /= 10;
    }
    while (carry > 0)
    {
        z.setDigit(pos++, carry % 10);
        carry /= 10;
    }
    return z;
}

void BigInteger::print(bool debug)
{
    if (digits == NULL)
        cout << '0';
    else
        for (int i = nDigits; --i >= 0;)
            cout << (int) digits[i];
    if (debug)
        printf(" [digits = %x, size = %d, nDigits = %d] ",
               digits,
               size,
               nDigits);
}

ostream& operator<<(ostream& out, BigInteger num)
{
//Task 3. Overload operattor << to write a BigInteger object to screen
    num.print();
    return out;
}
A-Sharabiani
  • 17,750
  • 17
  • 113
  • 128
  • 1
    So is the goal to get a BigInteger class working, or a dynamic array working? If it's the former, use `std::vector` and drop the manual memory management. After that, the problem can be solved at a higher level instead of getting into the weeds of `new[] / delete[]`. And if the response is "I can't use vector", using vector does not make a BigInteger class. What it **does** do is get you to actually start writing the code to make such a class without hassle. – PaulMcKenzie Feb 09 '16 at 22:58
  • Here is an example with no manual memory management. http://ideone.com/Kizzp1 There is no need for copy constructor, assignment operator, destructor. All we do is call `resize` to set the dynamic array to a new size. Now, none of the code to create a BigInteger from a string was coded. But at least, you have a solid barebones class, instead of one built on buggy base code using manual memory management. – PaulMcKenzie Feb 09 '16 at 23:17
  • 1
    Also, if for the odd reason you must use manual memory management, you should still use the sample code to, at least, code up the constructor for the `std::string` version. Then if that works, **then** you try to rewrite it using manual memory management, with the full knowledge that at least, you are / were on the right track. – PaulMcKenzie Feb 09 '16 at 23:21
  • A few useful hints: Digits can be isolated from an integer with the modulo operator, `%`, so if you have integer x = 314, you can `x % 10` to get the 4, then `x /=10` to remove the 4 and position x to get the 1. Stop when `x == 0`. Note you got a 4, a 1 and a 3 in that order. You'll have to turn it around. Turning a string into a number is similar. Usually you take one character from the string and subtract the value of character 0 to get the number value. So "314" is `'3' - '0'`, `'1' - '0'`, `'4' - '0'`. Some character sets don't store the numbers in a row, but you are unlikely to see one. – user4581301 Feb 09 '16 at 23:28

1 Answers1

0

You already have code to store an integer value in a BigInteger, in the multiply function. The code that saves the rest of the carry (at the end) is saving it into a BigInteger. Use that as an example.

For the string one, you just need to put the digits from the string into the BigInteger object in reverse.

The Dark
  • 8,453
  • 1
  • 16
  • 19