I been stuck here for a few days. Could anyone take a look at the toString method in the Row class, how can I retrieve every point from a tree of points and get the char value from the point? I know in vector or array we can probably use a for loop and do something like find(points[i]), but I really have no clue here.
**std::string toString() const
{
string s;
for(int i = 0; i != points.size(); i++)
{
//Maybe use points.find(???) here to retrieve the point
s.push_back(point.getType()); //Just for demonstration, this does not work
return s;
}
}**
};
So I cannot modify the binNode binTree class. And I cannot have the print method in the Point class, because the print() method print every element in a new line. But we have to retrieve the char value from every point, and attach all char value of all point into a String.
Thank you so much for giving me a hint!
The binNode template doesn't really support that sort of usage because it doesn't expose it's children. Nor does it supply an iterator. That makes it impossible to traverse the tree in code that is outside the class. The children are not even visible to subclasses so you can't extend it that way.
You could get hacky and specialize the binNode template for Point and force it to emit output into a global string:
std::string output; // a global
template <>
class binNode<Point> {
void print() const {
if (left != NULL) left->print();
output += nodeData.getType();
if (right != NULL) right->print();
}
};
// in some function
output.clear(); // remember to clear previous output
points.print(); // the string now has the output from `print`
This will of course not work if you have multiple threads calling print even on separate bintrees.
To properly implement such functionality, your only option is to modify bintree and binNode.
Related
This code is for finding the intersection and union of two sorted lists. The sorted list in inherited from a list class with all the basic functions. The main question is what is the return type of the function.
Is it a pointer to a list or the list itself? How would i display the contents of that "pointer".
template <typename Object>
class sorted_list : public List<Object>{
friend sorted_list<Object>*& slUnion( const sorted_list<Object>& list1, const sorted_list<Object> & list2){
auto i=list1.begin();
auto j=list2.begin();
sorted_list<Object> un;
static sorted_list<Object>* newlist=&un;
while(i!=list1.end() && j!=list2.end()){
if(*i<*j){
un.push_back(*i);
i++;
}
else if(*i>*j){
un.push_back(*j);
j++;
}
else{ //if equal
un.push_back(*i);
i++; j++;
}
}
while(i!=list1.end())
un.push_back(*i++);
while(j!=list2.end())
un.push_back(*j++);
return newlist;
}
};
When the program runs, the "un" in main points to NULL.
int main(){
sorted_list<int> l1;
int i=1;
while(i<10){
l1.push_back(i++);
}
sorted_list<int>l2;
int j=1;
while(j<10){
l2.push_back(j);
j+=2;
}
sorted_list<int> *un = slUnion(l1,l2);
}
You should typically return by value, i.e. sorted_list<Object>. Newer versions of cpp guarantee you that they will not actually make a copy.
What you are doing right now is wrong, because it has undefined behavior. You are using un, which is on the function stack, and return a pointer to it. By the time the function returns un has gone out of scope and the memory location can have been reused. Just completely remove the newlist pointer and return un instead.
You also seem to be confused about classes, methods and functions. As it is, your method does not have to be inside a class, or, since it does not seem to use class state, it can be static, if inside a class. It also does not seem like it would have to be a friend. If you wanted to write this as a member-function, it would look sth like this:
sorted_list<Object>& unionWith(const sorted_list<Object>& rhs) {
// merge this and rhs w deduplication into temp, then swap temp with this
...
return *this;
}
I think what is likely your problem, is that you don't assign &un to newlist, but that you initialize newlist with &un. Initialization is only performed once for a function-static variable, so future iterations of your method just skip that line and the pointer points to where the original version of un was. Try putting the assignment on a different line. That should fix your immediate issue, but the solution with the static pointer is still really bad, because the pointer is shared by all instances.
I added also void Clear()-method.
https://redstoner.com/forums/threads/840-minimal-class-to-replace-std-vector-in-c-for-arduino
https://forum.arduino.cc/index.php?topic=45626.0
I'm asking about this Vector class.
void push_back(Data const &x) {
if (d_capacity == d_size) resize();
d_data[d_size++] = x;
}; // Adds new value. If needed, allocates more space
How to add "insert"-method to this Vector class (arduino use C++ but not have a standard vector methods)?
Vector<Sensor*> sensors;
I have a another class Sensor and I use vector like this.
push.back(new Sensor (1,1,"Sensor_1",2));
Is it possible to add values one by one to this vector class? And how to do it?
I like to ask also other question.
How can I call delete/call destructor for this Vector "sensors" so all pointers are deleted? Or sensors vector is deleted? I want to clear the data and then add data to it.
If you want to add an item to the end of the vector, use the push_back method you've quoted above. If you want to add an item somewhere else in the vector, you'll need to add your own method which re-sizes if necessary, shifts the elements above the insert location up one place and then copies the new element into the correct slot. Something like this (untested):
void insert_at(size_t idx, Data const &data) {
assert(idx < d_size);
if (d_capacity == d_size) {
resize();
}
for (size_t i = d_size; i > idx; --i) {
d_data[i] = std::move(d_data[i - 1]);
}
d_data[idx] = data;
++d_size;
}
As Nacho points out, you might be better off with a linked list if you're going to do a lot of these insert operations, especially if the data you're storing is large and/or has a complex move operator.
I am trying to use the C++ "Clipper Library" (http://www.angusj.com/delphi/clipper.php), but when I try to return one of the objects from the clipper library from a function, it seems to become null or is altered somehow
Here is the function I wrote. The only relevant lines should be the last 3.
ClipperLib::PolyTree MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles)
{
// Make all of the triangles CW
for (auto& triangle : triangles)
{
triangle.makeClockwise();
}
// Set up the Clipper
ClipperLib::Clipper clipper;
// To take a union, add all the paths as "subject" paths
for (auto& triangle : triangles)
{
ClipperLib::Path triContour(3);
triContour[0] = convertGLMToClipperPoint(triangle.getVertex(0));
triContour[1] = convertGLMToClipperPoint(triangle.getVertex(1));
triContour[2] = convertGLMToClipperPoint(triangle.getVertex(2));
clipper.AddPath(triContour, ClipperLib::PolyType::ptSubject, true);
}
// Now get the PolyTree representing the contours
ClipperLib::PolyTree tree;
clipper.Execute(ClipperLib::ClipType::ctUnion, tree);
return tree;
}
When I call clipper.execute, it writes into the tree structure some contour information. It writes the correct information, and I've tested that it's correct. However, when I return the tree, it doesn't seem to copy anything, and the PolyTree that results from this function is empty.
I'm sure that there's nothing wrong with the library and that I'm just making a beginner c++ mistake here. Hopefully someone has an idea of what it might be.
Thanks!
edit: For reference, here is a documentation page for the polytree (http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/PolyTree/_Body.htm)
edit: I thought the clipper library wasn't open source, but it is. Here is the code
typedef std::vector< IntPoint > Path;
typedef std::vector< Path > Paths;
class PolyNode;
typedef std::vector< PolyNode* > PolyNodes;
class PolyNode
{
public:
PolyNode();
Path Contour;
PolyNodes Childs;
PolyNode* Parent;
PolyNode* GetNext() const;
bool IsHole() const;
bool IsOpen() const;
int ChildCount() const;
private:
unsigned Index; //node index in Parent.Childs
bool m_IsOpen;
JoinType m_jointype;
EndType m_endtype;
PolyNode* GetNextSiblingUp() const;
void AddChild(PolyNode& child);
friend class Clipper; //to access Index
friend class ClipperOffset;
};
class PolyTree: public PolyNode
{
public:
~PolyTree(){Clear();};
PolyNode* GetFirst() const;
void Clear();
int Total() const;
private:
PolyNodes AllNodes;
friend class Clipper; //to access AllNodes
};
Before doing anything, make sure the following program works correctly:
int main()
{
PolyTree p1;
// fill PolyTree with some values that make sense (please add code to do this)
//...
PolyTree p2 = p1;
PolyTree p3;
p3 = p1;
}
That is basically what we want to test. If you can get this code to work (add the relevant headers and initializations necessary), then you can focus back on the function. If the code above doesn't work, then there is your answer.
You need to get the code above to produce the correct copy semantics, and even just important, when main() exits, no memory corruption occurs on the destruction of p1, p2, and p3.
So either you can fix the class to copy safely, or forget about it and live with a class that you have to handle very carefully and in limited situations (i.e. you can't reliably return copies of it as you're doing now).
For the record and combining all the responses in the lengthy discussion to the question.
Problems are:
The value returned is a local variable that goes out of scope. This invokes the PolyTree destructor
The PolyTree contains a vector of PolyNode * pointers. Those are allocated when clipper.Execute() is invoked.
However PolyTree::Clear() does delete the nodes... and Clear() is invoked by the destructor.
So within the function, the content is correct (allocated by Execute()), when passed outside, in the absence of copy constructors and operator=, the destructor of the local variable is invoked an the nodes are cleared, the result received outside of the function is empty.
The code for PolyTree::Clear()
void PolyTree::Clear()
{
for (PolyNodes::size_type i = 0; i < AllNodes.size(); ++i)
delete AllNodes[i];
AllNodes.resize(0);
Childs.resize(0);
}
Probably you should follow the pattern of Execute and define your function as:
void MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles,ClipperLib::PolyTree &tree)
Assuming you don't want to modify the (obviously badly designed) Clipper library, you can do it like I suggested in my comment:
// Make sure to have this at the top of your header file:
#include <memory>
std::unique_ptr<ClipperLib::PolyTree> MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles)
{
// Rest of your code...
std::unique_ptr<ClipperLib::PolyTree> tree(new ClipperLib::PolyTree);
clipper.Execute(ClipperLib::ClipType::ctUnion, *tree);
return tree;
}
Then, when calling your function:
std::unique_ptr<ClipperLib::PolyTree> tree(yourMeshHandler.trianglesToPolyTreeUnion(/*...*/);
// make use of tree...
Still, I would suggest opening a ticket (if there's a bug tracker) or contacting the library's author about this issue.
Is there already a solution for this problem? I am dealing with the same problem.
Still no luck. The polytree outputs only memory adres.
when using : qDebug()<< "child id " << polynode->Childs;
When we have 2 childs, the output in terminal is :
std::vector(0x55f30d2a91b0, 0x55f30d258480)
I hope someone knows how to solve this..
Your problem is in the third line from the bottom of trianglesToPolyTreeUnion. The tree you are creating is created on the stack and is only in scope within the function.
You should dynamically allocate the memory and return a pointer to the tree or make your tree object a class member so it is still within scope once the function returns.
There is an array of objects and to add object to it i tries the following:
Shape ShapeList[30];
void addShape(Shape s)
{
for(int i=0; i<30;i++)
{
if(ShapeList[i] != '\0')
{ i++;}
else
{
ShapeList[i]=s;
numShapes++;
break;
}
}
}
numShapes is an integer variable, Shape is the class and ShapeList is the array of objects. But the compiler gives an error in this way that != operator is not allowed. So how can i implement this?
I think you need to change your 'container' declaration:
Shape *ShapeList[30];
void addShape(Shape *s)
{
for(int i=0; i<30;i++)
{
if(ShapeList[i])
{ i++;}
else
{
ShapeList[i]=s;
numShapes++;
break;
}
}
}
and call addShape this way:
addShape(new Shape());
ShapeList[i] returns an object of type Shape. In that case, you can overload operator != (char).
class Shape
{
//your implementation
//
public:
bool operator != (char x) const
{
// comparison logic
}
};
Also, I believe you have a mistake here:
if(ShapeList[i] != '\0')
{ i++;}
I assume you want to skip this case, but you already increment i in the for loop. You probably want:
if(ShapeList[i] != '\0')
{ continue;}
As others have pointed out, you should use a std::vector instead of a raw array. I initially assumed ShapeList was a wrapper over a std container.
Shape * ShapeList[30];
numShapes=0;
void addShape(Shape* s)
{
if( i>=30)
return;
ShapeList[numShapes++]=s; // provided you need to insert at end
}
You can't use \0 because it's an array, not a string.
storing the whole object as such is an overhead with memory. pointers are a better choice unless you have local variables going out of scope problems. and if STL and Vectors is not beyond your scope of the project you are on to try using it. in which you can use pushback() or pushfront()
You did not specify how ShapeList is declared.
With the != operator you compare it to the character NUL,
while 4 lines below you assign it a Shape object.
What i think you are trying to achieve, is: find an empty slot in the array of pointers to Shape, and store the Shape there.
But probably better is to use either a std::vector, or std::list, and push_back your shape.
Another thing you have to ask yourself: do i want to store copies of my Shape object, or pointers?
Unless you have a conversion operator in the Shape class to convert it to a character, or a not-equal comparison operator that takes a character as argument, you can not compare a Shape object to a char like you do.
You should be using a std::vector or std::array and use the at member function to see if entry exists or not.
I have a class symbol_table that has a vector of objects of another class row_st.also I have an enter method where inserts objects of row_st with a passed name into the vector of desired symbol_table.but when I call the enter to enter objects with name :
a;b;c;Iwill get the following result: a,b,c;b,c;c.the first element of vector gets the name of all the entered objects. and the second element also gets the name of the later entries.
class row_st
{
public:
char* name;
type_u type;//int:0,flaot:1;char:2,bool:3,array:
int offset;
symbol_table *next;
symbol_table *current;
};
class symbol_table
{
public:
vector <row_st *> row;
int type;
int header;
int starting_stmt;
int index;
int i;
symbol_table *previous;
symbol_table(){ header=0;
previous=0; index=0;i=0;starting_stmt=0;}
};
and here it is the enter method:
int enter(symbol_table *table,char* name,type_u type){
row_st *t=new row_st;
t->name=name;
t->type=type;
t->offset=table->index;
t->current=table;
table->index++;
t->next=0;
table->row.push_back(t);
table->header +=1;
return table->row.size()-1;
}
the push_backed elements all points to the same address.the new call makes the same row_st every time it is called.what should I do?
You can't use character pointers like that - you need to allocate storage to them. But as you are using C++, you should remove them and replace them with instances of the std::string class, which will manage storage for you.
As Neil Butterworth's answer suggest, the trouble is probably not with this code, but the place where you call it. Using character pointers does not make it impossible to make things work, just harder.
The problem in this case is definitely not with push_back. If you posted the method where you call this code it might be possible to see exactly what goes wrong.