Qt Delete Items from QMultiHash while Iterating - qt

I want to delete items out of my QMultiHash. Looking at the docs, I believe I am doing it correctly but it always crashes after the first delete. What am I doing wrong?
Here is my code:
for (QMultiHash<int, Frame*>::iterator i = m_FrameBuffer.begin(); i != m_FrameBuffer.end(); ++i) {
if ( (frameNumber - i.key()) >= ( 5 ) ) { // Delete frames 5 frames old or more
qDebug() << "DELETE ==> Key:" << i.key() << "Value:" << i.value() << " Difference: " << (frameNumber - i.key());
int removed = m_FrameBuffer.remove(i.key());
qDebug() << "Removed this many: " << removed;
}
}
Here is the output:
FRAME COUNT: 1
FRAME COUNT: 2
FRAME COUNT: 3
FRAME COUNT: 4
FRAME COUNT: 5
DELETE ==> Key: 2 Value: Frame(0x138a400) Difference: 5
Removed this many: 1
The program has unexpectedly finished.

Your iterator becomes invalid after you remove items from a container while iterating it. Try this:
QList<int> keys = m_FrameBuffer.keys();
foreach (int key, keys)
{
int diff = frameNumber - key;
if (diff >= 5)
{
qDebug() << "DELETE ==> Key:" << key
<< "Value:" << m_FrameBuffer.value(key)
<< "Difference: " << diff;
int removed = m_FrameBuffer.remove(key);
qDebug() << "Removed this many: " << removed;
}
}
Also you can use QMutableHashIterator for it:
QMutableHashIterator<int, Frame*> it(m_FrameBuffer);
while (it.hasNext())
{
it.next();
int key = it.key();
int diff = frameNumber - it.key();
if (diff >= 5)
{
qDebug() << "Items to be removed:"
<< m_FrameBuffer.values(it.key()).size();
it.remove();
}
}

Related

Passing map by reference in C++ and mutating its value

I am passing map by reference in the canSum function where i am mutating its value and adding pairs but at the end when I iterate over the map I find the value of map has not been updated.
canSum function is a recursive function which takes a number (targetSum) and an array and finds if it is possible to form targetSum by any combinations of number in the array (numbers can be repeated).
#include<iostream>
#include<vector>
#include<map>
using namespace std;
bool canSum(int targetSum,vector<int> a,map<int, bool> &m){
if(!(m.find(targetSum) == m.end()))
return m[targetSum];
if (targetSum == 0)
return true;
if(targetSum<0)
return false;
for (int num : a)
{
if (canSum(targetSum - num, a,m)==true)
{
// m[targetSum] = true;
m.insert(pair<int, bool>(targetSum, true));
return m[targetSum];
}
}
m[targetSum] = false;
return m[targetSum];
}
int main(){
int targetSum, t;
vector<int> a;
map<int, bool> m;
m[0] = true;
cout << "enter target" << endl;
cin >> targetSum;
cout << "enter array, press esc to stop entering"<<endl;
while(cin>>t){
a.push_back(t);
}
for (int j = 0; j < a.size(); j++)
{
cout << a[j]<<" ";
}
cout << endl;
for (auto itr = m.begin(); itr != m.end(); ++itr) {
cout << '\t' << itr->first
<< '\t' << itr->second << '\n';
}
if(canSum(targetSum, a,m)){
cout << endl << "true" << endl;
}
else cout << endl << "false" << endl;
return 0;
}
Please help me. Thank you.
The for loop to print the map should be after the function call like.
if(canSum(targetSum, a,m)){
cout << endl << "true" << endl;
}
else cout << endl << "false" << endl;
for (auto itr = m.begin(); itr != m.end(); ++itr) {
cout << '\t' << itr->first
<< '\t' << itr->second << '\n';
}
Instead of
for (auto itr = m.begin(); itr != m.end(); ++itr) {
cout << '\t' << itr->first
<< '\t' << itr->second << '\n';
}
if(canSum(targetSum, a,m)){
cout << endl << "true" << endl;
}
else cout << endl << "false" << endl;
To see mutations in the map due to the function

Need help figuriing out correct syntax to update objects in global scope

I have this code:
int do_transact(ifstream & inFile, list<shared_ptr<Bike>> bikelist, status s)
{
int id, i = 0, size = bikelist.size();
float days;
string str, str2;
char name[50];
list<shared_ptr<Bike>>::iterator it = bikelist.begin();
if (s == NO_STATUS) //performs rental
{
inFile >> id;
inFile >> days;
inFile >> str;
inFile >> str2;
strcpy_s(name, str.c_str());
while (i < size)
{
if (id == (*it)->id_num) // rents bike
{
cout << "vvvvvv PERFORMING RENTAL vvvvvv" << endl << endl;
cout << "The price of this rental will be: $" << (days)*((*it)->cost_per_day) << endl;
strcpy_s((*it)->to_whom, name);
(*it)->rented_code = RENTED;
cout << "Thank you for your business!" << endl << endl;
return 0;
}
i++;
it++;
}
}
}
I am trying to change to_whom and rented_code in the original list, but it is not updating.
What is the syntax I need in order to change these values the way I need?

