Why my operator* acts illogical?

Pages: 12
Hi there
I have this code which has strange output for the result of operator*
The output is totally illogical, do you have any idea?
It should be about AddOneTerm or Print I guess:



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
 include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <vector>
using namespace std;


typedef struct Node
{
	double  cof;      // coefficient 
	int     deg;      // degree
} Node;

class CPolynomial
{
public:
	CPolynomial();
	CPolynomial(const string& file);
	~CPolynomial();
	CPolynomial operator*(const CPolynomial &right);
	CPolynomial& operator=(const CPolynomial &right);
	void Print() const;

private:
	void ReadFromFile(string file);
	void AddOneTerm(Node term);

private:
	list<Node> m_Polynomial;
};



int main()
{
	CPolynomial p1("P3.txt");
	CPolynomial p2("P4.txt");
	CPolynomial p3;
	p1.Print();
	p2.Print();

	p3 = p1*p2;
	p3.Print();

	system("pause");
	return 0;
}

CPolynomial::CPolynomial()
{
	Node term;
	term.cof = 0;
	term.deg = 0;
	AddOneTerm(term);
}

CPolynomial::~CPolynomial()
{
	m_Polynomial.clear();
}

CPolynomial::CPolynomial(const string& file)
{
	ReadFromFile(file);
}

CPolynomial CPolynomial:: operator*(const CPolynomial &right)
{
	CPolynomial result;

	result.m_Polynomial = m_Polynomial;

	Node term;
	Node termR;
	Node temp;
	for (list<Node>::const_iterator it = m_Polynomial.begin(); it != m_Polynomial.end(); ++it)
	{
		for (list<Node>::const_iterator itR = right.m_Polynomial.begin(); itR != right.m_Polynomial.end(); ++itR)
		{
			term = *it;
			termR = *itR;

			temp.cof = termR.cof* term.cof;
			temp.deg = termR.deg + term.deg;

			cout << temp.cof << "x^" << temp.deg << endl;

			result.AddOneTerm(term);
		}
	}
	return result;
}

CPolynomial& CPolynomial:: operator=(const CPolynomial &right)
{

	this->m_Polynomial = right.m_Polynomial;
	return *this;
}

void CPolynomial::Print() const
{
	list<Node>::const_iterator it;

	for (it = m_Polynomial.begin(); it != m_Polynomial.end(); it++)
	{
		if (it->cof == 0)
		{
			;
		}
		else
		{
			if (it->cof > 0)
			{
				if (it != m_Polynomial.begin()) // if 'it' is not the first term, '+' is not necessary
					cout << "+";
			}
			cout << it->cof;
			if (it->deg != 0)
				cout << "x^" << it->deg;
		}
	}
	cout << endl;
}

void CPolynomial::ReadFromFile(string file)
{
	Node term;
	fstream MyFile;
	string p;
	int num;

	MyFile.open(file);

	if (!MyFile.is_open())
	{
		cerr << "Unable to open input file" << endl;
		exit(EXIT_FAILURE);
	}
	else
	{
		MyFile >> p >> num;

		std::list<Node>::iterator it = m_Polynomial.begin();

		for (int i = 0; i < num; i++)
		{
			MyFile >> term.deg >> term.cof;

			m_Polynomial.push_back(term);
		}
		MyFile.close();
	}

}

void CPolynomial::AddOneTerm(Node term)
{
	std::list<Node>::iterator it;
	for (it = m_Polynomial.begin(); it != m_Polynomial.end();)
	{
		if (term.deg < it->deg)
		{
			++it;
			continue;
		}
		else if (term.deg == it->deg) // if degree is same, coefficient is added directly 
		{
			it->cof += term.cof;
			return;
		}
		else // if the added degree is big than current term of m_polynomial,
			// justify the relationship of degree with the next term
			// if smaller than next, then 'insert'
			// if equal to the next term, then add the cof to next term
		{
			std::list<Node>::iterator next_it;
			next_it = ++it;
			if (next_it != m_Polynomial.end())
			{
				if (term.deg < it->deg)
				{
					m_Polynomial.insert(next_it, term);
					return;
				}
				else
				{
					it->cof += term.cof;
					return;
				}
			}
			else
			{
				m_Polynomial.push_back(term);
			}
			return;
		}
	}

}



