Solved

Beginner programming help operator overloading

Posted on 2009-03-30
51
549 Views
Last Modified: 2013-12-14
In my programming class I have to design a class that can store integer values of up to 40 digits and perform arithmetic operations with them by overloading operators. I'm not very good at programming, so I seem to have hit quite a few road blocks.

#pragma once
#include<vector>
#include<iostream>

using namespace std;

class HugeInt {
private:
int digits[40];
public:
HugeInt(void);
~HugeInt(void);
HugeInt(long long init);
HugeInt(const HugeInt &h);
friend istream& operator >>(istream &input, HugeInt &a);
friend ostream& operator <<(ostream &output, HugeInt &a);
void setHugeInt(long long init);
int getHugeInt();
HugeInt &operator =(HugeInt& rhs);
HugeInt operator +(const HugeInt& rhs) const;
HugeInt operator -(const HugeInt& rhs) const;
HugeInt operator *(const HugeInt& rhs) const;
HugeInt operator /(const HugeInt& rhs) const;
bool operator <(const HugeInt& rhs) const;
bool operator >(const HugeInt& rhs) const;
bool operator ==(const HugeInt& rhs) const;
bool operator !=(const HugeInt& rhs) const;
bool operator <=(const HugeInt& rhs) const;
bool operator >=(const HugeInt& rhs) const;
bool operator !() const;
};

^^is my class file. I'm working on the implementation of it now, but i can't get anywhere. the first issue at hand is how to handle the input streams and output streams.
stream& operator >> (istream& input, HugeInt& a)

{
      input>>a.digits;
      

      return input;




}
ostream& operator<<(ostream& output, HugeInt&a)
{
      output<< a.digits<<endl;
      return output;

}
this is what I have, but it doesn't seem to work like i'm intending it to.
0
Comment
Question by:jmckennon
  • 26
  • 18
  • 6
  • +1
51 Comments
 
LVL 40

Expert Comment

by:mrjoltcola
ID: 24020787
My 2 cents:

1st problem I see, is you are trying to handle (read/write) an array (pointer) of ints with streams. There is no operator in C++ by default, for that.

output << a.digits;   // this is a whole array, which ostream will not handle unless you overload it

If a HugeInt has 40 digits, and you plan to hold them in an int array, you need to pass each individual digit to the stream.

output << a.digits[0] << a.digits[1] << ...;

OR write a loop to do it.

for(int i = 0; i << 40; i++)
   output << a.digits[i];


However, the problem I see is that you are going to want to limit each digit to 0-9. By default, the C++ istream will read a string of digits for a single integer. So if you write:

input >> a.digits[0] >> a.digits[1];

Then legal input could be 12456 99999 for the 1st 2 digits. That is not what you want.

I think  you should approach it differently, perhaps by reading it in as a string, or as individual characters, then iterate through the string characters and validate each with isdigit(), and convert to your digits[] array.

That said, I don't use C++ streams that much, so if another expert, such as Infinity chimes in I will leave it for him.

#include <iostream.h>
 

int main() {
 

  int i[10];

  cin >> i[0] >> i[1];
 

  cout << i[0] << i[1] << endl;

}

Open in new window

0
 

Author Comment

by:jmckennon
ID: 24020892
Okay, I see how that would work with the input and the output.  I've got a whole bag of questions on this one. The next issue I had, was I'm not qutie sure how to set up the parameterized constructor and the copy constructor.

HugeInt:: HugeInt(long long init)
{
      int i(0);
      int integer(0);
      stringstream stream;
      string longInt;
      stream<<init;
      longInt=stream.str();
      for(i=0;i<40;i++)
      {
            integer=longInt[i] +'0';
            digits[i]=integer;
            
      }
      



}

is what I have for the parameterized one. I'm not sure if that's the proper way of handling it, and input would be great. I have no idea how to handle the copy constructor in this case. So far, I have
HugeInt::HugeInt(const HugeInt &h)
{
      int i(0);
      for(i=0;i<40;i++)
      {

      }
      
      
}
the copy constructor is so I can do things like
HugeInt h2;
HugeInt h3;
h2=h3;

in my main.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24021422
>>>> integer=longInt[i] +'0';

That is wrong. The longInt already contains digits. You may not add '0' to a char which is already in the range of '0' to '9'.

