I'm wondering how I would go about storing a value into a struct that is part of a linked list of structs. I have:
struct polynomial
{
polynomial(string newCoefficient, string newPower, polynomial *nextPtr);
string coefficient;
string power;
polynomial *next;
};
class linkedList
{
public:
void createList();
private:
polynomial *head;
};
For this assignment, we need to do some parsing when gathering input values. For example, we are to input two numbers separated by a space (ex. 7 9 or 10 8). Therefore, in void createList(), I want to read in a line using string, convert it to a char array to strip down the values, then store that value into polynomial.coefficient and polynomial.power, for each node in the linked list.
Or, I was searching some information up, and I was thinking maybe I can input two int values and then use stringstream to convert them into strings and them store into coefficient and power.
Either way, can you help introduce me to the concept of storing a value into a linked listed struct?
EDIT: I have added the overloaded constructor:
polynomial:: polynomial ( string newCoefficient, string newPower, polynomial *nextPtr )
{
coefficient = newCoefficient;
power = newPower;
next = nextPtr;
};
You are mixing C-style practice with C++ practice.
In C++, you generally separate the data from the container. Look at how std::list works.
Even if you don't want to get into templating, you can still do this:
struct polynomial {
string coefficient;
string power;
};
struct listnode {
polynomial data;
listnode *next;
};
If you really want to have the head concept, you can either keep a 'dummy head' where you store one listnode that has nothing in it.
Alternatively, if you really want the next pointer in polynomial and you want a way to copy over an existing element without nuking the pointer, just make a setter function:
void polynomial::set( const string& inCoeff, const string & inPower );
I tested the following code which may help you out:
struct Polynomial {
string coefficient;
string power;
Polynomial* next;
Polynomial(const string& coeff, const string& pow) : coefficient(coeff), power(pow), next(NULL) {}
};
// linked-list of Polynomials
struct LinkedList {
Polynomial* head;
LinkedList() : head(NULL) {}
// add to end of list
void add(const string& coeff, const string& pow) {
if(head == NULL)
head = new Polynomial(coeff, pow);
else {
Polynomial* n;
for(n = head; n->next != NULL; n = n->next);
n->next = new Polynomial(coeff, pow);
}
}
// check if results are correct
void print() {
for(Polynomial* n = head; n != NULL; n = n->next)
cout << n->coefficient << " " << n->power << endl;
}
};
// somewhere in main()
LinkedList ll;
...
// read input values
ll.add(coeff1, pow1);
ll.add(coeff2, pow2);
ll.add(coeff3, pow3);
// check results
ll.print();
Note your Polynomial struct members need not be strings. Instead you could just parse your input and store cofficient as float and power as int (All polynomial exponents are integers).
Related
I am trying to make a network application. Its class blueprint is roughly like this-
class Node
{
public:
// member functions
private:
int nodeID;
// other members
};
class NodeNetwork
{
public:
// member functions
private:
Node nodeArray[MAX_NODES];
// other members
};
Here, the Node class will deal with each node and the NodeNetwork is used to deal with the complete network.
The actual number of nodes in nodeArray can vary from 0 to MAX_NODES during runtime, i.e., it may not always be MAX_NODES, the number of nodes can be increased or decreased during runtime. Moreover, when the program starts the number will always be 0, after that it will start increasing.
I am using Node nodeArray[MAX_NODES];, but I think it's a serious wastage of space as not always I will have MAX_NODES nodes at runtime. So I am looking for ways to optimize it. I want it so that it starts with a zero-length array, but the size can be increased or decreased subjected to the above constraints based on the nodes added or removed at runtime. I researched on the internet but did not find any concrete answer.
I hope someone can help me solve this problem, thanks in advance.
You can use dynamically array allocation for this purpose:
int* arr = new int[5];
..and anytime you wish to change the number of elements:
int size = 5;
int* arr = new int[size] {};
int* new_arr = new int[size + 1];
for (int i = 0; i < size; i++)
{
new_arr[i] = arr[i];
}
delete[] arr;
arr = new_arr;
// Now arr has a storage capacity of 6 elements
..so for your case you can write:
Node* nodeArray = nullptr; // nullptr == null pointer
But this can take a lot of time for huge arrays.
So preferably, you can use std::vector:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> vec{ 1, 2, 3, 4, 5 };
vec.push_back(6); //Insert a new element
std::cout << vec[0]; // Accessing an element is the same as an array
}
..so for your case:
// {} is just for initialization, not exactly mandatory
std::vector<Node> nodeArray{};
You can use std::vector instead of array. That is, you can make the data member nodeArray to be a std::vector<Node> as shown below.
#include <iostream>
#include<vector>
class Node
{
public:
//constructor for initializing nodeID data member
Node(int pnodeID): nodeID(pnodeID)
{
}
//getter for nodeId
int getId() const
{
return nodeID;
}
private:
//always initialize built in type in local/block scope so that they don't have indeterminate value
int nodeID = 0;
// other members
};
class NodeNetwork
{
public:
// member function to add Node
void addNode(const Node& n)
{
nodeArray.push_back(n);
}
//member function to print out the current nodes
void display() const
{
std::cout<<"Network has the following nodes: "<<std::endl;
for(const Node& elem: nodeArray)
{
std::cout<<elem.getId()<<std::endl;
}
}
private:
std::vector<Node> nodeArray; //used std::vector instead of array
// other members
};
int main()
{
//create Node objects
Node node1{1};
Node node2{2};
Node node3{3};
NodeNetwork network1;
//add node1 into the network1's nodeArray data member
network1.addNode(node1);
//add node2 into the network1's nodeArray data member
network1.addNode(node2);
//display all nodes into network1
network1.display();
return 0;
}
In the above demo we have added elements into the nodeArray data member by using std::vector::push_back member function.
The output of the above program can be seen here:
Network has the following nodes:
1
2
I tried initializing a 2D vector with a constructor in 3 different ways but always get an
"error: no matching function to call"
Could you tell me where I am wrong?
class Node
{
public:
int to;
int length;
Node(int to, int length) : to(to), length(length){}
};
class Graph
{
public:
vector<vector<Node>> nodes_list;
int n;
Graph();
};
Graph::Graph(){
nodes_list = vector<vector<Node> >(n, vector<Node>(n,0x3fffffff));
}
vector<Node>(n,0x3fffffff);
is (roughly) equivalent to:
vector<Node> v;
for ( size_t i = 0; i < n; i++ )
{
v.push_back(Node(0x3fffffff));
}
As your Node class doesn't have a constructor taking a single integer this fails to compile. The correct code is:
vector<Node>(n,Node(0x3fffffff,0));
By the way I assume you have using namespace std; in your header for Graph, don't do that, it will cause you issues at some point.
Your code has two problems:
At the following line, you should have provided the parameters for
constructing the Node, which are to and legth.
vector<vector<Node>>(n, vector<Node>(n,0x3fffffff));
// ^^^^^^^^^^^--> here
In Graph, the member n is un-initialized, at the
point, you call the default constructor. That would lead you to have
a garbage value in n and hence the size of the nodes_list would
be undefined.
The fixed code will look like:
struct Node
{
int _to;
int _length;
Node(int to, int length) : _to{ to }, _length{ length } {}
};
class Graph
{
using VecNode = std::vector<Node>; // type alias for convenience
private:
int _n;
std::vector<VecNode> _nodes_list;
public:
Graph()
: _n{ 2 } // initialize _n
, _nodes_list{ _n, VecNode(_n, { 1, 3 }) }
// ^^^^^^-> initialize with the default 'Node(1, 3)'
{}
};
Also some suggestions:
Use member initializer
lists
to initialize the vector, instead of creating and assign to it.
It's not a good idea to name both constructor parameters and the
members with same in Node. At some point, that may lead to
confusions.
I'm trying to access a structure using another structure. From the below program, element is the member of Node. At this line " temp->element *e_temp;", I couldn't link the "element" member of Node to the "elements" structure object.
compile error says "'e_temp' was not declared in this scope". What am I missing?
#include <vector>
#include <cstdlib>
using namespace std;
typedef struct Elements
{
int data;
struct Elements *next;
}elements;
typedef struct Node
{
int sno;
elements *element;
struct Node *next;
}node;
void add(int sno, vector<int> a)
{
node *temp;
temp = new node;
temp->element *e_temp;
e_temp = new elements;
temp->sno = sno;
while(a.size())
{
temp->e_temp->data = a[0];
temp->e_temp = temp->e_temp->next;
a.erase(a.begin());
}
}
int main()
{
vector<int> a{1,2,3};
int sno = 1;
add(sno, a);
return 0;
}
If you're just looking to declare a local you can do auto e_temp = new elements but what i think you want is this for that line temp->element = new elements;
and then follow up with the rest of your code to reference temp's element instead of e_temp.
temp->element->data = a[0];
temp->element = temp->element->next
Also, i'd try to get out the habit of using new and use std::shared_ptr and std::unique_ptr instead.
The correct declaration for e_temp is
elements * e_temp;
but e_temp is not use of any part of your code.
I have my own classes which implements queue and stack using LL, the source code compiles fine on my machine but after throwing it in valgrind it shows me some memory leaks
class S{
private:
struct Node{
int value;
Node* next;
Node(int v, Node* n):value(v), next(n){}
};
Node* head;
S(const S& other) {}
S& operator=(const S& other) {}
public:
S():head(NULL){}
void push(unsigned int data){
head = new Node(data, head);
}
class Q{
private:
struct Node{
int value;
Node* next;
Node(int v, Node* n):value(v), next(n){}
};
Node* head;
Node* tail;
int size;
Q(const Q& other) {}
Q& operator=(const Q& other) {}
public:
Q():head(NULL), tail(NULL), size(0){}
void push(int data){
if (head == NULL) head = tail = new Node(data, tail);
else{
tail -> next = new Node(data, tail);
tail = new Node(data, tail);
}
size++;
}
What am i doing wrong? Much help would be appreciated :) cheers
In your class constructor:
PQ(int cap){
capacity = cap;
arr = new int [capacity++];
for (int i= 0; i < capacity; i++) arr[i] = {0};}
this:
capacity++
will first return the capacity and then increase its value by one.
Because of this, when you are filling your array in a for loop, you are going out of array range, because your array size is 1 less than the capacity value.
This is not a "memory leak".
This is memory corruption. You can start fixing it by making a mental effort to understand that arrays in C++ are 0-based, not 1-based. The first element of an array is array[0] and not array[1], and everything else is based on that. The following is based on the notion that array elements start with array element #1:
int top(){
return arr[1];
}
void pop(){
arr[1] = arr[size];
The first element of an array is element #0, not element #1, but this is structured based on the concept that the first element in the array is element #1.
It might seem like adding 1 to the array size before allocating it is an easy way to avoid having to make this adjustment, but it only leads to more grief, confusion, and bugs, later down the line. This is why, apparently, the constructor attempts to increment the size of the array before allocating it:
PQ(int cap){
capacity = cap;
arr = new int [capacity++];
for (int i= 0; i < capacity; i++) arr[i] = {0};
}
Except that it increments it incorrectly. It's a post-increment, so if, for example, cap was 4, new int[4] gets allocated, before capacity gets incremented. The next line attempts to clear array elements #0 through #4, except that array element #4 doesn't exist, the code tries to initialize it, runs off the end of the array, and valgrind throws a red flag.
Although this is fixable simply by using pre-increment instead of post-increment, the correct solution is not to increment at all, but restructure the code so that it follows the natural properties of C++ arrays being 0-based, instead of 1-based.
*Note: This is for an assignment: I don't want a solution, just some hints to get me thinking in the correct direction.
I've created a linked-list of Polynomial term objects (PolyTerm). I am supposed to write opperator overloads for + and -. I've not been able to figure out a way to get the overloading done. Doing research, I believe that the way that I set up the link list that I might not be able to do the overloads. I think I should have made a struct for the Nodes and put the nodes into an class. Instead, I just set it up as a single class and now I am struggling with trying to overload with pointers (which you can't do as far as I know).
I've created an addition member function and am wondering if there is any way of using that to cludge an + operator overload? Everything I've been reading seem to indicate no, but I just want final verification.
Here is my header for my class:
class PolyTerm
{
public:
/************************** CLASS CONSTRUCTORS *********************************/
PolyTerm(); // Default constructor
PolyTerm(int constant); // Constant term constructor
PolyTerm(int newExp, int newCoeff); // Unlinked term constructor
PolyTerm(int newExp, int newCoeff,
PolyTerm* next, PolyTerm* prev); // Full constructor
PolyTerm(PolyTerm* original); // Copy Constructor
/*******************************************************************************/
/**************************** CLASS DESTRUCTOR *********************************/
~PolyTerm();
/************************** ACCESSOR FUNCTIONS *********************************/
int getCoeff() const; // Returns coefficient of this term
int getExp() const; // Returns the exponent of this term
PolyTerm* getNext() const; // Returns the address of the next term
PolyTerm* getPrev() const; // Returns the address of the previous term
/*******************************************************************************/
/*************************** MUTATOR FUNCTIONS *********************************/
void setCoeff(int newCoeff); // Sets the value of this term's coefficient
void setExp(int newExp); // Sets the value of this term's coefficient
void setNext(PolyTerm* newNext); // Sets the value of this term's next term
void setPrev(PolyTerm* newPrev); // Sets the value of this term's prev term
/*******************************************************************************/
/**************************** MEMBER FUNCTIONS *********************************/
int evalTerm(int value); // Evaluates the term for using 'value'
void printTerm(); // Prints this term. ex '4x^3'
void printPoly(); // Prints the whole polynomial
void insertTerm(PolyTerm* afterMe, int exp, int coeff); // Node insertion
PolyTerm* addTogether(PolyTerm* p2); // adds this and p2 together.
PolyTerm* subtractThis(PolyTerm* p2); // subtracts this - p2.
/*******************************************************************************/
/************************** OPERATOR OVERLOADS *********************************/
const PolyTerm& operator+(const PolyTerm &other) const; // <----Cant figure this out
protected:
/**************************** MEMBER VARIABLES *********************************/
int exp; // The exponent of this term
int coeff; // The coefficient of this term
PolyTerm *next; // The location of the next term
PolyTerm *prev; // The location of the previous term
/*******************************************************************************/
private:
};
Everything else in the class works properly. Here is the AddTogether function definition as well. It works well, just not exactly what the assignment wants.
PolyTerm* PolyTerm::addTogether(PolyTerm* p2)
{
PolyTerm* bigHead; // This pointer has an Ego Problem.
PolyTerm* big;
PolyTerm* small;
int bigDegree, smallDegree;
// Sets the bigger degree and smaller degree polynomial.
if(this->getExp() >= p2->getExp())
{
big = new PolyTerm(this);
small = p2;
}
else
{
big = new PolyTerm(p2);
small = this;
}
//Assign a head pointer for big polynomial (resultant of sums)
bigHead = big;
bigDegree = big->getExp();
smallDegree = small->getExp();
// Step through the members of the big polynomial that don't
// don't have a corresponding term in small one.
for (int i = 0; i < bigDegree - smallDegree; i++)
{
big = big->getNext();
}
// For each term that they have in common, add the coefficients
// and create a new term.
for (int i = 0; i <= smallDegree; i++)
{
big->setCoeff(big->getCoeff() + small->getCoeff());
big = big->getNext();
small = small->getNext();
}
return bigHead;
}
Am I right that I can't set up an operator overload for this class?
Hope this will give some idea
class Test
{
public:
int x;
Test(int val)
{
x = val;
}
Test()
{
x = 0;
}
Test* operator+(const Test& testRhs)const
{
Test* test = new Test();
test->x = this->x + testRhs.x;
return test;
}
Test* operator+(const Test* testRhs)const
{
Test* test = new Test();
test->x = this->x + testRhs->x;
return test;
}
};
using namespace std;
int main()
{
Test* pTestOut = NULL;
Test test0(5);
Test test1(3);
pTestOut = test0 + test1; //calling Test* operator+(Test& testRhs)const
cout << pTestOut->x << endl;
Test* pTestOut2 = NULL;
Test* pTest3 = new Test(2);
Test* pTest4 = new Test(8);
pTestOut2 = (*pTest3) + pTest4; //Calling Test* operator+(Test* testRhs)const
//First parameter should be object reference. So looks ugly
cout << pTestOut2->x << endl;
return 0;
}
Please refer Operator overloading : cannot add two pointers for writing looking good functions