Output
1
2
3
4
5
6
7
2x^1-3x^4     (P1)
4x^1-3x^4     (P2)
8x^2
-6x^5
-12x^5
9x^8
6x^1-9x^4    (P1*P2)


P3
1
2
3
P 2
1 2
4 -3


P4
1
2
3
P 2
1 4
4 -3

Last edited on
Hi,
> How can I use cof and deg in constructors of class? I get errors if I use m_Polynomial->cof or m_Polynomial.cof

Look at this :
list<Node> m_Polynomial;

It is a (std::list) variable, not a (Node) variable. A (std::list) is a container, and a container is pretty essentially a normal array (it acts like an array). But it does not act completely like a pointer (it is actually a non-pointer variable it can't be dereferenced). So these two access approaches you provided will not work. But you can surely take advantage of it acting like an array, for example :
1
2
m_Polynomial[0].cof = 5; // access the 1st element
m_Polynomial[4].cof = 9; // access the 5th element 


More info :
http://www.cplusplus.com/reference/list/list/
.cpp file

Lines 4-5: These lines do nothing.

Lines 10-11: These variables go out of scope when the constructor exits. The values are lost.

Line 16: A friend declaration does not belong inside your constructor.

Your questions:
1) m_polynomial is a std::list. You need to create a Node. Set the cof and deg values in the node. Then do a push_back to add the node to your list.

2) Four different ways of creating a CPolynominal object. default, from file, specific deg and cof (not sure what n is), and vectors of coefficients and degrees.

3) No. For each entry in the file, set the values into a a Node struct, then push the Node struct onto the list.

4) Good practice. Might want to derive a class from CPolynominal in the future. Eliminates the need to change it later.
Last edited on
@closed account

But you can surely take advantage of it acting like an array, for example :
1
2
m_Polynomial[0].cof = 5; // access the 1st element
m_Polynomial[4].cof = 9; // access the 5th element  



std::list does not operate like an array and does not support the [] operator.

> std::list does not operate like an array and does not support the [] operator.
How boring. I never thought there would be a container that doesn't provide random access like std::list. Maybe implementing the [] operator is not cost-effective I guess?
closed account wrote:
. Maybe implementing the [] operator is not cost-effective I guess?

Correct. std::list is usually implemented as a linked list. Implementing an [] operator would imply traversing the linked list until the specified entry was found.
@AbstractionAnon

I'm sorry my knowledge is not enough to understand your answer.

*You said I create a Node, isn't it my Node?
typedef struct Node
{
double cof; // coefficient
int deg; // degree
} Node;

*And you mean push_back like this? m_Polynomial.push_back(Node);

*what is a specific deg and cof? Is it some technical word?

I am sorry I look stupid; I read all the tutorial of the website but still have too many problems.
You said I create a Node, isn't it my Node?

Yes, that's a declaration of a Node (and an instance also called Node).

And you mean push_back like this? m_Polynomial.push_back(Node);

Yes, assuming you've set coef and deg values into Node.

*what is a specific deg and cof? Is it some technical word?

All I meant by "specific" was a constructor where you passing in coef and deg.
1
2
3
  double deg[2] = { 1.0, 3.0};
  double coef[2] = { 5.0, 7.0};
  CPolynominal a (coef, deg, 2);  //  Note values are passed as arrays  

Since they are being passed in as pointers and there is a value n (count?), i'm presuming the arguments are arrays of size n.

Last edited on
Thanks for helping me @AbstractionAnon

