Pointer and QVector issue - c++

I want to define functions which will delete self-defined type object and the index from the QVector.
Originally the source was as follows:
Point PointCollection::RemovePoint(int index)
{
Point removedPoint = new Point(this[index].Id, this[index].X, this[index].Y);
this->remove(index);
updateCentroid();
return (removedPoint);
}
Point PointCollection::RemovePoint(Point p)
{
Point removedPoint = new Point(p.GetId(), p.GetX(), p.GetY());
this.remove(p);
updateCentroid();
return (removedPoint);
}
which was not working as I think because of new. Then I modified the source to the following:
Point PointCollection::deletePoint(int Index)
{
Point deleted = Point(this[Index].Id, this[Index].X, this[Index].Y);
this->remove(Index);
updateCentroid();
return(deleted);
}
Point PointCollection::deletePoint(Point point)
{
Point deleted = Point(point.GetId(), point.GetX(), point.GetY());
this->remove(point);
updateCentroid();
return(deleted);
}
Now Point PointCollection::deletePoint(int Index) compiles without any error, but this->remove(point); in Point PointCollection::deletePoint(Point point) functioned is compiled with following error:
error: no matching function for call to 'PointCollection::remove(Point&)'
Q1: Did I do correct that removed new?
Q2: How to fix the error I am having.

Your approach seems to be overall wrong. First of all focus on what you need:
performance and memory efficiency or...
fast inserts and deletes
QVector is of the former kind. If you do deletes and inserts that are not in the back you will likely get poor performance. Because the entire vector has to be reallocated every time you do a change.
If you need to insert and delete often go for a linked list, for example QLinkedList.
Qt already provides containers, implementing your own doesn't offer much benefit, it is not likely that you will produce a better container than a bunch of professionals working on this framework for 20 years.
Here is a simple snippet how to insert and delete points in vector and linked list. You can use this methods to implement your own wrapper class if you want:
QVector<QPoint> myPointVector;
QLinkedList<QPoint> myPointList;
// push back some data
myPointVector << QPoint(1, 1) << QPoint(2, 2) << QPoint(3, 3) << QPoint(4, 4);
myPointList << QPoint(1, 1) << QPoint(2, 2) << QPoint(3, 3) << QPoint(4, 4);
foreach (QPoint p, myPointVector) qDebug() << p;
foreach (QPoint p, myPointList) qDebug() << p;
qDebug() << endl;
auto i1 = myPointVector.indexOf(QPoint(2, 2));
auto i2 = qFind(myPointList.begin(), myPointList.end(), QPoint(2,2));
myPointVector.insert(i1, QPoint(5,5)); // or existing point object / reference
auto i3 = myPointList.insert(i2, QPoint(5,5));
foreach (QPoint p, myPointVector) qDebug() << p;
foreach (QPoint p, myPointList) qDebug() << p;
qDebug() << endl;
QPoint deletedFromVector = myPointVector[i1]; // use those to return before deleting
QPoint deletedFromList = *i3; // note you don't need to construct just assign
myPointVector.remove(i1);
myPointList.erase(i3);
foreach (QPoint p, myPointVector) qDebug() << p;
foreach (QPoint p, myPointList) qDebug() << p;
qDebug() << endl;
As you see, initially both containers contain points 1 2 3 4, then point 5 is inserted in the place of 2, then removed again. The vector uses an integer index for the operations, the list uses an iterator. That is why when 5 is inserted, I get its "index" because unlike the vector it won't push back the rest, so if i2 is removed it will not remove point 5 which was inserted in place of point 2, but point 2 to which it still refers to.
Also, if you want to insert in the list in a given index, you can just use the begin iterator + index to "forward" the iterator the appropriate number of positions.
Hopefully that made sense. Naturally you can use you point class in the place of QPoint.

Related

How to use google-diff-match-patch library in C++ QT?

