Basic polynomial reading using linked lists - c++

Ok, after failing to read a polynomial, I'm trying first a basic approach to this.
So i have class polinom with function read and print:
#ifndef _polinom_h
#define _polinom_h
#include <iostream>
#include <list>
#include <cstdlib>
#include <conio.h>
using namespace std;
class polinom
{
class term
{
public:
double coef;
int pow;
term(){
coef = 0;
pow = 0;
}
};
list<term> poly;
list<term>::iterator i;
public:
void read(int id)
{
term t;
double coef = 1;
int pow = 0;
int nr_term = 1;
cout << "P" << id << ":\n";
while (coef != 0) {
cout << "Term" << nr_term << ": ";
cout << "coef = ";
cin >> coef;
if (coef == 0) break;
cout << " grade = ";
cin >> pow;
t.coef = coef;
t.pow = pow;
if (t.coef != 0) poly.push_back(t);
nr_term++;
}
}
void print(char var)
{
for (i=poly.begin() ; i != poly.end(); i++ ) { //going through the entire list to retrieve the terms and print them
if (poly.size() < 2) {
if (i->pow == 0) //if the last term's power is 0 we print only it's coefficient
cout << i->coef;
else if (i->pow == 1) {
if (i->coef == 1)
cout << var;
else if (i->coef == -1)
cout << "-" << var;
else
cout << i->coef << var;
}
else
cout << i->coef << var << "^" << i->pow; //otherwise we print both
}
else {
if (i == poly.end()) { // if we reached the last term
if (i->pow == 0) //if the last term's power is 0 we print only it's coefficient
cout << i->coef;
else if (i->pow == 1)
cout << i->coef << var;
else
cout << i->coef << var << "^" << i->pow; //otherwise we print both
}
else {
if (i->coef > 0) {
if (i->pow == 1)//if the coef value is positive
cout << i->coef << var << " + "; //we also add the '+' sign
else
cout << cout << i->coef << var << "^" << i->pow << " + ";
}
else {
if (i->pow == 1)//if the coef value is positive
cout << i->coef << var << " + "; //we also add the '+' sign
else
cout << cout << i->coef << var << "^" << i->pow << " + ";
}
}
}
}
}
};
#endif
Well, it works when reading only one term but when reading more the printed coefficients are some random values and also after the last term it print '+' or '-' when it shouldn't.
So any idea what's wrong?
Thanks!
FINAL UPDATE
Ok, i made it work perfectly by modifying Bill's code so thanks a lot Bill and everyone else who commented or answered!
Here's the final print function:
void print(char var)
{
list<term>::iterator endCheckIter;
for (i=poly.begin() ; i != poly.end(); i++ )
{
//going through the entire list to retrieve the terms and print them
endCheckIter = i;
++endCheckIter;
if (i->pow == 0)
cout << i->coef;
else if (i->pow == 1)
cout << i->coef << var;
else
cout << i->coef << var << "^" << i->pow;
if (endCheckIter != poly.end()) {
if (endCheckIter->coef > 0)
cout << " + ";
else {
cout << " - ";
endCheckIter->coef *= -1;
}
}
}
}