ifstream reading multiple data types from same line BAD_ACCESS

I'm trying to read in multiple element types from a text file.
Here's an example input:
push 0
push 1
push 3
push 5
add
push 3
The code below work until the last line, then I get a BAD_ACCESS error after trying anything after it reads in a line without 'b'. Any suggestions?
ifstream infile("example.txt");
while (!infile.eof())
{
infile >> a >> b;
if (a == "push")
push(b);
if (a == "add")
{
add();
}
if (a == "subtract")
{
int y = subtract();
cout << y << endl;
}
if (a == "multiply")
{
int y = multiply();
cout << y << endl;
}
if (a == "divide")
{
int y = divide();
cout << y << endl;
}
if (a == "pop")
{
cout << b;
b = NULL;
}
cout << a << b << endl;
}

trouble with output of recursive function

i'm having trouble getting the correct output of the function. The function output should show the expression. For example, if the input is "1234", then the output should be 1 + 2 + 3 + 4 = 10.
i can get the function to output the first part of the expression, but i'm not sure how to get it to output the sum as well.
heres what i have so far:
void sumDigits(int num, int &sum){
sum += num % 10;
if(num < 10)
cout << num;
else {
sumDigits(num/10, sum);
cout << " + " << num % 10;
}
}
why don't you do it in caller?
you could pass the remaining digits number to process to a function and output sum when it's 0, but I doing it in the caller is better..
<< can be chained. Try
cout << " + " << num % 10 << " = " << sum << endl;

QAbstractItemModel::data() is not called for all tree subitems