It is not quit clear why you store the (decimal) digits of a long long into an int array. You could store the string as well and have much more advantages (e. g. for reading the number from cin).

You can simply drop the copy constructor. Then the compiler would create one for you which makes a binary copy of the object (what is just fine).
0
 

Author Comment

by:jmckennon
ID: 24023084
Would dropping the copy constructor allow me to perform deep copies in my main program?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24023980
>>>>> Would dropping the copy constructor allow me to perform deep copies in my main program?

Generally yes. But you should be aware that a member of an int array doesn't need a deep copy but that a flat copy would have the same results. A deep copy cmae into play if you either have class object members or pointer members. While for the first the default copy constructor still will be able to perform a deep copy, you need to implement a copy constructor when using pointer members. That is one of the reasons why pointer members should be avoided (beside when implementing a container class).
0
 

Author Comment

by:jmckennon
ID: 24024327
Ah, I see. My program is now telling me that I can't access the contents of digits even though I'm trying to do so in a member function or in a mutator function. How do I fix this?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24024423
the digits is a private member. You only can use it in a member function of class HugeInt or in a friend function.
0
 

Author Comment

by:jmckennon
ID: 24025433
HugeInt HugeInt:: operator+(HugeInt& rhs)
{
      HugeInt temp;
      long long input[40];
      long long rhsInput[40];

      int i(0);
      long long addition(0);
      long long z(0);
      long long f(0);

      vector<long long> hugeVector;
      for(i=0;i<40;i++)
      {
            input[i]=digits[i];
            rhsInput[i]=rhs.digits[i];
      }

      i=0;
      for(i=0;i<40;i++)
      {
            z= (input[i]+rhsInput[i])+f;
            if(z>10)
            {
                  z=z-10;
                  f=1;
            }
      }
            hugeVector.push_back(z);
            z=0;




      vector<long long>::iterator hugeIterator;

      long long parsedLong(0);
      i=0;
      for(hugeIterator=hugeVector.begin();hugeIterator<hugeVector.end();hugeIterator++)
      {
            
            parsedLong=*hugeIterator;
            temp.digits[i]=parsedLong;
            i++;
      }







      return temp;










}


this is my implementation of the + operator. It is written exactly how I would liek it to except I keep getting
Error      2      error LNK2001: unresolved external symbol "public: __thiscall HugeInt::HugeInt(class HugeInt const &)" (??0HugeInt@@QAE@ABV0@@Z)      HugeInt.obj      lab4_HugeInt
Error      3      fatal error LNK1120: 1 unresolved externals      z:\visual studio 2008\Projects\lab4_HugeInt\Debug\lab4_HugeInt.exe      1      lab4_HugeInt

I went through this portion of code line by line, and it gave me the error at return temp;
How do i fix this???
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24027312
>> I went through this portion of code line by line, and it gave me the error at return temp;