if (i == poly.end()) { // if we reached the last term
This comment shows your error. For any given collection of items, items.end() returns the entry after the last item.
For instance, say I have a 5-item std::vector:
[0] [1] [2] [3] [4]
Then begin() points to:
[0] [1] [2] [3] [4]
/\
And end() points to:
[0] [1] [2] [3] [4] []
/\
Your for loop, it looks like:
for (i=poly.begin() ; i != poly.end(); i++ )
Note that comparing i to poly.end() happens before iter is used. As soon as i == poly.end(), you're done.
Your code inside of if (i == poly.end()) { will never be executed because this can never be true.
You can test for the end using the following:
// get access to the advance function
#include <iterator>
....
std::list<term>::iterator endCheckIter = i;
std::advance(endCheckIter, 1);
if (endCheckIter == poly.end())
{
...
}
But a simpler way might be:
std::list<term>::iterator endCheckIter = i;
++endCheckIter;
if (endCheckIter == poly.end())
{
...
}
Edit:
I'm not sure why you're getting garbage. Add in your missing braces and handle the non-end case, and everything works here:
void print(char var)
{
list<term>::iterator endCheckIter;
for (i=poly.begin() ; i != poly.end(); i++ )
{ // <- MISSING BRACE
//going through the entire list to retrieve the terms and print them
endCheckIter = i;
++endCheckIter;
cout << i->coef << var << "^" << i->pow; // <- MISSING OUTPUT
if (endCheckIter != poly.end()) {
if (i->coef > 0)
cout << " + ";
else
cout << " - ";
}
} // <- MISSING BRACE
}

Okay, now that Vlad has decided how he's going to do it, here's how I'd do it:
#ifndef _polinom_h
#define _polinom_h
#include <iostream>
#include <list>
#include <cstdlib>
#include <cmath>
#include "infix_iterator.h"
using namespace std;
char var;
class polinom {
class term {
double coef;
int power;
ostream &write(ostream &os) const {
// At least to me, the logic is easier to follow if we
// handle one piece at a time.
// It may be longer, but I think it's easier to understand.
// First, if the coefficient is negative, subtract the term instead of adding it.
if (coef < 0)
// backspace over the "+ " and print '- ' in its place.
os << "\b\b- ";
// Then print the absolute value of the coefficient (if needed).
if (fabs(coef) != 1)
os << fabs(coef);
// Then print the var (if needed)
if (power != 0)
os << var;
// then print the power (if needed)
if (abs(power) > 1)
os << "^" << power;
// And we're done.
return os;
}
// support inserting a term into a stream.
friend std::ostream &operator<<(std::ostream &os, term const &t) {
return t.write(os);
}
public:
term(double c=0.0, int p=0) : coef(c), power(p) {}
bool read(std::ostream &os, std::istream &is, int num) {
// This is only slightly modified from the originally posted question
os << "\nTerm " << num << ": coef = ";
is >> coef;
if (coef == 0.0)
return false;
if (coef != 0.0) {
os << " grade = ";
is >> power;
}
return true;
}
bool operator<(term const &other) const {
// order by descending powers.
return other.power < power;
}
};
list<term> poly;
public:
void read(int id) {
term t;
int nr_term = 1;
std::cout << "P: " << id;
// Read and save individual terms:
while (t.read(std::cout, std::cin, nr_term++))
poly.push_back(t);
}
void write(char var) {
// sort the polynomial so the highest powers come first.
poly.sort();
// save the variable name for later use.
::var = var;
// Print out all the terms:
std::copy(poly.begin(), poly.end(), infix_ostream_iterator<term>(std::cout, " + "));
}
};
#endif
Using this is pretty trivial:
#include "polynom.h"
int main() {
polinom p;
p.read(1);
p.write('x');
return 0;
}

void print(char var)
{
for (list<term>::const_iterator i = poly.begin(), e = poly.end(); i != e; ++i) {
if (i != poly.begin() || i->coef < 0) {
cout << (i->coef > 0 ? '+' : '-');
}
if (abs(i->coef) != 1) {
cout << abs(i->coef);
}
if (i->pow == 0) {
if (abs(i->coef) == 1) {
cout << 1;
}
} else {
cout << var;
if (i->pow != 1) {
cout << '^' << i->pow;
}
}
}
}

Related

abnormal behaviour while displaying char array in C++ after object initialization

main():
char inp[] = "(A+B)/(C*D))";
Infix i;
cout << "In main: " << inp /* + ')' */ << endl << endl;
Here is Infix constructor:
Infix() {
push('(');
cout << "Element In Stack: " << *returnElement(returnTop()) << endl;
outputString = "";
strcpy(operatorArray, "/*-+%");
cout << "Operator Array: " << operatorArray << endl;
}
Infix is inheriting from a class 'Stack':
class Stack{
int top = -1;
char arr[100];
public:
bool push(char);
char pop();
char peek();
bool isEmpty();
void displayAll();
char returnTop() { return top;}
char* returnElement(int i) {
if(i > 98){
cout << "StackOutOfIndex";
return nullptr;
}
return &arr[i];
}
};
When I run the code in main, it displays unusual output:
Element In Stack: (
Operator Array: /*-+%
In main: +%
Stack Object Destroyed!
But, when in main, if the comment the line declaring 'Infix' object declaration, the code runs fine:
In main: (A+B)/(C*D))
EDITS:
Stack Class
#include<iostream>
using namespace std;
class Stack{
int top = -1;
char arr[100];
public:
bool push(char);
char pop();
char peek();
bool isEmpty();
void displayAll();
char returnTop() { return top;}
char* returnElement(int i) {
if(i > 98){
cout << "StackOutOfIndex";
return nullptr;
}
return &arr[i];
}
};
bool Stack:: push(char elementToPush) {
if(top > 98) {
cout << "\nStack Overflow!!";
return false;
} else {
arr[++top] = elementToPush;
return true;
}
}
char Stack:: pop() {
if(top <= -1) {
cout << "\nStack Underflow!!";
return ' ';
} else {
return (arr[top--]);
}
}
char Stack:: peek() {
if(top > 98) {
cout << "\nStack Overflow!!";
return ' ';
} else {
return arr[top];
}
}
bool Stack:: isEmpty() {
return (top <= 0);
}
void Stack:: displayAll() {
if(top <= -1) {
cout << "null";
return;
}
int i = top;
while (i >= 0) {
cout << arr[i] << " ";
--i;
}
cout << "\n";
}
Infix Class
#include<iostream>
#include<cstring>
#include<D:\Programs\11Stack.cpp>
using namespace std;
class Infix : public Stack {
string outputString;
char operatorArray[];
public:
Infix() {
push('(');
cout << "Element In Stack: " << *returnElement(returnTop()) << endl;
outputString = "";
strcpy(operatorArray, "/*-+%");
cout << "Operator Array: " << operatorArray << endl;
}
string infixToPostfix(char *, int);
bool manupulateOperator(char, int);
int checkPrecedence(char);
~Infix() {
cout << "\nStack Object Destroyed!" << endl;
}
};
string Infix:: infixToPostfix(char *str, int size) {
cout << "\nGiven String: " << str << endl;
int x;
for(int i = 0; i < size; ++size) {
x = str[i];
if(x != ' ') {
if(x == ')') {
while(returnTop() != '(') {
cout << pop() << " popped!\n";
}
cout << pop() << " popped!\n";
} else if(isalpha(x)) {
cout << x;
} /* else{ // scanned character is an operator
if(manupulateOperator(x, i)) {
} else {
return " ";
}
} */
}
}
return outputString;
}
bool Infix::manupulateOperator(char c, int position) {
try {
char topElement = *returnElement(returnTop());
if(checkPrecedence(c) == -1) {
cout << "\nErr\n";
}else if((checkPrecedence(c) > checkPrecedence(topElement)) || returnTop() == 0) {
push(c);
cout << c << " pushed!\n";
}
} catch(std::exception e) {
std::cerr << e.what() << '\n';
return false;
} catch (char* Ce) {
cout << Ce << endl;
}
return true;
}
int Infix::checkPrecedence(char c) {
/*
+ -> 1
- -> 1
* -> 2
/ -> 2
% -> 2
*/
switch(c) {
case '+':
return 1;
case '-':
return 1;
case '*':
return 2;
case '/':
return 2;
case '%':
return 2;
default:
// throw "Illegal Operator Detected!";
cout << "Illegal Operator Detected: " << c << endl;
return -1;
}
}
int main() {
cout << endl;
int x = 1;
char inp[] = "(A+B)/(C*D))";
//Infix i;
cout << "In main: " << inp /* + ')' */ << endl << endl;
// cout << i.infixToPostfix(input + ')', sizeof(input));
/* for(int i = 0; i < strlen(inp); ++i) {
cout << inp[i];
}
*/
return 0;
}
You are declaring operatorArray as an array of char but you are not assigning any memory for it! So, when you then call strcpy(operatorArray, "/*-+%"); in your Infix constructor, you are causing undefined behaviour by attempting to copy the given string constant to memory that hasn't been assigned - and this appears to be overwriting the inp[] array declared in your main.
To fix this, I would suggest giving your operatorArray member a specific size, which will be large enough to accommodate whatever string you want to copy to it - 8 characters will work in the sample code you've given:
class Infix : public Stack {
string outputString;
char operatorArray[8]; // Make this member a REAL array of characters.
//..
Your variable char operatorArray[] have no memory allocated when your constructor is called. When you use strcpy, you write to a place where you don't have permissions in your memory, and therefore on other informations.
To find these kinds of mistakes, I recommend using valgrind.
char operatorArray[]; is not allowed in Standard C++.
If you didn't see an error message then I would recommend adjusting compiler settings to follow the standard form of the language, this would have saved you a lot of time.

c++ (Compare all spaces with Pawns )

I have a board game that has spaces (has numeral values 1,2,3, etc.) starting from 1 and 16 pieces of pawns; four for each player.
I want to show the result of my board game at some point. I tried the method below but that will make my code extremely long.
i have 16 pieces and 100 spaces that i have to repeat that code with 100 space that would take forever. the code below is just for one space (the first space)
Any idea how to show my result in a short way? Thanks in advance!
Here is my old-fashioned way:
//space 1
if (bpiece1->value == 1)
{
cout << " bpiece1";
}
else if (bpiece2->value == 1)
{
cout << " bpiece2";
}
else if (bpiece3->value == 1)
{
cout << " bpiece3";
}
else if (bpiece4->value == 1)
{
cout << " bpiece4";
}
else if (gpiece1->value == 1)
{
cout << " gpiece1";
}
else if (gpiece2->value == 1)
{
cout << " gpiece2";
}
else if (gpiece3->value == 1)
{
cout << " gpiece3";
}
else if (gpiece4->value == 1)
{
cout << " gpiece4";
}
else if (ypiece1->value == 1)
{
cout << " ypiece1";
}
else if (ypiece2->value == 1)
{
cout << " ypiece2";
}
else if (ypiece3->value == 1)
{
cout << " ypiece3";
}
else if (y4->value == 1)
{
cout << " y4";
}
else if (rpiece1->value == 1)
{
cout << " rpiece1";
}
else if (rpiece2->value == 1)
{
cout << " rpiece2";
}
else if (rpiece3->value == 1)
{
cout << " rpiece3";
}
else if (rpiece4->value == 1)
{
cout << " rpiece4";
}
else
{
cout << " 01";
}
C++ is an object-oriented language. Therefore, we start by creating a class that stores your board and implements all functions on it. Like
//Board.h
#include <array>
using std::array;
enum class Figure { None, Pawn };
class Board {
private:
array<array<Figure, 8>, 8> fields; //8x8 if it was a chess board
public:
void print() const;
};
//Board.cpp
#include "Board.h"
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
inline string to_string(const Figure figure){
switch(figure){
case Figure::None:
return " ";
case Figure::Pawn:
return "p";
}
//throw error here
return "";
}
void Board::print() const {
for(size_t i = 0; i < fields.size(); i++){
for(size_t j = 0; j < fields[i].size(); j++){
cout << to_string(fields[i][j]);
}
cout << endl;
}
cout << endl;
}
If this is new to you, you should really read the basic tutorials first and make sure that you understand each line I wrote in the end.
Important here is: Representation, represenation, representation. Don't think in "1 is a pawn", think in "a pawn is a pawn". Everything that has a function which you can think of should probably be a class, a structure or an enum.

Negative value not being added to Array

Problem
I have 2 arrays, one for positive numbers, one for negative numbers. For some reason, if the first number to be added is a negative number, it creates the array space to add the number yet the number inserted will always be 0.
Code for adding
Here is my add method, it determines if the value is negative or positive and adds the value to the appropriate array:
bool MyClass::addInt(int valueToBeInserted){
if (valueToBeInserted >= 0){
if (posArrayIterator >= sizeOfMyArray){
return false;
} else {
cout << "added " << valueToBeInserted << "\n" << endl;
myPArray[posArrayIterator] = valueToBeInserted;
posArrayIterator ++;
return true;
}
} else {
if (negArrayIterator >= sizeOfMyArray){
return false;
} else {
cout << "added " << valueToBeInserted << "\n" << endl;
myNarray[negArrayIterator] = valueToBeInserted;
negArrayIterator ++;
return true;
}
}
}
Output
With the following test:
b.addInt(-1);
b.addInt(-3);
b.addInt(-9);
The expected output would be
[-1, -3, -9]
but output is
[-3, -9, 0].
Any help is much appreciated.
Since you are not posting the whole class I can only guess where the problem is.
1) Are posArrayIterator and negArrayIterator initialized to 0? They should be!
2) What is a value of sizeOfMyArray?
There is nothing wrong with your bool MyClass::addInt(int valueToBeInserted)
See example below:
class MyClass
{
private:
int sizeOfMyArray;
int posArrayIterator;
int negArrayIterator;
int myNarray[20];
int myPArray[20];
public:
MyClass(){
sizeOfMyArray = 20;
posArrayIterator = 0;
negArrayIterator = 0;
};
bool addInt(int value);
void printNArray()
{
cout << "[ ";
for (int i=0; i<negArrayIterator; i++)
{
cout << myNarray[i];
if ( (i+1) < negArrayIterator )
{
cout << ", ";
}
}
cout << "]";
}
};
bool MyClass::addInt(int valueToBeInserted){
if (valueToBeInserted >= 0){
if (posArrayIterator >= sizeOfMyArray){
return false;
} else {
cout << "added " << valueToBeInserted << "\n" << endl;
myPArray[posArrayIterator] = valueToBeInserted;
posArrayIterator ++;
return true;
}
} else {
if (negArrayIterator >= sizeOfMyArray){
return false;
}
else {
cout << "added " << valueToBeInserted << "\n" << endl;
myNarray[negArrayIterator] = valueToBeInserted;
negArrayIterator ++;
return true;
}
}
}
int main()
{
MyClass b;
b.addInt(-1);
b.addInt(-3);
b.addInt(-9);
b.printNArray();
return 0;
}
Output:
added -1
added -3
added -9
[ -1, -3, -9]