.h File:
1
2
3
4
5
6
7
//as it was
class CPolynomial
{
private:
	list<Node> m_Polynomial;
	Node Node;  //this is added
//as it was 


From .cpp file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

CPolynomial::CPolynomial()
{
	Node.cof = 0;
	Node.deg = 0;
	m_Polynomial.push_back(Node);
}
CPolynomial::CPolynomial(const string& file)
{
	fstream MyFile;
	string p;
	int num;
	MyFile.open("file");
	MyFile >> p >> num;
	cout << "p=" << num;
	for (int i = 0; i < num; i++)
	{
		MyFile >> Node.deg>> Node.cof;
		m_Polynomial.push_back(Node);
	}
}



Is it how you mean it?


But why this way of using cof and deg doesn't work for operator functions?
I thought you weren't supposed to change the .h file?

Line 6 (.h) Node is not needed as a member of CPolynomial. Node should be a local variable where needed. Suggestion: When you instantiate Node, use something other than Node as your variable name. Using a variable name which is the same as your typedef name is confusing.

.cpp file:
Your first constructor is fine.
Regarding the second constructor:
Line 13: The name of the file is being passed in as an argument. You're not using it.
Line 14: I'm presuming from this line that the file has an initial line that specifies the number of entries in the file, rather than reading until eof.

But why this way of using cof and deg doesn't work for operator functions?

I'm not sure I understand your question.
Your operator overloads all take a right hand side of another CPolynominal instance.

Lines 20-25 of the original .h file. Did you add these lines? They're not going to compile.

edit: The class declaration for CPolynominal has a ReadFromFile() function. Pretty sure the second constructor is meant to call ReadFromFile(). Just move your existing logic from your second constructor into the ReadFromFile() functionn.
Last edited on
@AbstractionAnon

I thought you weren't supposed to change the .h file?


I am not but I had no other idea

I'm presuming from this line that the file has an initial line that specifies the number of entries in the file, rather than reading until eof.


You are right, my bad. I should have informed.

Lines 20-25 of the original .h file. Did you add these lines?


I'm sorry, a mistake.

my .cpp now is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <vector>
#include "CPolynomial.h"
using namespace std;


CPolynomial::CPolynomial()
{
	Node term;
	term.cof = 0;
	term.deg = 0;
	m_Polynomial.push_back(term);
}
CPolynomial::CPolynomial(const string& file)
{
	// Node term;          // if I define it here instead of in the class body, I get error: polynomial has no "term" member
	fstream MyFile;
	string p;
	int num;
	MyFile.open(&file);  //Error: this declaration has no storage class or type specifier
	MyFile >> p >> num;
	cout << "p=" << num;
	for (int i = 0; i < num; i++)
	{
		MyFile >> term.deg>> term.cof;
		m_Polynomial.push_back(term);
	}
}

CPolynomial::CPolynomial::CPolynomial(double *cof, double *deg, int n)
{

	//Not sure what to do
}

CPolynomial::CPolynomial(const vector<double>& cof, const  vector<double> & deg)
{
	//Not sure what to do
}

CPolynomial::~CPolynomial()
{
	m_Polynomial.clear();
}

CPolynomial operator+(const CPolynomial &right)
{
	
	if (term.deg == right.term.deg)
	{
		CPolynomial temp;
		temp.term.cof = term.cof + right.term.cof;
		return temp;
	}
}
CPolynomial operator-(const CPolynomial &right)
{
	if (term.deg == right.term.deg)
	{
		CPolynomial temp;
		temp.term.cof = term.cof - right.term.cof;
		return temp;
	}
}
CPolynomial operator*(const CPolynomial &right)
{
	CPolynomial temp;
	temp.term.cof = term.cof * right.term.cof;
	temp.term.deg = term.deg + right.term.deg;
	return temp;
}
Cpolynomial& operator=(const CPolynomial &right)
{
	// Node term;          // if I define it here instead of in the class body, I get error: polynomial has no "term" member
	term.cof = right.term.cof;
	term.deg = right.term.deg;
	return *this;
}
void CPolynomial::Print() const
{
	
}

void CPolynomial::ReadFromFile(string file)
{

}

void CPolynomial::AddOneTerm(Node term)
{

}
Last edited on
Line 19: Your comment seems backwards. You should be fine if you define term here. If term is commented out, then you should get the error "term is not a member of the class" (or similar).

Lines 19-30: See the edit in my previous post regarding ReadFromFile().

Lines 15,29: Your class declaration has a function named AddOneTerm(). You should be calling that instead of doing a push_back() directly. Move your psuh_back to AddOneTerm().

Line 33: You're being passed two arrays. One of coefficients and one of degrees, plus a count of how many entries are in the arrays. You need to iterate through the arrays setting a local copy of term to the n'th pair, then call AddOneTerm() for each iteration.

Line 39: This is nearly identical to the previous constructor, except that you're being passed two vectors (one of coefficients, one of degrees). Logic is essentially the same as the previous constructor. Iterate through the vectors, set a local term, call AddOneTerm() for each iteration.

Line 50-58: This is more complicated than what you have. You have two lists. this->m_polynominal and right.m_polynominal. You need to iterate through each list finding matching terms (degrees), then add the two terms (coefficients). Line 58: Keep in mind that a term on the right may not exist on the left and visa-versa.

Lines 60-67: Ditto, except the operation is subtraction.

Line 68-74: Ditto.

Line 78-79: You want to replace the list on the left.
 
