Errors implementing class functions "no match for operator"

  • (3 Pages)
  • +
  • 1
  • 2
  • 3

44 Replies - 1232 Views - Last Post: 25 September 2013 - 10:54 PM Rate Topic: -----

#16 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3552
  • View blog
  • Posts: 11,010
  • Joined: 05-May 12

Re: Errors implementing class functions "no match for operator"

Posted 24 September 2013 - 08:33 PM

You have a buffer overrun.

Since you didn't define operator[] for your DigitList class, the compiler treats accessing leadingDigit[j] as *(leadingDigit + j). It looks like our intent was to access the j-th element in your list.

So your options are to implement operator[], or to add a getDigitAt() method on your DigitList class.

Personally, though, why are you rolling your own doubly linked list? Won't std::vector<> or std::list<> suffice?
Was This Post Helpful? 1
  • +
  • -

#17 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1335
  • View blog
  • Posts: 4,574
  • Joined: 19-February 09

Re: Errors implementing class functions "no match for operator"

Posted 24 September 2013 - 08:49 PM

Hi, and should the nDigits be taken from the i object in the copy constructor?

11	    leadingDigit = trailingDigit = new DigitList (nDigits);


This post has been edited by #define: 24 September 2013 - 09:14 PM

Was This Post Helpful? 1
  • +
  • -

#18 CoryMore  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 111
  • Joined: 26-June 12

Re: Errors implementing class functions "no match for operator"

Posted 24 September 2013 - 09:02 PM

I don't know how to implement those, I was using natural1 as an example and template. If you'd point me in a better direction, I would appreciate it.

This post has been edited by CoryMore: 24 September 2013 - 09:22 PM

Was This Post Helpful? 0
  • +
  • -

#19 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1335
  • View blog
  • Posts: 4,574
  • Joined: 19-February 09

Re: Errors implementing class functions "no match for operator"

Posted 24 September 2013 - 10:07 PM

Hi, do you want/need to use a linked list?

You could create a function to add a digit to the end of the digit list.

Don't get confused by the name struct DigitList each node just holds a digit.

This post has been edited by #define: 24 September 2013 - 10:30 PM

Was This Post Helpful? 1
  • +
  • -

#20 CoryMore  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 111
  • Joined: 26-June 12

Re: Errors implementing class functions "no match for operator"

Posted 24 September 2013 - 10:39 PM

I could multiply by 10 to add a zero, then increase the first number.
Was This Post Helpful? 0
  • +
  • -

#21 CoryMore  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 111
  • Joined: 26-June 12

Re: Errors implementing class functions "no match for operator"

Posted 24 September 2013 - 10:56 PM

Natural::Natural (const Natural& i)
{
  {
     DigitList* d = i.leadingDigit;
     DigitList* dd =leadingDigit = new DigitList (d->data,0,0);
     while ( d->next != NULL)
     {
       d = d->next;
       dd = dd->next = new DigitList(d->data,dd,0);
      }
     trailingDigit = dd;
     nDigits = i.nDigits;
     normalize();
   }
}



Above was recommended to me by a classmate, which I'm muddling through my understanding of that, but even after I add that, I'm getting a segmentation fault, just from my compiler.

Program received signal SIGSEGV, Segmentation fault.
0x610ff7fc in cygwin1!__getreent () from ~/home/Cygwin/bin/cygwin1.dll
Was This Post Helpful? 0
  • +
  • -

#22 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1335
  • View blog
  • Posts: 4,574
  • Joined: 19-February 09

Re: Errors implementing class functions "no match for operator"

Posted 24 September 2013 - 11:22 PM

When I suggested creating a function to add a digit to the end of the list, I was thinking about the copy constructor which you will need to copy a digit at a time.

With the list usually the trailing digits next pointer would be set to null or 0, and the leading digits previous pointer would be set to null or 0. When iterating through the list the end can then be found easily.

Using that convention this would be wrong in the addLeadingZero function:

  leadingDigit->prev = d;




Your timesTen function could be generalized to add a trailing digit.

void Natural::addTrailingDigit(int digit)
// adds a digit to the end of the number
{
  DigitList* d = new DigitList(digit, trailingDigit, 0); // next set to null here
  // trailingDigit->next = d; // not needed and incorrect
  trailingDigit = d;
  ++nDigits;
}




then you could use it in you timesTen function:

void Natural::timesTen()
// adds a 0 digit to the end of the number, effectively 
//  multiplying it by 10
{
  addTrailingDigit(0);
}




and you could use it in your copy constructor to add digits.
Was This Post Helpful? 1
  • +
  • -

#23 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3552
  • View blog
  • Posts: 11,010
  • Joined: 05-May 12

Re: Errors implementing class functions "no match for operator"

Posted 25 September 2013 - 05:55 AM

View Post#define, on 25 September 2013 - 02:22 AM, said:

void Natural::addTrailingDigit(int digit)
// adds a digit to the end of the number
{
  DigitList* d = new DigitList(digit, trailingDigit, 0); // next set to null here
  // trailingDigit->next = d; // not needed and incorrect
  trailingDigit = d;
  ++nDigits;
}



Actually you do need line 5. Without it, the old trailing digit node will not point to the new digit d that was just allocated.

Beyond that, #define's analysis and advice is excellent. Listen to him since he is taking a more measured approach towards teaching you what you need to learn step by step versus my "accelerated" approach of just dumping the linked list and using std::vector<> or std::list<>.
Was This Post Helpful? 2
  • +
  • -

#24 CoryMore  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 111
  • Joined: 26-June 12

Re: Errors implementing class functions "no match for operator"

Posted 25 September 2013 - 08:17 AM

I believe I get what you're saying, but I'm still having issues executing it. I think I need to do more of an if/then scenario to use the function.

natural.h
#ifndef NATURAL_H
#define NATURAL_H

#include <iostream>
#include <utility>
#include <cmath>

using namespace std;

// The natural numbers are the non-negative integers.
// This class allows for the manipulation of natural numbers of
// arbitarily large size.

class Natural
{
public:
  Natural();
  //   Natural k;
  //post:  k == 0

  Natural (unsigned i);
  //   Natural k = i;
  //post:  k == i

  Natural (const Natural&);
  ~Natural();
  Natural& operator= (const Natural&);

  Natural& operator+= (const Natural& i);
    
  Natural& operator++ ();
  Natural operator++ (int);
  Natural& operator-- ();
  Natural operator-- (int);

private:

  // Implemented as a linked list of digits, each digit should
  // be a number between 0 and 9, inclusive.
  struct DigitList {
    int data;
    DigitList* prev;
    DigitList* next;

    DigitList (unsigned d, DigitList* prv = 0, DigitList* nxt = 0)
      : data(d), prev(prv), next(nxt)
      {}
  };
  unsigned nDigits;
  DigitList* leadingDigit;
  DigitList* trailingDigit;


  void clear();
  // Empty the list

  void normalize();
  // Between operations (though not necessarily during the implementation
  // of an operation), all Natural numbers should be in "normal form" 
  //   - each digit should be between 0 and 9, inclusive
  //   - the leading digit should be non-zero, unless the number itself is
  //     zero, in which case it will have a single zero digit
  // This function scans the number, correcting any deviations from
  // normal form.

  // Internal operations for list manipulation
  void addLeadingZero();
  // adds a 0 digit to the front of the number

  void addTrailingDigit(int digit);
  //adds a digit to the end of the number
  
  void timesTen();
  // adds a 0 digit to the end of the number, effectively multiplying it by 10

  void divTen();
  // removes the trailing digit of a number, effectively dividing it by 10

  friend Natural operator+ (const Natural& i, const Natural& j);
  friend Natural operator- (const Natural& i, const Natural& j);
  friend Natural operator* (const Natural& i, const Natural& j);
  friend Natural operator/ (const Natural& i, const Natural& j);
   
  friend std::ostream&  operator<< (std::ostream& out, const Natural& k);


  // Utility functions

  void multiplyByDigit (unsigned i);
  //pre: 0 <= i < 10
  //   Natural k = k0;  k.multiplyBy(i);
  //post: k == k0 * i

  void divideBy2 ();  
  //   Natural k = k0;  j = k.divideBy2();
  //post: k0 == 2*k  || k0 = 2*k + 1

  void subtract1 ();
  //   Natural k = k0; k.subtract1();
  //Post:  k0 == k + 1

};


Natural operator+ (const Natural& i, const Natural& j);
Natural operator- (const Natural& i, const Natural& j);
Natural operator* (const Natural& i, const Natural& j);
Natural operator/ (const Natural& i, const Natural& j);
bool operator== (const Natural& i, const Natural& j);
bool operator< (const Natural& i, const Natural& j);