temp is returned by value, so a copy is made of the object. For that, you need a copy constructor (either the default copy constructor, if it's straightforward, or you have to define your own). If you want to use the default copy constructor, then make sure not to declare one in the class definition.
0
 

Author Comment

by:jmckennon
ID: 24027604
I'm not sure as to how a copy constructor should be written. I have one declared in my header file, and I have
HugeInt::HugeInt(const HugeInt &h)
{
}
in my implementation, but I don't know what to put inside the brackets. How would I go about designing this?
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24027633
>> in my implementation, but I don't know what to put inside the brackets. How would I go about designing this?

The idea of a copy constructor is to copy the data from the object passed by (const) reference to the current object (being constructed). You only really need a custom copy constructor if there's something special to be done (like dynamically allocate data, or obtain a resource, or increment a reference counter, or ...). If the copying is simply straightforward data copying, you can rely on the default copy constructor provided for you if you don't specify one.
0
 

Author Comment

by:jmckennon
ID: 24027989
Awesome! That cleared up the error. I've finished overloading the addition and subtraction operators, but I'm stuck on the = operator. I haven't the slightest idea even what overloading that would do?
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24028039
>> but I'm stuck on the = operator. I haven't the slightest idea even what overloading that would do?

It's the assignment operator. It does a similar thing to the copy constructor, ie. it copies the data from the object argument to the current object.
0
 

Author Comment

by:jmckennon
ID: 24028376
I don't really see how to overload that though. Can I see maybe some pseudo code or possibly help me work through setting this part up?
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24028443
What do you mean ? You already had the start in your original post.

In any case, here's an example :
class Foo {

  private :

    int data;

  public :

    Foo(int d = 0) : data(d) { }

    Foo &operator=(const Foo &f);       // <--- the assignment operator

};
 

Foo &Foo::operator=(const Foo &f) {     // <--- implementation of the assignment operator

  if (this != &f) {                     // <--- check for self-assignment

    this->data = f.data;

  }

  return *this;

}
 
 

// and then :
 

Foo f1(5), f2;

f2 = f1;                                // <--- calls the assignment operator

Open in new window

0
 

Author Comment

by:jmckennon
ID: 24028579
Ohh!! Okay! i see it now thanks! I'll keep working on this and get back to you!
0
 

Author Comment

by:jmckennon
ID: 24028739
HugeInt &HugeInt::operator=( HugeInt &f) {    
      int i=0;
      for(i=0;i<40;i++)
      {

            if (this != &f) {                    

                  this->digits[i] = f.digits[i];
            }
      }

      return *this;
}


is my implementation of the equals operator, the compiler doesn't like it.
Warning      1      warning C4244: '=' : conversion from '__int64' to 'int', possible loss of data      z:\visual studio 2008\projects\lab4\lab4\hugeint.cpp      397      lab4
Error      2      error LNK2019: unresolved external symbol "public: __thiscall HugeInt::HugeInt(class HugeInt const &)" (??0HugeInt@@QAE@ABV0@@Z) referenced in function "public: class HugeInt __thiscall HugeInt::operator+(class HugeInt &)" (??HHugeInt@@QAE?AV0@AAV0@@Z)      HugeInt.obj      lab4
Error      3      error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup      MSVCRTD.lib      lab4
Error      4      fatal error LNK1120: 2 unresolved externals      Z:\visual studio 2008\Projects\lab4\Debug\lab4.exe      1      lab4


i don't understand what those errors mean?
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24028779
Several things :

1) You need to pass the argument by const reference, not just a reference (see my example).

2) You do the check for self-assignment only once, not for each data member. Do you understand what that check does, and why it's needed ?
0
 

Author Comment

by:jmckennon
ID: 24029395
I think I understand it. The check checks to see if the data at that location is the same as the data being passed as an argument, and if it's not, if makes it the same?
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24029465
>> The check checks to see if the data at that location is the same as the data being passed as an argument, and if it's not, if makes it the same?

Not exactly. Self-assignment is something like this :

    Foo f1;
    f1 = f1;          // <--- self assignment

In the basic case, this is not a problem, since you'd just copy data from location X to location X (the same location) ... ie. not change anything at all. The problem however occurs, when the assignment operator does something more complicated, like dynamically allocate memory, or obtain a resource, or ... which would result in a memory leak or resource leak resp. in the case of self-assignment. In order to prevent these problems, a check needs to be done for self-assignment, and if it's detected, nothing should be done.
0
 

Author Comment

by:jmckennon
ID: 24029524
Oh okay. I see what you mean, but I'm not quite sure how to write it so that it would perform the check for every data member. I thought my for loop would take care of that.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24029542
>> but I'm not quite sure how to write it so that it would perform the check for every data member.

how to NOT perform the check for each data member, but instead perform the check only ONCE. There's no reason or need to check it more than once. Just do it once, at the start, and that's it.
0
 

Author Comment

by:jmckennon
ID: 24029576
HugeInt &HugeInt::operator=( const HugeInt &rhs) {    

      if (this != &rhs)
      {                    

            this->digits = rhs.digits;
      }


      return *this;
}

is my set up for it now. Does that look about right?

also, it gives me this error when I compile it now
Error      1      error C2440: '=' : cannot convert from 'const int [40]' to 'int [40]'      z:\visual studio 2008\projects\lab4\lab4\hugeint.cpp      41      lab4


I really appreciate all your help with this, you're really helping me trudge through the tough stuff here.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24029626
>>             this->digits = rhs.digits;

Since digits is an array, you cannot copy it like that.

Just like this wouldn't work either :

        int array1[10];
        int array2[10];
        array2 = array1;          // <--- this won't work

You need to copy the data differently (either using a loop, and copy each element separately, or doing a memory copy of the entire array).
0
 

Author Comment