Function counting characters of a string class being skipped?

I was trying to count the number of characters in a string class but for some reason the program is skipping over my function completely. This is just the test code from the main program, it still was giving me the same results. How come the counter function is skipped over?
#include <iostream>
#include <string>
using namespace std;
void prompt(string& dna)
{
cout << "Input: ";
getline(cin, dna);
}
void counter(const string DNA,
int* a_count, int* t_count, int* c_count, int* g_count)
{
for (int i = 0; i < DNA.size(); i++)
{
if (DNA.at(i) == 'a')
{
*a_count++;
}
else if (DNA.at(i) == 't')
{
*t_count++;
}
else if (DNA.at(i) == 'c')
{
*c_count++;
}
else if (DNA.at(i) == 'g')
{
*g_count++;
}
}
}
int main()
{
string dna;
int a = 0;
int t = 0;
int c = 0;
int g = 0;
prompt(dna);
if (! dna.empty())
{
cout << "Before:\n"
<< "A: " << a << endl
<< "T: " << t << endl
<< "C: " << c << endl
<< "G: " << g << endl;
counter(dna, &a, &t, &c, &g);
cout << "\n\nAfter:\n"
<< "A: " << a << endl
<< "T: " << t << endl
<< "C: " << c << endl
<< "G: " << g << endl;
}
system("pause");
return 0;
}
You're applying operator ++ the wrong way. It should be:
if (DNA.at(i) == 'a')
{
(*a_count)++;
}
else if (DNA.at(i) == 't')
{
(*t_count)++;
}
else if (DNA.at(i) == 'c')
{
(*c_count)++;
}
else if (DNA.at(i) == 'g')
{
(*g_count)++;
}
You've got a priority problem between the ++ and * operators. You are incrementing the pointer address, not the value. (*a_count)++; would be correct.
You may find it easier to use reference parameters for the counts instead, since you don't actually need to do any pointer arithetic. ie:
void counter(const string DNA, int& a_count, int& t_count, int& c_count, int& g_count)
And, yes a switch statement would be neater.