using namespace std::rel_ops;

std::ostream&  operator<< (std::ostream& out, const Natural& k);


#endif





natural2.cpp
#include "natural.h"


using namespace std;


// Insert your own function bodies in this file

Natural::Natural (const Natural& i)
{
  addTrailingDigit(0);  
}

Natural::~Natural()
{
    clear();
}

Natural& Natural::operator= (const Natural& i)
{
  if (this != &i)
      {
          clear();
          nDigits = i.nDigits;
          for (unsigned j = 0; j <= nDigits; ++j)
            leadingDigit[j] = i.leadingDigit[j];
      }
    return *this;
}

Natural& Natural::operator+= (const Natural& i)
{
  *this += i;
  return *this;
}

void Natural::addTrailingDigit(int digit)
{
  DigitList* d = new DigitList(digit, trailingDigit,0);
  trailingDigit->next = d;
  trailingDigit = d;
  ++nDigits;
}

void Natural::subtract1 ()
//   Natural k = k0; k.subtract1();
//Post:  k0 == k + 1
{
  for (DigitList* d = leadingDigit; d != 0; d = d->next)
    d->data -= 1;
  normalize();
}

Natural operator- (const Natural& i, const Natural& j)
{
  Natural k = i;
  k = k - j;
  return k;
}

bool operator== (const Natural& i, const Natural& j)
{
  return i == j;
}

bool operator< (const Natural& i, const Natural& j)
{
  if (i-j<0)
  {
    return (i<j);
   }
   else
   {
   return !(i<j);
   }
   
}




Errors
Program received signal SIGSEGV, Segmentation fault.
0x00403378 in Natural::addTrailingDigit(int) ()
(gdb) backstack
Undefined command: "backstack".  Try "help".
(gdb) backtrace
#0  0x00403378 in Natural::addTrailingDigit(int) ()
#1  0x00403261 in Natural::Natural(Natural const&) ()
#2  0x00403416 in operator-(Natural const&, Natural const&) ()
#3  0x00403436 in operator-(Natural const&, Natural const&) ()
#4  0x00403578 in operator<(Natural const&, Natural const&) ()
#5  0x00440318 in bool std::rel_ops::operator<=<Natural>(Natural const&, Natural const&) ()
#6  0x00401215 in factorial(Natural const&) ()
#7  0x00401cd8 in main ()


Was This Post Helpful? 0
  • +
  • -

#25 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1335
  • View blog
  • Posts: 4,574
  • Joined: 19-February 09

Re: Errors implementing class functions "no match for operator"

Posted 25 September 2013 - 03:50 PM

Hi, I think that is because with the addTrailingDigit function we are assuming that the list has been created.

In both the other constructors the list is initialized with either a 0 or integer:

Natural::Natural()
//   Natural k;
//post:  k == 0
{
  nDigits = 1;
  leadingDigit = trailingDigit = new DigitList(0);
}




So in your copy constructor you need to initialize the list. You could make another function that does that if you want.


View PostSkydiver, on 25 September 2013 - 01:55 PM, said:

Actually you do need line 5. Without it, the old trailing digit node will not point to the new digit d that was just allocated.


Of course! Thanks Skydiver.
Was This Post Helpful? 1
  • +
  • -

#26 CoryMore  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 111
  • Joined: 26-June 12

Re: Errors implementing class functions "no match for operator"

Posted 25 September 2013 - 04:00 PM

Would it work to just use the same initiator? EDIT: I realized it wouldn't be zero.

  leadingDigit = trailingDigit = new DigitList (nDigits);
  addTrailingDigit(0);



I tried that, and got an error I have no idea how to read/what it means. EDIT: Same/similar error

Program received signal SIGSEGV, Segmentation fault.
0x610ff7fc in cygwin1!__getreent ()
from ~home/Cygwin/bin/cygwin1.dll
(gdb) step
Single stepping until exit from function cygwin1!__getreent,
which has no line number information.
[Inferior 1 (process 6916) exited with code 030000000005]
(gdb) backtrace
No stack.

This post has been edited by CoryMore: 25 September 2013 - 04:12 PM

Was This Post Helpful? 0
  • +
  • -