by:jmckennon
ID: 24029680
Sweet! I got it to work. I'll continue working and see how things go!
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:jmckennon
ID: 24029850
HugeInt HugeInt:: operator +(HugeInt& rhs)
{
      HugeInt temp;
      char input[40];
      char rhsInput[40];
      int i(0);
      long long addition(0);
      long long z(0);
      long long f(0);
      vector<long long> hugeVector;
      
      for(i=0;i<=40;i++)
      {
            if(rhs.digits[i]+'0'>=0)
            {
                  rhsInput[i]=rhs.digits[i]+'0';
            }
            else
            {
                  rhsInput[i]=NULL;
            }
            if(digits[i]+'0'>=0)
            {
                  input[i]=digits[i]+'0';
            }
            else
            {
                  input[i]=NULL;
            }

      }

Is what I'm workign with now. I'm currently stepping through the program, and I'm trying to make sure the values that the user enters are getting into input and rhsInput. the value are getting in there except if the user puts in say 123 and 111 input gets 023 and rhsInput gets 011. WHy is the leading zero replacing the first value?
0
 

Author Comment

by:jmckennon
ID: 24030005
Figured it out, it had to do with my input stream operator.
0
 

Author Comment

by:jmckennon
ID: 24030322
HugeInt HugeInt:: operator +(const HugeInt& rhs) const
{
      HugeInt temp;
      char input[40];
      char rhsInput[40];
      int c;
      int parsedInt(0);
      int i(0);
      int addition(0);
      int z(0);
      int f(0);
      vector<int> hugeVector;

      for(i=40;i>=0;i--)
      {
            if(rhs.digits[i]+'0'>=0)
            {
                  rhsInput[i]=rhs.digits[i]+'0';
            }
            else
            {
                  rhsInput[i]=NULL;
            }
            if(digits[i]+'0'>=0)
            {
                  input[i]=digits[i]+'0';
            }
            else
            {
                  input[i]=NULL;
            }

      }
      i=0;
      for(i=40;i>=0;i--)
      {
            z= ((input[i]-'0')+(rhsInput[i]-'0')+f);
            if(z>10)
            {
                  z=z-10;
                  f=1;
            }
            if(z>=0)
            {hugeVector.push_back(z);
            }
            z=0;
      }


      vector<int>:: reverse_iterator it;
      i=0;
      for ( it=hugeVector.rbegin() ; it < hugeVector.rend(); it++  )
      {

            parsedInt=*it;
            c=parsedInt;

            temp.digits[i]=c;
            i=i+1;
      }
      i=0;
      for(i=0;i<40;i++)
      {
            if(temp.digits[i]<=0)
            {
                  temp.digits[i]='\0';

            }
      }




      return temp;










}



Now when i reach the return statement, the compiler tells me "the stack around rhsInput is corrupted" I have never seen this before.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24033373
>>       for(i=40;i>=0;i--)

40 is not a valid index for an array of size 40. The last element of the array is at index 39, not 40.


>> if(rhs.digits[i]+'0'>=0)

won't this always be the case ? Since rhs.digits[i] is a value between 0 and 9 (inclusive), (rhs.digits[i]+'0') is definitely bigger than 0. For ASCII, '0' has the value 0x30, so (rhs.digits[i]+'0') would range from 0x30 to 0x39 (inclusive), which is definitely >= 0.


>> rhsInput[i]=NULL;

This is confusing. rhsInput[i] is a char, because rhsInput is an array of char's. NULL is usually used for pointers, not for char's.
Although the compiler will interpret this by setting the char to '\0' (was that what you intended ?), it is confusing to the human reader.


>> temp.digits[i]='\0';

And here, it's similar. temp.digits[i] is an int, since temp.digits is an array of int. '\0' is usually used for characters, not for ints.
The compiler will interpret this by setting the int to 0 (was that what you intended ?).
0
 

Author Comment

by:jmckennon
ID: 24035353
Hello, I'm back again. I have successfully set up the + operator to specification which is awesome. I am however stuck with that same "stack corrupted" type thing but i can't seem to figure out where it's coming from in the subtraction part
HugeInt HugeInt:: operator -(const HugeInt& rhs) const
{

      HugeInt temp;
      char input[40];
      char rhsInput[40];
      int c;
      int parsedInt(0);
      int i(0);
      int addition(0);
      int z(0);
      int f(0);
      vector<int> hugeVector;
      vector<int> inputDigitCounter;
      vector<int> inputCounter;
      vector<int> rhsCounter;
      vector<int>:: iterator counter;

      for(i=0;i<40;i++)
      {
            if(rhs.digits[i]+'0'>=0)
            {
                  rhsInput[i]=rhs.digits[i]+'0';
                  rhsCounter.push_back(rhsInput[i]);
            }

            if(digits[i]+'0'>=0)
            {
                  input[i]=digits[i]+'0';
                  inputCounter.push_back(input[i]);
            }

      }
      while(rhsCounter.size()< inputCounter.size())
      {
            counter=rhsCounter.begin();
            rhsCounter.insert(counter,'0');

      }
      while(inputCounter.size()< rhsCounter.size())
      {
            counter=inputCounter.begin();
            inputCounter.insert(counter,'0');

      }
      for(counter=inputCounter.begin();counter<inputCounter.end();counter++)
      {
            input[i]=*counter;
            i++;

      }
      i=0;
      for(counter=rhsCounter.begin();counter<rhsCounter.end();counter++)
      {
            rhsInput[i]=*counter;
            i++;

      }

      i=0;
      
      for(i=39;i>=0;i--)
      {
            z= ((input[i]-'0')-(rhsInput[i]-'0'));
            if(f==1)
            {
                  z=z-1;
            }
            f=0;
            if(z<0)
            {
                  z=z+10;
                  f=1;
            }
            if(z>0||f==1)
            {
                  hugeVector.push_back(z);
            }
            z=0;
      }

      if(f==1)
      {
            hugeVector.push_back(f);
      }

      vector<int>:: iterator it;
      i=39;


      for ( it=hugeVector.begin() ; it < hugeVector.end(); it++  )
      {

            parsedInt=*it;
            c=parsedInt;

            temp.digits[i]=c;
            i=i-1;
      }
      i=0;












      return temp;


}
is my code for it. Hope you can help!
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24036991
At the start of this loop :

>>       for(counter=inputCounter.begin();counter<inputCounter.end();counter++)

i is equal to 40. 40 is out of range for the array of size 40, and each iteration of that loop will further increase i, and you end up overwriting memory past the end of the buffer.
0
 

Author Comment

by:jmckennon
ID: 24040879
Ah! you always seem to see what i dont.
I'm now working on the multiply operator and i have it working for single digit multiplication, but i have no idea how toimplement something of multiple digits. My program will go through each digit of hugeInt h1 and multiply them all by the 1st digit of h2. then it will go back to the beginning of h1 and multiply everything by the second digit of h2 etc etc.  the only issue is, at the end, to successfull multiply numbers,you need to shift the numbers over one place each time   h2 is incremented and then add them. I don't know how/where to store all the multiplied values before I add them. Here's what i have so far

HugeInt HugeInt:: operator *(const HugeInt& rhs) const
{
      HugeInt temp;
      char input[40];
      char rhsInput[40];
      int c;
      int parsedInt(0);
      int i(0);
      int addition(0);
      int z(0);
      int f(0);
      int push(0);
      int multiplyArray[40][40];

      vector<int> hugeVector;
      vector<int> inputDigitCounter;
      vector<int> inputCounter;
      vector<int> rhsCounter;
      vector<int>:: iterator counter;

      for(i=0;i<40;i++)
      {
            if(rhs.digits[i]+'0'>=0)
            {
                  rhsInput[i]=rhs.digits[i]+'0';
                  rhsCounter.push_back(rhsInput[i]);
            }

            if(digits[i]+'0'>=0)
            {
                  input[i]=digits[i]+'0';
                  inputCounter.push_back(input[i]);
            }

      }
      while(rhsCounter.size()< inputCounter.size())
      {
            counter=rhsCounter.begin();
            rhsCounter.insert(counter,'0');

      }
      while(inputCounter.size()< rhsCounter.size())
      {
            counter=inputCounter.begin();
            inputCounter.insert(counter,'0');

      }
      i=0;
      for(counter=inputCounter.begin();counter<inputCounter.end();counter++)
      {
            input[i]=*counter;
            i++;

      }
      i=0;
      for(counter=rhsCounter.begin();counter<rhsCounter.end();counter++)
      {
            rhsInput[i]=*counter;
            i++;

      }

      i=0;
      int start(0);
      int a(39);
      for(i=39;i>=0;i--)
      {
            z= ((input[i]-'0')*(rhsInput[a]-'0'))+f;
            f=0;
      while(z>=10&&z<99)
            {
                  z=z-10;
                  f=f+1;
                  push=1;
                  start=1;
            }
            if(z>0&&push==1||f==1||z<10&&z>0)
            {
                  hugeVector.push_back(z);
                  start=1;
            }
            if(z==0 && start==1)
            {
                  hugeVector.push_back(z);
            }
            
            z=0;
            push=0;
            if(i==0&&a>=0)
            {
                  i=39;
                  a--;
            }
      }

      if(f==1)
      {
            hugeVector.push_back(f);
      }
      while(hugeVector.size()<inputCounter.size())
      {
            counter=hugeVector.begin();
            hugeVector.insert(counter,0);
      }
            while(hugeVector.size()<rhsCounter.size())
      {
            counter=hugeVector.begin();
            hugeVector.insert(counter,0);
      }

      vector<int>:: iterator it;
      i=39;

vector<int> parsedCounter;
      int parseInt(0);


       for(it=hugeVector.begin();it<hugeVector.end();it++)
       {
            while(parsedCounter.size()<inputCounter.size())
            {

                  parsedInt=*it;
                  c=parsedInt;
                  it++;
                  if(c!=0||parseInt==1)
                  {
                        parseInt=1;
                  

            
                  temp.digits[i]=c;
                  i=i-1;
                  parsedCounter.push_back(c);
                  
                  
                  }
                  
            }
            if(parseInt==1)
                  {
                  it--;
                  }
            
            parseInt=0;
            
       }
       return temp;





}
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24046996
>>>> Ah! you always seem to see what i dont.
You should avoid code where you use variables in a loop which were not rightly initialized just before the loop but at the top of the function or in some other unrelated code sequence. Keep your code tightly together so that you easily could turn sequences to a function if the code gets lengthy or if you need to repeat some parts.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24047791
>> I don't know how/where to store all the multiplied values before I add them.

You only really need to keep two values : the current multiplication result, and the total. You start by setting the total to 0, and then start multiplying the first value with the first digit of the second value. The result of that is placed in the multiplication result variable, and then added to the total. Next, you multiply with the second digit, again placing the result in the multiplication result variable, and then add it to the total, etc.
0
 

Author Comment

by:jmckennon
ID: 24050102
i tried doing that but i always got an overflow. do you have maybe some pseudocode or an example i could look at? I really appreciate all your help with this, I wish i could give more than 500 pts in the end
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24050230
Are you sure that your i doesn't go below zero here ?

>>                   temp.digits[i]=c;
>>                   i=i-1;


You didn't fix what I pointed out earlier about :

>> if(rhs.digits[i]+'0'>=0)


>> i tried doing that but i always got an overflow.

What overflow ? Where ? With what code ?
0
 

Author Comment

by:jmckennon
ID: 24056173
Hi again,

I got alot of work on the program done today, but I ran into another one of those external error things again.
HugeInt HugeInt::multiplySub(int multiplier) const
{
      //in progress
      HugeInt result3;

      int carry = 0;      //holds value of carry over
     
      for (int i = 39; i>=0; i--)
      {
        //multiply both digits together and add carry over
          int temp = (digits[i]);
          result3.digits[i] = (temp * multiplier) + carry;
          carry = 0;
          //if integer is greater than 10
        if (result3.digits[i] >= 10)
          {
             carry = result3.digits[i] / 10;
             result3.digits[i] = result3.digits[i] % 10;
          }
     }

      return result3;
}
HugeInt HugeInt::operator*(const HugeInt &rhs) const
{
     
      HugeInt result;

      int carry = 0;      
      int powerOfTen = 0;
     
      for (int i = 39;i>=0; i--)
      {      
         int temp = rhs.digits[i];
         if (temp > 0) {
           
            HugeInt result0 = *this;
            for (int loopIndex = powerOfTen; loopIndex > 0; loopIndex--) {
               HugeInt result2a = multiplySub(2);
               HugeInt result2b = result2a.multiplySub(5);
               copyHugeInt(result0.digits,result2b.digits);
            }
            HugeInt result3 = result0*(temp);
            HugeInt result4 = result+(result3);
            copyHugeInt(result.digits,result4.digits);
            powerOfTen++;
         }
      }

      return result;
}
 is my code that i've added today.

the error says " error lnk2019: unresolved external symbol" public :_thiscall HugeInt::HugeInt(class HugeInt const&)"(??0HugeInt@@QAE@ABV0@@Z) referenced in function "public:class HugeInt_thiscall HugeInt multiplySub(int)const "(?multiplySub@HugeInt@@QBE?AV!@H@Z)

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24057160
>>>> HugeInt::HugeInt(class HugeInt const&)"(??0HugeInt@@QAE@ABV0@@Z)

Seems that in the class declaration there is no final const as in

   HugeInt HugeInt::operator*(const HugeInt &rhs) const

Check, that all signatures of operators and functions were same in .h and .cpp.

If that doesn't help you may do a rebuild.


0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24057711
Did you implement the copy constructor :

        HugeInt(const HugeInt &h);

?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24058432
>>>> Did you implement the copy constructor :
>>>>         HugeInt(const HugeInt &h);

Ah. Infinity is right. I mixed it up with the operator* but the linker complains about a missing copy constructor.

Note, if you omit the copy constructor (in the class definition) the compiler will create one if needed (and it was needed in your case when you have a statement like 'return hugeint;') . That is fine as long as you have no pointer members. So, instead of implementing a copy constructor you could simply remove the 'HugeInt(const HugeInt &h);' statement in your class and make a rebuild.



0
 

Author Comment

by:jmckennon
ID: 24059844
Ah i see it now! The only thing is, that I do need a copy constructor as part of the specs for the program in order to do a deep copy. The program has a simple output  i have to show

HugeInt 1 + HugeInt 2
HugeInt1 - HugeInt 2
etc etc
and at the end I have to show

HugeInt3=HugeInt1
HugeInt4=HugeInt 2
HugeInt5=HugeInt1+HugeInt2+200

how would I set up a copy constructor to make these last things possible, or, is the default one good enough?

Here's what I have for my constructor in the class header
HugeInt(const HugeInt &h);

I have no idea how to implement that part so that deep copying will be available
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24059901
If you haven't modified the data members, and they're still just :

        int digits[40];

then you don't really need to do anything special in the copy constructor. You can in fact rely on the default generated copy constructor if you wish.

If you have dynamically allocated member data for example, you'll need to provide your own copy constructor that constructs a new object which has its own dynamically allocated memory that contains a copy of the original data.
0
 

Author Comment

by:jmckennon
ID: 24060119
When I use the statement h3=h1; i get a value of 9000000000000000000000000000000000000000000 when i print out the value of h3. this kind of tells me that i may need an external copy constructor of some sort, or that something funky is going on.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24060136
You'll need to check your assignment operator if the result is wrong.
0
 

Author Comment

by:jmckennon
ID: 24060210
I'll check , but I'm on a computer where I can't access my program at the moment. I'll look at the assignment operator/send the code in about a half hour thanks!
0
 

Author Comment

by:jmckennon
ID: 24060824
HugeInt &HugeInt::operator=( const HugeInt &rhs) {    

      if (this != &rhs)
      {    
            for(int i=0;i<40;i++)
            {

                  this->digits[i] = rhs.digits[i];

                  if(rhs.digits[i] <=0)
                  {
                        this->digits[i]=NULL;
                  }

            }
      }


      return *this;
}

Im not sure where I went wrong in this


0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24060865
>>                   if(rhs.digits[i] <=0)
>>                   {
>>                         this->digits[i]=NULL;
>>                   }

NULL is not generally used as an int value ... The compiler will interpret this as a 0 value, so there's no problem if that's what you intended, but the use of NULL is misleading since it suggests that you're dealing with a pointer rather than an int value.

Also, is it ever possible that rhs.digits[i] is < 0 ?


>> Im not sure where I went wrong in this

What makes you think you went wrong somewhere ? What was the (complete) code you used, the test data you used, the result you got, and the result you expected ?
0
 

Author Comment

by:jmckennon
ID: 24061443
well now, I can't even get that far. I was checking to see if my multiplication works, and it gives me an error when I run the program, but not when i build it. it tells me error, string subscript out of range when it exits the for loop in this part of the code
HugeInt HugeInt:: operator *(const HugeInt& rhs) const
{
     
      HugeInt result;

      int carry = 0;      
      int powerOfTen = 0;
     
      for (int i = 39;i>=0; i--)
      {      
         int temp = rhs.digits[i];
         if (temp > 0) {
           
            HugeInt result0 = *this;
            for (int loopIndex = powerOfTen; loopIndex >0; loopIndex--) {
               HugeInt result2a = multiplySub(2);
               HugeInt result2b = result2a.multiplySub(5);
               copyHugeInt(result0.digits,result2b.digits);
            }
            HugeInt result3 = result0*temp;
            HugeInt result4 = result+(result3);
            copyHugeInt(result.digits,result4.digits);
            powerOfTen++;
         }
      }

      return result;
}
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24062245
>> string subscript out of range

What string ? Can you post the whole code as well as the exact location of the error, as well as the test data you used as input ?
0
 

Author Comment

by:jmckennon
ID: 24062355
Well I changed the multiplication stuff to
HugeInt HugeInt::operator *(const HugeInt& rhs) const
{
   

   int carry = 0;      //holds value of carry over
   // Skip leading multiplier zeros.  
   // There will be a nonzero digit because we've already checked whether the multiplier is zero.
   int digitIndex = 0;
      for ( ; ((digitIndex < 40) && (rhs.digits[digitIndex] == 0)); digitIndex++);
      // Process the rest of the multiplier
   HugeInt result;
      for (digitIndex = digitIndex; digitIndex < 40; digitIndex++) {
         int temp = (rhs.digits[digitIndex]);
         HugeInt result0 = multiplySub(temp);
         HugeInt result1 = result.multiplySub(2);
         HugeInt result2 = result1.multiplySub(5);  // These two together multiply the result by 10
         HugeInt result3 = result2 + result0;
         copyHugeInt(result.digits,result3.digits);
      }
   
   return result;
}
HugeInt HugeInt::multiplySub(int multiplier) const
{
      //in progress
      HugeInt result3;

      int carry = 0;      //holds value of carry over
     
      for (int i = 39; i>0; i--)
      {
        //multiply both digits together and add carry over
          int temp = (digits[i]);
          result3.digits[i] = (temp * multiplier) + carry;
          carry = 0;
          //if integer is greater than 10
        if (result3.digits[i] >= 10)
          {
             carry = result3.digits[i] / 10;
             result3.digits[i] = result3.digits[i] % 10;
          }
     }

      return result3;
}

and it tells me the stack around variable 'temp' is corrupted. I'm using 2009 as my first input and 2 as the second input.
Here is my output
 Please enter the first HugeInt
2009

Please enter the second HugeInt
2

 h1 + h2 = 2011
h1 - h2 = 40040040900000000000000000000000000000000
h1 * h2 = 204264870931537598204264870931537600000
 h1 < h2 : False
 h1 <= h2 : False
 h1 > h2 : True
 h1 >=h2 : True
 h1 == h2 : False
 h1 !=h2 :  False
 !h1  : False
 !h2 : False
 h3 = h1 = 9000000000000000000000000000000000000

so, multiplication, subtraction and the copy constructors are being weird.
here's the subtraction code, i can't figure out where it's getting all that stuff
HugeInt HugeInt::operator -(const HugeInt &rhs)const
{
      HugeInt result2;
      int borrow = 0;

     
     
 
           
            if (*this>=rhs)
            {
                  for (int digitIndex = 39; digitIndex > 0; digitIndex--)
                  {
                       
                        if (digits[digitIndex] < rhs.digits[digitIndex])
                        {
                              int temp = digits[digitIndex];
                              result2.digits[digitIndex] = temp + 10 - rhs.digits[digitIndex] - borrow;
                              borrow = 1;
                 
                        }//end inner if
                        else
                        {
                              int temp = digits[digitIndex];
                              result2.digits[digitIndex] = temp - borrow - rhs.digits[digitIndex];
                              borrow = 0;
                        }
                  }
            return result2;
            }
           
}
0
 
LVL 53

Accepted Solution

by:
Infinity08 earned 500 total points
ID: 24062595
To find out what the problem is, either run your code in a debugger, and watch all calculations (verify that everything is ok, and find out where it starts going wrong).

Or, add some debugging output to track the progress, again with the purpose of finding out where exactly it starts going wrong.
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
Here is a helpful source code for C++ Builder programmers that allows you to manage and manipulate HTML content from C++ code, while also handling HTML events like onclick, onmouseover, ... Some objects defined and used in this source include: …
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now