  this->m_polynominal = right.m_polynominal;

Last edited on
@AbstractionAnon Thanks for all your help; I can't believe this homework is proceeding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <vector>
#include "CPolynomial.h"
using namespace std;


CPolynomial::CPolynomial()
{
	Node term;
	term.cof = 0;
	term.deg = 0; 
	AddOneTerm(term);
}
CPolynomial::CPolynomial(const string& file)
{
        Node term;
	fstream MyFile;
	string p;
	int num;                     //How can I reach it in operator functions?
	MyFile.open(file);
	MyFile >> p >> num;
	cout << "p=" << num;
	ReadFromFile(file);
}

CPolynomial::CPolynomial::CPolynomial(double *cof, double *deg, int n)
{
	Node term;

	for (int i = 0; i < n; i++)
	{
		term.cof = *cof;
		term.deg = *deg;

		AddOneTerm(term);
	}
}

CPolynomial::CPolynomial(const vector<double>& cof, const  vector<double> & deg)
{
	Node term;

	if (cof.size != deg.size)
	{
		cout << "Invalidate input!" << endl;
	}
	else
	{
		//??  //Sorry still have problem
	}

}

CPolynomial::~CPolynomial()
{

	m_Polynomial.clear();
}

CPolynomial operator+(const CPolynomial &right)  /*there are tons of methods for these operators  but I am not sure which is proper for my case*/
{
	for (int i = 0; !EOF; i++)  
	{
		if (deg.right = deg.term)
		{
			this->m_Polynomial += right.m_Polynomial;
		}
		else
		{
			this->m_Polynomial
		}
	}
	return *this;
}

CPolynomial operator-(const CPolynomial &right)
{

	for (int i = 0; !EOF; i++) 
	{
		if (deg.right = deg.term && deg.right != NULL)
		{
			this->m_Polynomial -= right.m_Polynomial;
		}
		else
		{
			this->m_Polynomial;
		}
	}
	return *this;

}

CPolynomial operator*(const CPolynomial &right)
{
	this->deg += right.deg;
	this->cof *= right.cof;

	free(this->cof);

	return *this;
}


Cpolynomial& operator=(const CPolynomial &right)
{
	this->m_polynominal = right.m_polynominal;
	return *this;
}


void CPolynomial::Print() const
{
	for (int i = 0; i < num; i++)
	{
		if (term.cof[i] > 0 && term.deg[i] != 0)
		{
			cout << "+" << term.cof[i] << "x^" << term.deg[i];
		}
		if (term.cof[i] > 0 && term.deg[i] == 0)
		{
			cout << "+" << term.cof[i];
		}
		if (term.cof[i] < 0 && term.deg[i] != 0)
		{
			cout << cof[i] << "x^" << term.deg[i];
		}
		if (term.of[i] < 0 && term.deg[i] == 0)
		{
			cout << term.cof[i];
		}
	}
	cout << endl;
}

void CPolynomial::ReadFromFile(string file)
{
	for (int i = 0; i < num; i++)
	{
		MyFile >> term.deg >> term.cof;
		AddOneTerm(term);
	}
}

void CPolynomial::AddOneTerm(Node term)
{
	m_Polynomial.push_back(term);
}



A sample text file:

1
2
3
4
5
6
7
8
9
P 8
0 2
5 -3
12 5
2 6
5 7
3 -4
2 9
2 2
Last edited on
or maybe like this??

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CPolynomial::CPolynomial(const vector<double>& cof, const  vector<double> & deg)
{
	Node term;

	if (cof.size != deg.size)
	{
		cout << "Invalidate input!" << endl;
	}
	else
	{
		for (int i = 0; i < sizeof(cof); i++)
		{
			cof.push_back[i];
			cof.push_back[i];

			AddOneTerm(term);
		}
	}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
CPolynomial::CPolynomial(const vector<double>& cof, const  vector<double> & deg)
{
	Node term;

	if (cof.size() != deg.size()) // Note: size is a function (wihout () you compare the function pointer)
	{
		cout << "Invalidate input!" << endl;
	}
	else
	{
		for (int i = 0; i < cof.size(); i++) //sizeof(cof) doesn't make sense: You get the size of the vector object not the number of items.
		{
			//??? cof.push_back[i];
			//??? cof.push_back[i];

			term.cof = cof[i];
			term.deg = deg[i];

			AddOneTerm(term);
		}
	}

}
@coder777

Actually me myself don't believe in my code, just I don't get how should it be.


What about rest of the code? does it make sense?
You've made good progress.

I've been proceeding on the implicit assumption that input to the constructors (file, array, vector) was in order by degree (either ascending or descending) and that you want to represent the polynomial in it's simplest form. Perhaps that is not a requirement.

It might be a reasonable assumption since one normally writes polynomials from left to right in decreasing order of degree. A std::map might have made more sense for this assignment, but we're stuck with std::list.

However, your sample input file belies this assumption. Looking at the sample input file, you can see three input terms of degree 2, two of degree 5 and in general, not in any particular order.

Representing CPolynomial in it's simplest form is going to make AddOneTerm() more complex. AddOneTerm() is going to have to navigate the list and determine if there is already a term of the specified degree, and if so, combine the term being added with the specified term. If there is not an existing term of the specified degree, the AddOneTerm() should insert the new term at the correct position in the list. See list::insert.

cpolynomial.h
----------------
line 4,14,15: deg is defined in Node as an int, which makes sense. However, in the array and vector constructors, deg is a double. Is this really how the supplied header file is? This is inconsistent. If this is how it is supplied in the header, we can deal with it. Just wanted to double check that this wasn't something you messed with.

line 22: CPolynomial capitalization is incorrect. I assume this is your typo and the provided header file is correct.

cpolynomial.cpp
-------------------
Lines 6-7:
using namespace std; needs to be before #include "cpolynomial.h" since CPolymonial uses list<> without std::

Line 29: You have an extraneous CPolynomial::

Line 35-36: Every iteration of the array is adding the same first element of each array. You want to set term to the n'th degree and coefficient.
1
2
3
4
5
6
7
8
9
CPolynomial::CPolynomial  (double *cof, double *deg, int n)
{   Node term;

	for (int i = 0; i < n; i++)
	{   term.cof = cof[i];
		term.deg = (int)deg[i];  // cast double to int
		AddOneTerm(term);
	}
}


Line 52: This is essentially identical to the code above for arrays of doubles.

Line 63-77: Your operators need some work. From my previous post:
This is more complicated than what you have. You have two lists. this->m_polynominal and right.m_polynominal. You need to iterate through each list finding matching terms (degrees), then add the two terms (coefficients). Keep in mind that a term on the right may not exist on the left and visa-versa.


Line 139-146: Some problems with ReadFromFile()
"file" is passed in as an argument, but is not used. The implication is that ReadFromFile() should open the file, rather than opening it in the constructor.

"num" is used, but not passed in. Again, the implication is that ReadFromFile should read the header line.

"myfile" is used, but not defined.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void CPolynomial::ReadFromFile(string file)
{   fstream MyFile;
	string p;
	int num;            
    Node term;         
	
	MyFile.open(file);
	if (! MyFile.is_open())
	{   cout << "Unable to open input file" << endl;
	    exit (EXIT_FAILURE);
	}
	MyFile >> p >> num;
	cout << "p=" << num;	
	for (int i = 0; i < num; i++)
	{   MyFile >> term.deg >> term.cof;
		AddOneTerm(term);
	}
}


edit:
Lines 63,79,97,108: Your operators need to be qualified by CPolynomial::

Line 108: CPolynomial capitalization error on the return type.

Several problems with your print function:
Line 117: You need to walk the list using an iterator.
Line 117: num is not defined.

Line 119,121,123,125,127,129,131,133: deg and cof are simple members of node and are not arrays. You can't index them.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void CPolynomial::Print() const
{   list<Node>::const_iterator citer;
    Node    term;
    
    //  Need to iterate through the list
	for (citer=m_Polynomial.begin(); citer!=m_Polynomial.end(); citer++)
	{   term = *citer;  // Making a copy of Node for clarity
	    if (term.cof == 0)
	    {   //  Skip this term
	    }
	    else
	    {   if (term.cof > 0)
	            cout << "+";
            cout << term.cof;	            
	        if (term.deg != 0)
		        cout << "x^" << term.deg;        
		}
	}
	cout << endl;
}





Last edited on
@AbstractionAnon Thanks God you're back :)))

navigate the list and determine if there is already a term of the specified degree,...


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void CPolynomial::AddOneTerm(Node term)
{
	for (int i = 0; i < m_Polynomial.size(); i++)
	{
		std::list<Node>::iterator it = m_Polynomial.begin();

		while (it != m_Polynomial.end()) {
			if (it->deg < term.deg)
			{
				m_Polynomial.insert(it, term);
			}
			if (it->deg == term.deg)
			{
				it->cof += term.cof;
			}
		}
	}
}






deg is defined in Node as an int, which makes sense. However, in the array and vector constructors, deg is a double


Yes it is how it was, but I believe it was a typo. I think I should assume deg is int and cof is double.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <vector>
using namespace std;
#include "CPolynomial.h"


CPolynomial::CPolynomial()
{
	Node term;
	term.cof = 0;
	term.deg = 0; 
	AddOneTerm(term);
}

CPolynomial::CPolynomial(const string& file)
{
	ReadFromFile(file);
}

CPolynomial::CPolynomial(double *cof, int *deg, int n)
{
	Node term;

	for (int i = 0; i < n; i++)
	{
		term.cof = cof[i];
		term.deg = deg[i];

		AddOneTerm(term);
	}
}

CPolynomial::CPolynomial(const vector<double>& cof, const  vector<int> & deg)
{
	Node term;

	if (cof.size() != deg.size())
	{
		cerr << "Invalidate input!" << endl;
	}
	else
	{
		for (unsigned int i = 0; i < cof.size(); i++)
		{
			term.cof = cof[i];
			term.deg = deg[i];
			AddOneTerm(term);
		}
	}

}

CPolynomial::~CPolynomial()
{

	m_Polynomial.clear();
}

CPolynomial CPolynomial:: operator+(const CPolynomial &right)
{
	Node term;
	
	for (unsigned int i = 0; i < m_Polynomial.size(); i++)
	{
		std::list<Node>::iterator it = m_Polynomial.begin();

		while (it != m_Polynomial.end())
		{
			if (it->deg == term.deg)
			{
				it->cof += term.deg;
			}
			if (it->deg < term.deg)
			{
				m_Polynomial.insert(it, term);
			}
			if (it->deg > term.deg)
			{
				m_Polynomial.push_back(term);
			}

		}
	}
}

CPolynomial CPolynomial:: operator-(const CPolynomial &right)
{
	Node term;
	for (unsigned int i = 0; i < m_Polynomial.size(); i++)
	{
		std::list<Node>::iterator it = m_Polynomial.begin();

		while (it != m_Polynomial.end())
		{
			if (it->deg == term.deg)
			{
				it->cof -= term.deg;
			}
			if (it->deg < term.deg)
			{
				term.cof = -term.cof;
				m_Polynomial.insert(it, term);
			}
			if (it->deg > term.deg)
			{
				term.cof = -term.cof;
				m_Polynomial.push_back(term);
			}

		}
	}
}

CPolynomial CPolynomial:: operator*(const CPolynomial &right)
{
	Node term;
	for (unsigned int i = 0; i < m_Polynomial.size(); i++)
	{
		std::list<Node>::iterator it = m_Polynomial.begin();

		while (it != m_Polynomial.end())
		{
			it->cof *= term.cof;
			it->deg += term.deg;
		}
	}
}


CPolynomial CPolynomial:: &operator=(const CPolynomial &right)
{
	this->m_polynominal = right.m_polynominal;
	return *this;
}


void CPolynomial::Print() const
{
	Node term;

	for (unsigned int i = 0; i < m_Polynomial.size(); i++)
	{
		std::list<Node>::iterator it = m_Polynomial.begin();

		while (it != m_Polynomial.end())
		{
			term = *it;
			if (term.cof == 0)
			{
				//  Skip this term
			}
			else
			{
				if (term.cof > 0)
					cout << "+";
				cout << term.cof;
				if (term.deg != 0)
					cout << "x^" << term.deg;
			}
			cout << endl;
		}
	}
}

void CPolynomial::ReadFromFile(string file)
{
	
	fstream MyFile;
	string p;
	int num;
	Node term;


	MyFile.open(file);
	if (!MyFile.is_open())
	{
		cout << "Unable to open input file" << endl;
		exit(EXIT_FAILURE);
	}
	MyFile >> p >> num;
	cout << "p=" << num;
	for (int i = 0; i < num; i++)
	{
		MyFile >> term.deg >> term.cof;
		AddOneTerm(term);
	}
}

void CPolynomial::AddOneTerm(Node term)
{
	for (unsigned int i = 0; i < m_Polynomial.size(); i++)
	{
		std::list<Node>::iterator it = m_Polynomial.begin();

		while (it != m_Polynomial.end()) 
		{
			if (it->deg < term.deg)
			{
				m_Polynomial.insert(it, term);
			}
			if (it->deg == term.deg)
			{
				it->cof += term.cof;
			}
			if (it->deg > term.deg)
			{
				m_Polynomial.push_back(term);
			}
		}
	}
}


Last edited on
@AbstractionAnon
But still those 2 constructors are not clear for me.
A few comments on AddToTerm().
1) You don't need both the for loop and the while loop. You have two choices. Use the iterator in your for loop (see Print) and get rid of the while loop, or get rid of the for loop and after line 15, simply increment your iterator.
2) Line 10: Once you've inserted term, you should return. No point in continuing.
3) Ditto for finding a match at line 14.
4) You've overlooked what happens if you don't find a < or = condition.
After the while loop, you should do a push_back to add term to the end of the list.
5) You're ordering the list in ascending order by degree. That's fine, but you might want to consider the impact on print(). print() is going to print the smallest degree first.