#27 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1335
  • View blog
  • Posts: 4,574
  • Joined: 19-February 09

Re: Errors implementing class functions "no match for operator"

Posted 25 September 2013 - 04:50 PM

An object/variable of DigitList is not a list but just a digit. So here you make a new digit with the value of nDigits.

leadingDigit = trailingDigit = new DigitList (nDigits);



To initialize the list with a dummy value the number of digits is set to 1 and a digit with a value of 0 is created as in the constructor with no parameters. The normalize function should remove leading zeroes and a leading digit of 0 will not affect the number.

Notice if you create an initialize list function it could be used in several places.


After you initialize the list then you can think about copying the data from the other list.
Was This Post Helpful? 1
  • +
  • -

#28 CoryMore  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 111
  • Joined: 26-June 12

Re: Errors implementing class functions "no match for operator"

Posted 25 September 2013 - 05:22 PM

I see, so after I initialize the list

  nDigits = 1;
  leadingDigit = trailingDigit = new DigitList(0);
  addTrailingDigit(0);
  normalize();



Then I need to import the data from the other list. Would I do that using the code?

for (unsigned j = 0; j < nDigits; ++j)
 
      leadingDigit[j] = i.leadingDigit[j];


Was This Post Helpful? 0
  • +
  • -

#29 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1335
  • View blog
  • Posts: 4,574
  • Joined: 19-February 09

Re: Errors implementing class functions "no match for operator"

Posted 25 September 2013 - 06:15 PM

Hi, yes you can do something like that but you would need to create new digits.

And you cannot access the list like leadingDigit[j], (it could be done if the [] operator was defined for that, but it is not as efficient as iterating using pointers).

I have changed my mind slightly and was thinking you could create and initialize the list more directly.

You have your copy constructor :

Natural::Natural (const Natural& i)
{

}



You could initialize the list with the first value in the list in i. Remember here the lists should be a least one digit in size.

Natural::Natural (const Natural& i)
{
  leadingDigit = trailingDigit = new DigitList(i.leadingDigit->data, 0, 0);

}




With a for loop you can get the rest of the list and use the addTrailingDigit function to create the new digits.

Natural::Natural (const Natural& i)
{
  DigitList* d;
  leadingDigit = trailingDigit = new DigitList(i.leadingDigit->data, 0, 0);

  // use for loop with pointer 
  // to add digits to list

  // update nDigits
}



I'll let you have a little look at that and see how you get on.

'

This post has been edited by #define: 25 September 2013 - 06:18 PM

Was This Post Helpful? 0
  • +
  • -

#30 CoryMore  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 111
  • Joined: 26-June 12

Re: Errors implementing class functions "no match for operator"

Posted 25 September 2013 - 06:48 PM

I tried two different things, but both got me in an infinate loop.

  DigitList* d;
  leadingDigit = trailingDigit = new DigitList(i.leadingDigit->data, 0, 0);
  while (d !=NULL)
  {
  addTrailingDigit(0);
  }
  nDigits = nDigits; 



And on this, I know why it gave me an infinite loop, because I'm incriminating nDigits, but I couldn't think of another integer to compare j to.

  DigitList* d;
  leadingDigit = trailingDigit = new DigitList(i.leadingDigit->data, 0, 0);
  for (int j=0; j < nDigits; j++)
  {
  addTrailingDigit(0);
  }
  nDigits = nDigits;



I thought maybe to take the value of nDigits first, and make it a variable and set that.
  DigitList* d;
  leadingDigit = trailingDigit = new DigitList(i.leadingDigit->data, 0, 0);
  int end = nDigits;
  for (int j=0; j < end; j++)
  {
  addTrailingDigit(0);
  }
  nDigits = nDigits; 



Still an infinite loop though.

stackdump
$ ./lottery.exe.stackdump
./lottery.exe.stackdump: line 1: Exception:: command not found
./lottery.exe.stackdump: line 3: pid: command not found
./lottery.exe.stackdump: line 5: Stack: command not found
./lottery.exe.stackdump: line 6: Frame: command not found
./lottery.exe.stackdump: line 7: syntax error near unexpected token `('
./lottery.exe.stackdump: line 7: `00288BA8  610F9B7E  (00000000, 00000000, 00103'00, 00000004)


This post has been edited by CoryMore: 25 September 2013 - 07:21 PM

Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3