<<operator is only printing an empty line

In main the list prints out using the insertion operator, but all that I get is an empty line. Not sure why. Is it that there is nothing being stored in the list even when you use the set_coefficient? Any other critiquing is welcome. Thanks
here's the driver:
#include <iostream>
#include "polynomial.h"
using namespace std;
int main(){
Polynomial* poly = new Polynomial();
poly->set_coefficient(3,2);
poly->set_coefficient(0,2);
poly->set_coefficient(3,1);
cout << "trying to print data" << endl;
cout << *poly << endl;
return 0;
}
Here's the header:
#ifndef _POLYNOMIAL_H_
#define _POLYNOMIAL_H_
#include <iostream>
class Polynomial {
public:
struct PolyNode {
int coefficient, degree;
struct PolyNode* next;
PolyNode(int c, int d, PolyNode* n): coefficient(c),degree(d),next(n){}
};
PolyNode* firstTerm;
Polynomial(): firstTerm(0) {}
struct PolyNode* get_first(){
return firstTerm;
}
//makes the term with degree d have a coefficient of c
void set_coefficient(int c, int d);
~Polynomial();
friend std::ostream& operator<<(std::ostream& o, const Polynomial& p);
};
#endif
Here's the implementation:
#include "polynomial.h"
#include <iostream>
#include <ostream>
using namespace std;
void Polynomial::set_coefficient(int c, int d){
PolyNode* start = firstTerm;
if(c != 0 && firstTerm == 0)
firstTerm = new PolyNode(c,d,NULL);
else{
cout << "Entered set_coefficient()" << endl;
while(start->degree != d && start->next != NULL){
cout << "Inside set_coefficient() while loop" << endl;
start = start->next;
}
if(c != 0 && start == 0)
start = new PolyNode(c,d,0);
else if(c!= 0 && start != 0)
start->coefficient = c;
else if(c == 0){
cout << "deleting a term" << endl;
delete start;
}
}
cout << "Leaving set_coefficient()" << endl;
}
ostream& operator<<(ostream& o,const Polynomial& p){
Polynomial::PolyNode* start = p.firstTerm;
for(unsigned int i = 0; start->next != 0; i++){
o << "Term " << i << "'s coefficient is: " << start->coefficient << " degree is: " << start->degree << endl << flush;
start = start->next;
}
return o;
}
if(c != 0 && start == 0)
start = new PolyNode(c,d,0);
else if(c!= 0 && start != 0)
start->coefficient = c;
else if(c == 0){
cout << "deleting a term" << endl;
delete start;
}
if (c != 0 && start == 0) // this situation may occur ? you have already judged surrounding if
else if (c == 0) {
cout << "deleting a term" << endl;
delete start; // that may be cause linkedList detach.
}
cout << "Entered set_coefficient()" << endl;
while(start->degree != d && start->next != NULL){
cout << "Inside set_coefficient() while loop" << endl;
start = start->next;
}
if(c != 0 && start == 0)
start = new PolyNode(c,d,0);
else if(c!= 0 && start != 0)
start->coefficient = c;
else if(c == 0){
cout << "deleting a term" << endl;
delete start;
}
It appears you want a linked list, but you're neither creating nor removing links (start->next), only allocating memory. Without setting up the links, there is no list.
There are probably multiple bugs here :>
ostream& operator<<(ostream& o,const Polynomial& p){
Polynomial::PolyNode* start = p.firstTerm;
for(unsigned int i = 0; start->next != 0; i++){
this won't print the last PolyNode...