I've downloaded google diff library for C++ Qt.
https://code.google.com/archive/p/google-diff-match-patch/
But I don't really understand how to use it for a simple comparing of two strings.
Let assume I have two QStrings.
QString str1="Stackoverflow"
QString str2="Stackrflow"
As I understood I need to create dmp object of diff_match_match class and then call the method for comparing.
So what do I do to have for example "ove has deleted from 5 position".
Usage is explained in the API wiki and diff_match_patch.h.
The position isn’t contained in the Diff object. To obtain it, you could iterate over the list and calculate the change position:
Unchanged substrings and deletes increment the position by the length of the unchanged/deleted substring.
Insertions do not alter positions in the original string.
Deletes followed by inserts are actually replacements. In that case the insert operation happens at the same position where the delete occured, so that last delete should not increment the position.
i.e. something like this (untested):
auto diffResult = diff_main(str1, str2);
int equalLength = 0;
int deleteLength = 0;
bool lastDeleteLength = 0; // for undoing position offset for replacements
for (const auto & diff : diffResult) {
if (diff.operation == Operation.EQUAL) {
equalLength += diff.text.length();
lastDeleteLength = 0;
}
else if (diff.operation == Operation.INSERT) {
pos = equalLength + deleteLength - lastDeleteLength;
qDebug() << diff.toString() << "at position" << pos;
lastDeleteLength = 0;
}
else if (diff.operation == Operation.DELETE) {
qDebug() << diff.toString() << "at position" << equalLength + deleteLength;
deleteLength += diff.text.length();
lastDeleteLength = diff.text.length();
}
}

Why iterator is not dereferenced as an lvalue