I have a QAbstractItemModel-derived class attached to a QTreeView.
Model implements 2 top-level rows and one of them has 3 sub-rows. Only first 2 sub-rows are displayed. If I add one “dummy” top-level row then everything is displayed.
I used qDebug() to print how many times QTreeView calls my model::data() and with what indexes (only Qt::DisplayRole cases are printed) and see that it is actually called 2 times for sub-rows instead of 3.
Of course, first suspicion is that my model::rowCount() is incorrect and makes QTreeView “think” that there are only 2 sub-rows. So here are qDebug() prints:
rowCount returning 3 for parent 0xbc6f70
…….
Qt::DisplayRole for row 0 ,column 0 pointer 0xbc6fc0 parent= 0xbc6f70
Qt::DisplayRole for row 1 ,column 0 pointer 0xbc7068 parent= 0xbc6f70
where 0xbc6f70 is:
parent.internalPointer() in model::rowCount(const QModelIndex &parent)
index.parent().internalPointer() in model::data(const QModelIndex &index, int role)
So why is model::data() being called for row 0 and row 1 but not for row 2 if model::rowCount() returned 3 for index with internalPointer() 0xbc6f70?
Here is the code:
int Model_Tree::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid())
{
// This is 1st level
qDebug() << "rowCount returning m_RowCount" << m_RowCount << "for !parent.isValid()" << parent.internalPointer() << "row" << parent.row() << "column" << parent.column();
return m_RowCount;
}
int column = parent.column();
if(0 != column)
{
qDebug() << "rowCount returning 0 for parent 0 != column (" << column << ")";
return 0; // only item at 0th column can have children
}
const TreeItem* pTreeItem = (const TreeItem*)parent.internalPointer();
if (0 == pTreeItem)
{
qDebug() << "rowCount returning 0 for parent 0==pTreeItem" << pTreeItem;
return 0;
}
qDebug() << "rowCount returning " << pTreeItem->m_Children.size() << "for parent " << pTreeItem << "type:" << pTreeItem->m_type;
return pTreeItem->m_Children.size();
}
QVariant Model_Tree::data(const QModelIndex &index, int role) const
{
if (!(index.isValid()))
{
return QVariant();
}
switch (role)
{
case Qt::TextAlignmentRole:
return Qt::AlignTop;
case Qt::DisplayRole:
void* p = index.internalPointer();
int column = index.column();
int row = index.row();
qDebug() << "Qt::DisplayRole for row " << row << ",column " << column << "pointer" << p << "parent=" << index.parent().internalPointer();
// .... the rest of Model_Tree::data implementation
}
and here is some qDebug() output:
rowCount returning 3 for parent **0x122ee138** type: 0
....
Qt::DisplayRole for row 0 ,column 0 pointer 0x122ee168 parent= **0x122ee138**
Qt::DisplayRole for row 1 ,column 0 pointer 0x122ee198 parent= **0x122ee138**
note 0x122ee138 - this is "internalPointer" value for parent node that contains 3 children
here are index() and parent() implementations:
QModelIndex Model_Tree::index(int row, int column, const QModelIndex &parent) const
{
void* p = 0;
if (!parent.isValid())
{
// This is 1st level
// we use our whole record
if (row < m_RowCount)
{
const TreeItem& treeItem = *(m_pRootItem->m_Children.at(row));
const LogRecord* pRecord = treeItem.m_pRecord;
const LogRecord& record = *pRecord;
if (column == 0)
{
p = (void*)&treeItem; // because createIndex() wants void* a 3rd parameter
}
else
{
const QList<QVariant>& fieldList = record.fieldList;
if (column <= fieldList.size())
{
const QVariant* pField = &(fieldList[column - 1]); // -1 Because we have extra column at left side
if ( (QMetaType::Type)(pField->type()) == QMetaType::QString )
{
//const QString *pString = static_cast<const QString*>(pField->data());
p = const_cast<void*>(pField->data());
}
if ( (QMetaType::Type)(pField->type()) == QMetaType::QStringList )
{
const QStringList *pStringList = static_cast<const QStringList*>(pField->data());
//const QString *pString = &(pStringList->at(0)) ;
p = const_cast<void*>( static_cast<const void*>( &(pStringList->at(0)) ) );
}
}
}
}
//qDebug() << "Creating index: " << row << ", " << column << ", " << p;
return createIndex(row, column, p);
}
if (0 != column)
{
//qDebug() << "Creating index: " << row << ", " << column << ", 0 -- if (0 != column)";
return createIndex(row, column, (void*)0);
}
p = parent.internalPointer();
const TreeItem* pTreeItem = (const TreeItem*)p;
if (0 == pTreeItem)
{
//qDebug() << "Creating index: " << row << ", " << column << ", 0 -- if (0 == pTreeItem)";
return createIndex(row, column, (void*)0);
}
if (row < pTreeItem->m_Children.size())
{
const TreeItem* pTreeSubItem = pTreeItem->m_Children.at(row).data();
//qDebug() << "Creating subline index: " << row << ", " << column << ", " << (void*)pTreeSubItem << "parent: " << pTreeItem;
return createIndex(row, column, (void*)pTreeSubItem);
}
//qDebug() << "Creating index: " << row << ", " << column << ", 0";
return createIndex(row, column, (void*)0);
}
QModelIndex Model_Tree::parent(const QModelIndex &index) const
{
if (!index.isValid())
{
QModelIndex qi;
qDebug() << "Creating INVACHILD PARENT index: " << qi.row() << ", " << qi.column() << ", " << 0;
return qi;
}
const TreeItem* pChildItem = static_cast<const TreeItem*>(index.internalPointer());
if (0 == pChildItem)
{
QModelIndex qi;
qDebug() << "Creating NOTREEITEM PARENT index: " << qi.row() << ", " << qi.column() << ", " << 0;
return qi;
}
const TreeItem* pParentItem = pChildItem->m_pParent;
if (0 == pParentItem)
{
QModelIndex qi;
qDebug() << "Creating NOPARENT PARENT index: " << qi.row() << ", " << qi.column() << ", " << 0;
return qi;
}
qDebug() << "Creating PARENT index: " << pChildItem->m_RecordNumber << ", " << 0 << ", " << pParentItem;
return createIndex(pParentItem->m_RecordNumber, 0, (void*)pParentItem);
}
QVariant Model_Tree::data(const QModelIndex &index, int role) const
{
if (!(index.isValid()))
{
return QVariant();
}
switch (role)
{
case Qt::TextAlignmentRole:
return Qt::AlignTop;
case Qt::DisplayRole:
void* pInternal = index.internalPointer();
int column = index.column();
int row = index.row();
if (0 == column)
qDebug() << "Qt::DisplayRole for row " << row << ",column " << column << "pointer" << pInternal << "parent=" << index.parent().internalPointer();
if (0 == pInternal)
{
//qDebug() << "DR: internal pointer is 0";
return QVariant();
}
if (0 == column)
{
const TreeItem* pTreeItem = static_cast<const TreeItem*>(pInternal);
QString displayString;
QTextStream(&displayString) << pTreeItem->m_LogLineNumber;
if (pTreeItem->m_type == TreeItem::Subline)
{
QTextStream(&displayString) << " (" << row << "-th sub-line)"
<< " " << (*(pTreeItem->m_pSubline));
}
if (pTreeItem->m_type == TreeItem::Record)
{
if (pTreeItem->m_Children.size() > 0)
{
QTextStream(&displayString) << " (" << rowCount(index)/*pTreeItem->m_Children.size()*/ << " sub-lines)";
}
}
return displayString;
}
// for columns other than 0 index contains QString* as internal pointer
const QString* pText = static_cast<const QString*>(pInternal);
return *pText;
}
return QVariant();
}
Thank you Marek for trying to help me!
The problem was in my QSortFilterProxyModel-derived class that didn't take into account sub-items )))

Resources