I think I should assume deg is int and cof is double.

Unless you get confirmation from your instructor it is a typo, I would not change it.
As I said, we can deal with it. It's a simple matter of a cast to convert the double to an int where needed.

operator +
Ditto item #1 above regarding for and while loops.
Line 11: term is undefined.
You need two iterators. One for the left hand side and one for the right hand side.
You will need to walk both lists in parallel.
Line 13,17,22: You never set term.

operator -
All the same comments as operator +

operator *
When multiplying two polynomials, you want to multiple each term of the left hand side by each term on the right hand side. Keep in mind that the multiplication will result in a different degree which may or may not already exist on the left hand side. Degree 0 times degree 0 is a special case. Suggestion: Calculate a temporary term, delete the left hand term, the call AddOneTerm() to insert the new term.

operator =
Line 76: Capitialization error.

Print()
Same comments about not needing both for and while loops. I provided you the code using only a for loop. See comment #5 regarding AddToTerm().

But still those 2 constructors are not clear for me.

In the array constructor, you're being passed an array of degrees and an array of coefficients.
You iterate through the arrays building a Node for each pair from the arrarys, then call AddOneTerm() to add the Node to the list. Visualize this as the input file (minus the first line) stored in two arrays of doubles. The third argument n is the number of entries in the arrays.

The vector constructor is almost identical. You're passed two vectors. One vector of degrees, one vector of coefficients. For each pair from the vectors, you build a Node and call AddToTerm().

If that's not clear you're going to have to tell me what is not clear.

Do you have, or has the instructor provided a main function to test your class?

Pages: 12