Apologies if my question does not contain all relevant info. Please comment and I will amend accordingly.
I use CLion on Win7 with MinGW and gcc
I have been experimenting with circular buffers and came across boost::circular_buffer, but for the size of my project I want to use circular buffer by Pete Goodlife, which seems like a solid implementation in just one .hpp.
Note: I am aware of how to reduce boost dependecies thanks to Boost dependencies and bcp.
However, the following example with Pete's implementation does not behave as expected, i.e. the result to std::adjacent_difference(cbuf.begin(),cbuf.end(),df.begin()); comes out empty. I would like to understand why and possibly correct its behaviour.
Follows a MWE:
#include "circular.h"
#include <iostream>
#include <algorithm>
typedef circular_buffer<int> cbuf_type;
void print_cbuf_contents(cbuf_type &cbuf){
std::cout << "Printing cbuf size("
<<cbuf.size()<<"/"<<cbuf.capacity()<<") contents...\n";
for (size_t n = 0; n < cbuf.size(); ++n)
std::cout << " " << n << ": " << cbuf[n] << "\n";
if (!cbuf.empty()) {
std::cout << " front()=" << cbuf.front()
<< ", back()=" << cbuf.back() << "\n";
} else {
std::cout << " empty\n";
}
}
int main()
{
cbuf_type cbuf(5);
for (int n = 0; n < 3; ++n) cbuf.push_back(n);
print_cbuf_contents(cbuf);
cbuf_type df(5);
std::adjacent_difference(cbuf.begin(),cbuf.end(),df.begin());
print_cbuf_contents(df);
}
Which prints the following:
Printing cbuf size(3/5) contents...
0: 0
1: 1
2: 2
front()=0, back()=2
Printing cbuf size(0/5) contents...
empty
Unfortunately, being new to c++ I can’t figure out why the df.begin() iterator is not dereferenced as an lvalue.
I supsect the culprit is (or don't completely uderstand) the member call of the circular_buffer_iterator on line 72 in Pete's circular.h:
elem_type &operator*() { return (*buf_)[pos_]; }
Any help is very much appreciated.
The iterator you pass as the output iterator is dereferenced and treated as an lvalue, and most probably the data you expect is actually stored in the circular buffer's buffer.
The problem is, that apart from the actual storage buffer, most containers also contain some internal book-keeping state that has to be maintained. (for instance: how many elements is in the buffer, how much frees space is left etc).
Dereferencing and incrementing the container doesn't update the internal state, so the container does not "know" that new data has been added.
Consider the following code:
std::vector<int> v;
v.reserve(3);
auto i = v.begin();
*(i++) = 1; // this simply writes to memory
*(i++) = 2; // but doesn't update the internal
*(i++) = 3; // state of the vector
assert(v.size() == 0); // so the vector still "thinks" it's empty
Using push_back would work as expected:
std::vector<int> v;
v.reserve(3);
v.push_back(1); // adds to the storage AND updates internal state
v.push_back(2);
v.push_back(3);
assert(v.size() == 3); // so the vector "knows" it has 3 elements
In your case, you should use std::back_inserter, an iterator that calls "push_back" on a container every time it is dereferenced:
std::adjacent_difference(
cbuf.begin(), cbuf.end(),
std::back_inserter(df));
std::adjacent_difference writes to the result iterator. In your case, that result iterator points into df, which has a size of 0 and a capacity of 5. Those writes will be into the reserved memory of df, but will not change the size of the container, so size will still be 0, and the first 3 ints of the reserved container space will have your difference. In order to see the results, the container being written into must already have data stored in the slots being written to.
So to see the results you must put data into the circular buffer before the difference, then resize the container to the appropriate size (based in the iterator returned by adjacent_difference.

How to chain delete pairs from a vector in C++?

I have this text file where I am reading each line into a std::vector<std::pair>,
handgun bullets
bullets ore
bombs ore
turret bullets
The first item depends on the second item. And I am writing a delete function where, when the user inputs an item name, it deletes the pair containing the item as second item. Since there is a dependency relationship, the item depending on the deleted item should also be deleted since it is no longer usable. For example, if I delete ore, bullets and bombs can no longer be usable because ore is unavailable. Consequently, handgun and turret should also be removed since those pairs are dependent on bullets which is dependent on ore i.e. indirect dependency on ore. This chain should continue until all dependent pairs are deleted.
I tried to do this for the current example and came with the following pseudo code,
for vector_iterator_1 = vector.begin to vector.end
{
if user_input == vector_iterator_1->second
{
for vector_iterator_2 = vector.begin to vector.end
{
if vector_iterator_1->first == vector_iterator_2->second
{
delete pair_of_vector_iterator_2
}
}
delete pair_of_vector_iterator_1
}
}
Not a very good algorithm, but it explains what I intend to do. In the example, if I delete ore, then bullets and bombs gets deleted too. Subsequently, pairs depending on ore and bullets will also be deleted (bombs have no dependency). Since, there is only one single length chain (ore-->bullets), there is only one nested for loop to check for it. However, there may be zero or large number of dependencies in a single chain resulting in many or no nested for loops. So, this is not a very practical solution. How would I do this with a chain of dependencies of variable length? Please tell me. Thank you for your patience.
P. S. : If you didn't understand my question, please let me know.
One (naive) solution:
Create a queue of items-to-delete
Add in your first item (user-entered)
While(!empty(items-to-delete)) loop through your vector
Every time you find your current item as the second-item in your list, add the first-item to your queue and then delete that pair
Easy optimizations:
Ensure you never add an item to the queue twice (hash table/etc)
personally, I would just use the standard library for removal:
vector.erase(remove_if(vector.begin(), vector.end(), [](pair<string,string> pair){ return pair.second == "ore"; }));
remove_if() give you an iterator to the elements matching the criteria, so you could have a function that takes in a .second value to erase, and erases matching pairs while saving the .first values in those being erased. From there, you could loop until nothing is removed.
For your solution, it might be simpler to use find_if inside a loop, but either way, the standard library has some useful things you could use here.
I couldn't help myself to not write a solution using standard algorithms and data structures from the C++ standard library. I'm using a std::set to remember which objects we delete (I prefer it since it has log-access and does not contain duplicates). The algorithm is basically the same as the one proposed by #Beth Crane.
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
#include <string>
#include <set>
int main()
{
std::vector<std::pair<std::string, std::string>> v
{ {"handgun", "bullets"},
{"bullets", "ore"},
{"bombs", "ore"},
{"turret", "bullets"}};
std::cout << "Initially: " << std::endl << std::endl;
for (auto && elem : v)
std::cout << elem.first << " " << elem.second << std::endl;
// let's remove "ore", this is our "queue"
std::set<std::string> to_remove{"bullets"}; // unique elements
while (!to_remove.empty()) // loop as long we still have elements to remove
{
// "pop" an element, then remove it via erase-remove idiom
// and a bit of lambdas
std::string obj = *to_remove.begin();
v.erase(
std::remove_if(v.begin(), v.end(),
[&to_remove](const std::pair<const std::string,
const std::string>& elem)->bool
{
// is it on the first position?
if (to_remove.find(elem.first) != to_remove.end())
{
return true;
}
// is it in the queue?
if (to_remove.find(elem.second) != to_remove.end())
{
// add the first element in the queue
to_remove.insert(elem.first);
return true;
}
return false;
}
),
v.end()
);
to_remove.erase(obj); // delete it from the queue once we're done with it
}
std::cout << std::endl << "Finally: " << std::endl << std::endl;
for (auto && elem : v)
std::cout << elem.first << " " << elem.second << std::endl;
}
#vsoftco I looked at Beth's answer and went off to try the solution. I did not see your code until I came back. On closer examination of your code, I see that we have done pretty much the same thing. Here's what I did,
std::string Node;
std::cout << "Enter Node to delete: ";
std::cin >> Node;
std::queue<std::string> Deleted_Nodes;
Deleted_Nodes.push(Node);
while(!Deleted_Nodes.empty())
{
std::vector<std::pair<std::string, std::string>>::iterator Current_Iterator = Pair_Vector.begin(), Temporary_Iterator;
while(Current_Iterator != Pair_Vector.end())
{
Temporary_Iterator = Current_Iterator;
Temporary_Iterator++;
if(Deleted_Nodes.front() == Current_Iterator->second)
{
Deleted_Nodes.push(Current_Iterator->first);
Pair_Vector.erase(Current_Iterator);
}
else if(Deleted_Nodes.front() == Current_Iterator->first)
{
Pair_Vector.erase(Current_Iterator);
}
Current_Iterator = Temporary_Iterator;
}
Deleted_Nodes.pop();
}
To answer your question in the comment of my question, that's what the else if statement is for. It's supposed to be a directed graph so it removes only next level elements in the chain. Higher level elements are not touched.
1 --> 2 --> 3 --> 4 --> 5
Remove 5: 1 --> 2 --> 3 --> 4
Remove 3: 1 --> 2 4 5
Remove 1: 2 3 4 5
Although my code is similar to yours, I am no expert in C++ (yet). Tell me if I made any mistakes or overlooked anything. Thanks. :-)

Segmentation fault trying to dereference a pointer from a vector of pointers

I have a vector of pointers to objects that I am iterating through using std::vector::iterator`. Since the element returned is itself a pointer I dereference the iterator twice, once to return the pointer and once to resolve the pointer to the actual object.
I'm trying to invoke a member function (getClass) that returns an std::string and I have tried both (**it).getClass() and (*it)->getClass() but both give me a segmentation fault. I keep feeling like I'm missing something obvious.
partial function code:
void dataSet::createFolds()
{
// Shuffle the data vector
std::random_shuffle( m_records.begin(), m_records.end());
std::cout << "STARTING MAIN LOOP. THERE ARE " << m_records.size() << " RECORDS\n";
// iterate through the data vector and assign each to a fold
std::vector<dataRecord *>::iterator it = m_records.begin();
while (it != m_records.end())
{
std::string currentClass = (*it)->getClass(); // SEG FAULT HERE
.
.
.
}
.
.
.
}
The vector is m_records ... code
dataRecord is defined like this ... code
In response to questions about filling the vector:
The data is read from a text file and I really don't want to post the entire thing unless I have to (212 lines) but the pertinent code for populating the vector is below. The constructor for the dataRecord object takes a vector of field objects. I use a temporary pointer, use new to create the object then push_back the pointer.
while ...
{
std::vector<field> fields;
// build the fields vector
for (unsigned int i = 0; i < numAttribs; ++i)
fields.push_back(field(data.at(i), attribTypes[i]));
// create the new dataRecord
dataRecord * newRecord = new dataRecord(fields);
// add the record to the set
m_records.push_back(newRecord);
++recordNum;
std::cout << "read record " << recordNum << std::endl;
}
In my opinion the vector elements are badly initialized. Perhaps you have to test the code that fill the vector independently before testing to extract them. Sorry for my english ;)
Either the pointers in your containers are null, or they are dangling pointers to free'd memory.
Double check the code that fills m_records.
In
std::string dataRecord::getClass() {return m_data.at(m_data.size() - 1).getTextData();}
You must to verify m_data.size() because could be 0, so you will get an exception of out or range.
// create the new dataRecord
dataRecord * newRecord = new dataRecord(fields);
I'm guessing the bug is in dataRecord's constructor. Are you sure it's doing it's job properly?
This doesn't necessarily apply to the OP's question but for those arriving here from googling...
If you're receiving segfaults on dereferencing vector iterators and are working in multi-threaded applications, remember that vectors aren't necessary thread-safe!
The following example is unsafe without mutex locks.
Thread 1
myVector.push_back(new Object());
Thread 2
std::vector<Object*>::iterator = myVector.begin();
for (it; it != myVector.end(); it++) {
Object* obj = *it;
}
Instead, something like this should be done:
myMutex.lock();
myVector.push_back(new Object());
myMutex.unlock();
Thread 2
myMutex.lock();
std::vector<Object*>::iterator = myVector.begin();
for (it; it != myVector.end(); it++) {
Object* obj = *it;
}
myMutex.unlock();

Invalid heap error when trying to copy elements from a Map to a compatible priority Queue

My program makes a frequency map of characters (which I store in , surprise surprise, a Map), I am trying to copy each element from this map into a Priority Queue so that I can have a sorted copy of these values (I plan to make further use of the Q, that's why am not sorting the map) , but whenever I try to copy these values , the program executes fine for the first two or three iterations and fails on the fourth citing an "Invalid heap" error.
I'm not sure how to proceed from here, so I am posting the code for the classes in question.
#include "srcFile.h"
#include <string>
#include <iostream>
srcFile::srcFile(std::string s_flName)
{
// Storing the file name
s_fileName= s_flName;
}
srcFile::srcFile()
{
// Default constructor (never to be used)
}
srcFile::~srcFile(void)
{
}
void srcFile::dispOverallMap ()
{
std::map<char,int>::iterator dispIterator;
dispIterator = map_charFreqDistribution.begin();
charElement *currentChar;
std::cout<<"\n Frequency distribution map \n";
while(dispIterator != map_charFreqDistribution.end())
{
std::cout<< "Character : " << (int)dispIterator->first << " Frequency : "<< dispIterator->second<<'\n';
currentChar = new charElement(dispIterator->first,dispIterator->second);
Q_freqDistribution.push(*currentChar);
dispIterator++;
// delete currentChar;
}
while(!Q_freqDistribution.empty())
{
std::cout<<'\n'<<"Queue Element : " << (int)Q_freqDistribution.top().ch_elementChar << " Frequency : " << Q_freqDistribution.top().i_frequency;
Q_freqDistribution.pop();
}
}
map_charFreqDistribution has already been populated, if I remove the line
Q_freqDistribution.push(*currentChar);
Then I can verify that the Map is indeed there.
Also , both the Q and the use charElement as the template type , its nothing except the character and its frequency, along with 2 pointers to facilitate tree generation (unused upto this point)
Adding the definition of charElement on request
#pragma once
class charElement
{
public:
// Holds the character for the element in question
char ch_elementChar;
// Holds the number of times the character appeared in the file
int i_frequency;
// Left pointer for tree
charElement* ptr_left;
// Right pointer for tree
charElement* ptr_right;
charElement(char,int);
charElement(void);
~charElement(void);
void operator=(charElement&);
};
class compareCharElt
{
public:
bool operator()(charElement &operand1,charElement &operand2)
{
// If the frequency of op1 < op2 then return true
if(operand1.i_frequency < operand2.i_frequency) return true;
// If the frequency of op1 > op2 then return false
if(operand1.i_frequency > operand2.i_frequency)return false;
// If the frequency of op1 == op2 then return true (that is priority is indicated to be less even though frequencies are equal)
if(operand1.i_frequency == operand2.i_frequency)return false;
}
};
Definition of Map and Queue
// The map which holds the frequency distribution of all characters in the file
std::map<char,int> map_charFreqDistribution;
void dispOverallMap();
// Create Q which holds character elements
std::priority_queue<charElement,std::vector<charElement>,compareCharElt> Q_freqDistribution;
P.S.This may be a noob question, but Is there an easier way to post blocks of code , putting 4 spaces in front of huge code chunks doesn't seem all that efficient to me! Are pastebin links acceptable here ?
Your vector is reallocating and invalidating your pointers. You need to use a different data structure, or an index into the vector, instead of a raw pointer. When you insert elements into a vector, then pointers to the contents become invalid.
while(dispIterator != map_charFreqDistribution.end())
{
std::cout<< "Character : " << (int)dispIterator->first << " Frequency : "<< dispIterator->second<<'\n';
currentChar = new charElement(dispIterator->first,dispIterator->second);
Q_freqDistribution.push(*currentChar);
dispIterator++;
delete currentChar;
}
Completely throws people off because it's very traditional for people to have huge problems when using new and delete directly, but there's actually no need for it whatsoever in this code, and everything is actually done by value.
You have two choices. Pick a structure (e.g. std::list) that does not invalidate pointers, or, allocate all charElements on the heap directly and use something like shared_ptr that cleans up for you.
currentChar = new charElement(dispIterator->first,dispIterator->second);
Q_freqDistribution.push(*currentChar);
dispIterator++;
delete currentChar;
In the above code, you create a new charElement object, then push it, and then delete it. When you call delete, that object no longer exists -- not even in the queue. That's probably not what you want.