Reputation: 37
I am working on a program that reads in a polynomial as input, outputs the polynomial, evaluating the polynomial, and adding two polynomials while maintaining a circularly linked list. An analysis using gdb revealed that there is a problem with the Next() member function of CircListIterator class template. What could I be doing wrong with Next()? The code and the output are reproduced below. I apologize for the long code.
main.cpp
#include <iostream>
#include "Polynomial.h"
int main() {
Polynomial poly1, poly2;
Polynomial result;
std::cout << "Enter the first polynomial (format: number_of_terms coef1 expon1 coef2 expon2 ...): ";
std::cin >> poly1;
std::cout << "Polynomial 1: " << poly1 << std::endl;
std::cout << "Enter the second polynomial (format: number_of_terms coef1 expon1 coef2 expon2 ...): ";
std::cin >> poly2;
std::cout << "Polynomial 2: " << poly2 << std::endl;
float x = 2.0; // Example value for x
std::cout << "Value of Polynomial 1 at x = " << x << " is: " << poly1.Evaluate(x) << std::endl;
std::cout << "Value of Polynomial 2 at x = " << x << " is: " << poly2.Evaluate(x) << std::endl;
result = poly1 + poly2;
std::cout << "Sum: " << result << std::endl;
std::cout << "Value of Sum Polynomial at x = " << x << " is: " << result.Evaluate(x) << std::endl;
return 0;
}
Term.h
#ifndef TERM_H
#define TERM_H
struct Term {
int coef;
int expon;
void Init(int c, int e) { coef = c; expon = e; }
};
#endif // TERM_H
ListNode.h
#ifndef LISTNODE_H
#define LISTNODE_H
template <class Type> class CircList;
template <class Type> class CircListIterator;
template <class Type>
class ListNode {
friend class CircList<Type>;
friend class CircListIterator<Type>;
template <class T>
friend std::ostream& operator<<(std::ostream& os, const CircList<T>& list);
private:
Type data;
ListNode *link;
public:
ListNode(Type element = 0, ListNode *next = nullptr) : data(element), link(next) {}
};
#endif // LISTNODE_H
CircList.h
#ifndef CIRCLIST_H
#define CIRCLIST_H
#include <iostream>
#include "ListNode.h"
template <class Type> class CircListIterator;
template <class Type>
class CircList {
friend class CircListIterator<Type>;
private:
ListNode<Type> *last;
public:
static ListNode<Type>* av;
CircList() : last(nullptr) {}
~CircList();
void RetNode(ListNode<Type>* x);
ListNode<Type> *GetNode();
ListNode<Type> *getFirst() const;
ListNode<Type> *getLast() const;
ListNode<Type> *Insert(ListNode<Type> *x, Type i);
void Delete(ListNode<Type> *x);
void Attach(const Type &item);
};
template <class Type>
ListNode<Type>* CircList<Type>::av = nullptr;
template <class Type>
std::ostream& operator<<(std::ostream& os, const CircList<Type>& list);
// Include the implementation here
#include "CircList.cpp"
#endif // CIRCLIST_H
CircList.cpp
#ifndef CIRCLIST_CPP
#define CIRCLIST_CPP
#include "CircList.h"
template <class Type>
ListNode<Type>* CircList<Type>::GetNode() {
ListNode<Type>* x;
if (!av) x = new ListNode<Type>;
else { x = av; av = av->link; }
return x;
}
template <class Type>
void CircList<Type>::RetNode(ListNode<Type>* x) {
x->link = av;
av = x;
}
template <class Type>
CircList<Type>::~CircList() {
if (last != nullptr) {
ListNode<Type>* current = last->link;
while (current != last) {
ListNode<Type>* temp = current;
current = current->link;
delete temp;
}
delete last;
}
}
template <class Type>
ListNode<Type> *CircList<Type>::getFirst() const {
if (last == nullptr) return nullptr;
else return last->link;
}
template <class Type>
ListNode<Type> *CircList<Type>::getLast() const {
return last;
}
template <class Type>
ListNode<Type> *CircList<Type>::Insert(ListNode<Type> *x, Type i) {
if (last == nullptr) {
last = new ListNode<Type>(i);
last->link = last;
return last;
}
ListNode<Type> *temp = new ListNode<Type>(i, x->link);
x->link = temp;
if (x == last) {
last = temp;
}
return temp;
}
template <class Type>
void CircList<Type>::Delete(ListNode<Type> *x) {
if (last == nullptr) {
std::cout << "The list is empty" << std::endl;
return;
}
if (last->link == last && last == x) {
delete last;
last = nullptr;
return;
}
ListNode<Type> *temp = last->link;
ListNode<Type> *prev = last;
do {
if (temp == x) {
prev->link = temp->link;
if (x == last) {
last = prev;
}
if (x == last->link) {
last->link = x->link;
}
delete x;
return;
}
prev = temp;
temp = temp->link;
} while (temp != last->link);
std::cout << "Node not found" << std::endl;
}
template <class Type>
void CircList<Type>::Attach(const Type &item) {
ListNode<Type>* newNode = new ListNode<Type>(item);
if (last == nullptr) {
last = newNode;
last->link = last;
} else {
newNode->link = last->link;
last->link = newNode;
last = newNode;
}
std::cout << "Term with Exponent " << item.expon
<< " and coefficient " << item.coef << " added. " << std::endl;
}
#endif // CIRCLIST_CPP
CircListIterator.h
#ifndef CIRCLISTITERATOR_H
#define CIRCLISTITERATOR_H
#include "CircList.h"
template <class Type>
class CircListIterator {
public:
CircListIterator(const CircList<Type> &l);
Type getData();
bool NotNull() const;
bool NextNotNull() const;
Type* First();
Type* Next();
bool IsEmpty() const;
ListNode<Type>* CurrentPosition() const;
private:
const CircList<Type> &list;
ListNode<Type> *current;
};
// Include the implementation here
#include "CircListIterator.cpp"
#endif // CIRCLISTITERATOR_H
CircListIterator.cpp
#ifndef CIRCLISTITERATOR_CPP
#define CIRCLISTITERATOR_CPP
#include "CircListIterator.h"
template <class Type>
CircListIterator<Type>::CircListIterator(const CircList<Type> &l)
: list(l), current(l.getFirst()) {}
template <class Type>
Type CircListIterator<Type>::getData() {
return current->data;
}
template <class Type>
bool CircListIterator<Type>::NotNull() const {
return current != nullptr ? true : false;
}
template <class Type>
bool CircListIterator<Type>::NextNotNull() const {
return current != nullptr && current->link != nullptr ? true : false;
}
template <class Type>
Type* CircListIterator<Type>::First() {
current = list.getFirst();
if (current && current->data.expon == -1) {
current = current->link;
if (current == list.getFirst()) {
current = nullptr;
}
}
return current ? ¤t->data : nullptr;
}
template <class Type>
Type* CircListIterator<Type>::Next() {
if (current) {
current = current->link;
if (current && (current->data.expon == -1 || current == list.getFirst())) {
current = nullptr;
}
return current ? ¤t->data : nullptr;
}
return nullptr;
}
template <class Type>
bool CircListIterator<Type>::IsEmpty() const {
const ListNode<Type>* first = list.getFirst();
return first == nullptr || (first->data.expon == -1 && first->link == first);
}
template <class Type>
ListNode<Type>* CircListIterator<Type>::CurrentPosition() const {
return current;
}
#endif // CIRCLISTITERATOR_CPP
Polynomial.h
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
#include "CircList.h"
#include "Term.h"
#include "CircListIterator.h"
class Polynomial {
friend std::istream& operator>>(std::istream&, Polynomial&);
friend std::ostream& operator<<(std::ostream&, const Polynomial&);
friend Polynomial operator+(const Polynomial&, const Polynomial&);
private:
CircList<Term> poly;
public:
Polynomial() : poly() {}
Polynomial(const Polynomial& other);
const Polynomial& operator=(const Polynomial& a);
~Polynomial();
float Evaluate(float x);
};
#endif // POLYNOMIAL_H
Polynomial.cpp
#include <iostream>
#include <cmath>
#include "Polynomial.h"
Polynomial::Polynomial(const Polynomial& other) : poly() {
CircListIterator<Term> iter(other.poly);
const Term* t = iter.First();
while (t != nullptr) {
poly.Attach(*t);
t = iter.Next();
}
}
const Polynomial& Polynomial::operator=(const Polynomial& a) {
if (this != &a) { // Check for self-assignment
// Clean up existing polynomial
CircListIterator<Term> iter(poly);
Term* t = iter.First();
while (t != nullptr) {
poly.Delete(iter.CurrentPosition());
t = iter.Next();
}
// Copy the polynomial 'a'
CircListIterator<Term> aIter(a.poly);
const Term* aTerm = aIter.First();
while (aTerm != nullptr) {
poly.Attach(*aTerm);
aTerm = aIter.Next();
}
}
return *this;
}
Polynomial::~Polynomial() {
CircListIterator<Term> iter(poly);
Term* t = iter.First();
while (t != nullptr) {
poly.Delete(iter.CurrentPosition());
t = iter.Next();
}
}
Polynomial operator+(const Polynomial& a, const Polynomial& b) {
CircListIterator<Term> Aiter(a.poly);
CircListIterator<Term> Biter(b.poly);
Polynomial c;
Term *p = Aiter.First();
Term *q = Biter.First();
Term temp;
while (p != nullptr || q != nullptr) {
if (p == nullptr) {
std::cout << "Attaching q: coef=" << q->coef << ", expon=" << q->expon << std::endl;
temp.Init(q->coef, q->expon);
c.poly.Attach(temp);
q = Biter.Next();
} else if (q == nullptr) {
std::cout << "Attaching p: coef=" << p->coef << ", expon=" << p->expon << std::endl;
temp.Init(p->coef, p->expon);
c.poly.Attach(temp);
p = Aiter.Next();
} else if (p->expon == q->expon) {
std::cout << "Summing: p->coef=" << p->coef << ", q->coef=" << q->coef << std::endl;
int sum = p->coef + q->coef;
if (sum != 0) {
temp.Init(sum, p->expon);
c.poly.Attach(temp);
}
p = Aiter.Next();
q = Biter.Next();
} else if (p->expon > q->expon) {
std::cout << "Attaching p: coef=" << p->coef << ", expon=" << p->expon << std::endl;
temp.Init(p->coef, p->expon);
c.poly.Attach(temp);
p = Aiter.Next();
} else {
std::cout << "Attaching q: coef=" << q->coef << ", expon=" << q->expon << std::endl;
temp.Init(q->coef, q->expon);
c.poly.Attach(temp);
q = Biter.Next();
}
}
return c;
}
std::istream& operator>>(std::istream& is, Polynomial& x) {
int n, coef, expon;
Term temp;
x.poly = CircList<Term>(); // Clear existing polynomial
temp.Init(0, -1); // Create head node with exponent -1
x.poly.Attach(temp);
is >> n; // Read number of terms
for (int i = 0; i < n; i++) {
is >> coef >> expon;
if (coef != 0) { // Ignore terms with zero coefficients
temp.Init(coef, expon);
x.poly.Attach(temp);
}
}
return is;
}
std::ostream& operator<<(std::ostream& os, const Polynomial& p) {
CircListIterator<Term> iter(p.poly);
const Term* t = iter.First();
if (t == nullptr) {
os << "0";
return os;
}
bool firstTerm = true;
while (t != nullptr) {
if (t->expon != -1) {
if (!firstTerm) {
os << (t->coef > 0 ? " + " : " - ");
} else {
if (t->coef < 0) {
os << "-";
}
firstTerm = false;
}
int absCoef = std::abs(t->coef);
if (absCoef != 1 || t->expon == 0) {
os << absCoef;
}
if (t->expon != 0) {
os << "x";
if (t->expon != 1) {
os << "^" << t->expon;
}
}
}
t = iter.Next();
}
return os;
}
float Polynomial::Evaluate(float x) {
float result = 0.0;
CircListIterator<Term> iter(poly);
const Term* t = iter.First();
while (t != nullptr) {
result += t->coef * std::pow(x, t->expon);
t = iter.Next();
}
return result;
}
Output:
Enter the first polynomial (format: number_of_terms coef1 expon1 coef2 expon2 ...): Term with Exponent -1 and coefficient 0 added.
3 1 2 2 1 1 0
Term with Exponent 2 and coefficient 1 added.
Term with Exponent 1 and coefficient 2 added.
Term with Exponent 0 and coefficient 1 added.
Polynomial 1: x^2 + 2x + 1
Enter the second polynomial (format: number_of_terms coef1 expon1 coef2 expon2 ...): Term with Exponent -1 and coefficient 0 added.
3 1 2 3 1 2 0
Term with Exponent 2 and coefficient 1 added.
Term with Exponent 1 and coefficient 3 added.
Term with Exponent 0 and coefficient 2 added.
Polynomial 2: x^2 + 3x + 2
Value of Polynomial 1 at x = 2 is: 9
Value of Polynomial 2 at x = 2 is: 12
Summing: p->coef=1, q->coef=1
Term with Exponent 2 and coefficient 2 added.
Summing: p->coef=2, q->coef=3
Term with Exponent 1 and coefficient 5 added.
Summing: p->coef=1, q->coef=2
Term with Exponent 0 and coefficient 3 added.
Term with Exponent 2 and coefficient 2 added.
Term with Exponent 1 and coefficient 5 added.
Term with Exponent 0 and coefficient 3 added.
Program received signal SIGSEGV, Segmentation fault.
0x000055555555657b in CircListIterator<Term>::Next (this=0x7fffffffeb10) at /home/CircListIterator.cpp:42
Upvotes: 0
Views: 79