This is my first time using c++ and I am having trouble manipulating a set. The function is supposed to iterate through the set, find the pair of Regions* that have the least distance between them, insert a new Region* and remove the two selected Regions* from the list. However, when I call s.insert() the set will be updated, but when the outer while loops begins again the set size is still the original. I commented out the s.erase() lines, but I was having the same issue. I have tried creating a new set and working off the one that is passed. Any help would be greatly appreciated. I have a feeling it has something to with pointers.
Region* reduce(set<Region*>& ls) {
set<Region*> s = ls;
int i = 0;
std::set<Region*> remove;
while (i < 5) {
double cur_smallest = 0.0;
Region* smallest1 = new Region(0, 0, 0, 0);
Region* smallest2 = new Region(0, 0, 0, 0);
std::set<Region*>::iterator rIterator;
std::set<Region*>::iterator regionsIterator = s.begin();
while (regionsIterator != s.end()) {
Region* current = *regionsIterator;
if (s.size() == 1) {
return current;
}
rIterator = s.begin();
while (rIterator != s.end()) {
Region* c = *rIterator;
double d = c->distance(*current);
if (d < cur_smallest) {
cur_smallest = d;
smallest1 = c;
smallest2 = current;
}
else if (d == cur_smallest) {
if ((getArea(c) + getArea(current)) <= (getArea(smallest1) + getArea(smallest2))) {
smallest1 = c;
smallest2 = current;
}
}
rIterator++;
}
regionsIterator++;
}
Region tmp = *(smallest1,smallest2);
s.insert(&tmp);
//s.erase(smallest1);
//s.erase(smallest2);
cout << s.size();
i++;
}
Region tmp = *(smallest1,smallest2);
Region* tmp1 = new Region(tmp.x, tmp.y, tmp.width, tmp.height, tmp.r1, tmp.r2);
s.insert(tmp1);
Related
I am making a music player program using MFC.
I would like to add a function to select multiple values in the listbox and delete them, but I would like to ask for advice.
The option of the listbox is Extended, and multiple selection using the control keys is fine.
Among the methods of listbox, it seems to be possible to use SetSel, GetCursel, GetSelItems, etc, but I can't solve it.
I would appreciate it if you could give me a simple advice.
Thank you very much.
void CMFC_MP3Dlg::DeleteList(CStatus* head)
{
CFileFind finder;
CString strTemp;
CString strRemoveFile;
POSITION pos;
CStatus* pTemp = new CStatus();
CStatus* pPrev = new CStatus();
//int nSelCount = m_ListBox.GetCurSel();
//m_ListBox.GetText(nSelCount, strTemp);
LPINT lpSelItems = new int[m_nListBoxCount];
m_ListBox.GetSelItems(m_nListBoxCount, lpSelItems);
for (int nCount = 0; nCount <= m_nListBoxCount; nCount ++)
{
if(m_ListBox.SetSel(nCount,1))
{
m_ListBox.GetText(nCount, strTemp);
m_vec.push_back(strTemp);
}
}
std::vector<CString>::iterator iter;
for(iter = m_vec.begin(); iter != m_vec.end();)
{
strRemoveFile.Format(_T("C:\\MFC_MP3\\%s"), *iter);
BOOL bRet = finder.FindFile(strRemoveFile);
if(bRet)
{
if(DeleteFile(strRemoveFile))
{
pPrev = NULL;
pTemp = head;
if(pTemp == NULL)
{
return;
}
while(pTemp->m_strFileName != strTemp)
{
pPrev = pTemp;
pTemp = pTemp->m_right;
}
if(pTemp->m_strFileName == strTemp)
{
pPrev->m_right = pTemp->m_right;
pTemp->m_right->m_left = pPrev;
delete pTemp;
}
MessageBox(_T("삭제 성공!"));
ShowList();
}
else
{
MessageBox(_T("삭제 실패!"));
}
}
else
{
MessageBox(_T("File Not Found!"));
}
iter++;
}
}
Does this help?
void CChristianLifeMinistryPersonalCopiesDlg::BuildSelectedArray()
{
int i, iSize, *pIndex;
CString strText;
m_aryStrPublishers.RemoveAll();
// get selected count
iSize = m_lbPublishers.GetSelCount();
if (iSize > 0)
{
pIndex = new int[iSize];
m_lbPublishers.GetSelItems(iSize, pIndex);
for (i = 0; i < iSize; i++)
{
m_lbPublishers.GetText(pIndex[i], strText);
m_aryStrPublishers.Add(strText);
}
delete[] pIndex;
}
}
This works fine for me.
Note that your code is incomplete though. We don't see you specify what the count is of the selected items. And we don't see you reset your vector array before you begin.
Have you actually debugged your code to see where it fails?
I'm having a problem with the code attached below. Essentially it generates a huge memory leak but I can't see where it happens.
What the code does is receiving an array of strings, called prints, containing numbers (nodes) separated by ',' (ordered by desc number of nodes), finding other compatible prints (compatible means that the other string has no overlapping nodes 0 excluded because every print contains it) and when all nodes are covered it calculates a risk function on the basis of a weighted graph. In the end it retains the solution having the lowest risk.
The problem is that leak you see in the picture. I really can't get where it comes from.
Here's the code:
#include "Analyzer.h"
#define INFINITY 999999999
// functions prototypes
bool areFullyCompatible(int *, int, string);
bool contains(int *, int, int);
bool selectionComplete(int , int);
void extractNodes(string , int *, int &, int);
void addNodes(int *, int &, string);
Analyzer::Analyzer(Graph *graph, string *prints, int printsLen) {
this->graph = graph;
this->prints = prints;
this->printsLen = printsLen;
this->actualResult = new string[graph->nodesNum];
this->bestResult = new string[graph->nodesNum];
this->bestReSize = INFINITY;
this->bestRisk = INFINITY;
this-> actualSize = -1;
}
void Analyzer::getBestResult(int &size) {
for (int i = 0; i < bestReSize; i++)
cout << bestResult[i] << endl;
}
void Analyzer::analyze() {
// the number of selected paths is at most equal to the number of nodes
int maxSize = this->graph->nodesNum;
float totRisk;
int *actualNodes = new int[maxSize];
int nodesNum;
bool newCycle = true;
for (int i = 0; i < printsLen - 1; i++) {
for (int j = i + 1; j < printsLen; j++) {
// initializing the current selection
if (newCycle) {
newCycle = false;
nodesNum = 0;
extractNodes(prints[i], actualNodes, nodesNum, maxSize);
this->actualResult[0] = prints[i];
this->actualSize = 1;
}
// adding just fully compatible prints
if (areFullyCompatible(actualNodes, nodesNum, prints[j])) {
this->actualResult[actualSize] = prints[j];
actualSize++;
addNodes(actualNodes, nodesNum, prints[j]);
}
if (selectionComplete(nodesNum, maxSize)) {
// it means it's no more a possible best solution with the minimum number of paths
if (actualSize > bestReSize) {
break;
}
// calculating the risk associated to the current selection of prints
totRisk = calculateRisk();
// saving the best result
if (actualSize <= bestReSize && totRisk < bestRisk) {
bestReSize = actualSize;
bestRisk = totRisk;
for(int k=0;k<actualSize; k++)
bestResult[k] = actualResult[k];
}
}
}
newCycle = true;
}
}
float Analyzer::calculateRisk() {
float totRisk = 0;
int maxSize = graph->nodesNum;
int *nodes = new int[maxSize];
int nodesNum = 0;
for (int i = 0; i < actualSize; i++) {
extractNodes(this->actualResult[i], nodes, nodesNum, maxSize);
// now nodes containt all the nodes from the print but 0, so I add it (it's already counted but misses)
nodes[nodesNum-1] = 0;
// at this point I use the graph to calculate the risk
for (int i = 0; i < nodesNum - 1; i++) {
float add = this->graph->nodes[nodes[i]].edges[nodes[i+1]]->risk;
totRisk += this->graph->nodes[nodes[i]].edges[nodes[i+1]]->risk;
//cout << "connecting " << nodes[i] << " to " << nodes[i + 1] << " with risk " << add << endl;
}
}
delete nodes;
return totRisk;
}
// -------------- HELP FUNCTIONS--------------
bool areFullyCompatible(int *nodes, int nodesNum, string print) {
char *node;
char *dup;
int tmp;
bool flag = false;
dup = strdup(print.c_str());
node = strtok(dup, ",");
while (node != NULL && !flag)
{
tmp = atoi(node);
if (contains(nodes, nodesNum, tmp))
flag = true;
node = strtok(NULL, ",");
}
// flag signals whether an element in the print is already contained. If it is, there's no full compatibility
if (flag)
return false;
delete dup;
delete node;
return true;
}
// adds the new nodes to the list
void addNodes(int *nodes, int &nodesNum, string print) {
char *node;
char *dup;
int tmp;
// in this case I must add the new nodes to the list
dup = strdup(print.c_str());
node = strtok(dup, ",");
while (node != NULL)
{
tmp = atoi(node);
if (tmp != 0) {
nodes[nodesNum] = tmp;
nodesNum++;
}
node = strtok(NULL, ",");
}
delete dup;
delete node;
}
// verifies whether a node is already contained in the nodes list
bool contains(int *nodes, int nodesNum, int node) {
for (int i = 0; i < nodesNum; i++)
if (nodes[i] == node)
return true;
return false;
}
// verifies if there are no more nodes to be added to the list (0 excluded)
bool selectionComplete(int nodesNum, int maxSize) {
return nodesNum == (maxSize-1);
}
// extracts nodes from a print add adds them to the nodes list
void extractNodes(string print, int *nodes, int &nodesNum, int maxSize) {
char *node;
char *dup;
int idx = 0;
int tmp;
dup = strdup(print.c_str());
node = strtok(dup, ",");
while (node != NULL)
{
tmp = atoi(node);
// not adding 0 because every prints contains it
if (tmp != 0) {
nodes[idx] = tmp;
idx++;
}
node = strtok(NULL, ",");
}
delete dup;
delete node;
nodesNum = idx;
}
You have forgotten to delete several things and used the wrong form of delete for arrays where you have remembered, e.g.
float Analyzer::calculateRisk() {
float totRisk = 0;
int maxSize = graph->nodesNum;
int *nodes = new int[maxSize];
//...
delete [] nodes; //<------- DO THIS not delete nodes
The simplest solution is to avoid using raw pointers and use smart ones instead. Or a std::vector if you just want to store stuff somewhere to index into.
You have new without corresponding delete
this->actualResult = new string[graph->nodesNum];
this->bestResult = new string[graph->nodesNum];
These should be deleted somewhere using delete [] ...
You allocate actualNodes in analyze() but you don't release the memory anywhere:
int *actualNodes = new int[maxSize];
In Addition, Analyzer::bestResult and Analyzer::actualResult are allocated in the constructor of Analyzer but not deallocated anywhere.
this->actualResult = new string[graph->nodesNum];
this->bestResult = new string[graph->nodesNum];
If you must use pointers, I really suggest to use smart pointers, e.g. std::unique_ptr and/or std::shared_ptr when using C++11 or later, or a Boost equivalent when using C++03 or earlier. Otherwise, using containers, e.g. std::vector is preferred.
PS: You're code also has a lot of mismatches in terms of allocation and deallocation. If memory is allocated using alloc/calloc/strdup... it must be freed using free. If memory is allocated using operator new it must be allocated with operator delete. If memory is allocated using operator new[] it must be allocated with operator delete[]. And I guess you certainly should not delete the return value of strtok.
I've this piece of code, which is called by a timer Update mechanism.
However, I notice, that the memory size of the application, while running, continuously increases by 4, indicating that there might be a rogue pointer, or some other issue.
void RtdbConnection::getItemList()
{
std::vector<CString> tagList = mItemList->getItems();
//CString str(_T("STD-DOL1"));
PwItemList* pil = mPwSrv->GetItemList();
CPwItem pw ;
for(auto it = tagList.begin(); it != tagList.end(); ++it)
{
pw = mPwSrv->GetItem(*it);
pil->AddItem(&(PwItem)pw);
}
pil->AddInfo(DB_DESC); //Description
pil->AddInfo(DB_QALRM); // Alarm Status
pil->AddInfo(DB_QUNAK); //UNACK status
pil->AddInfo(DB_AL_PRI); // Priority of the alarm tag
pil->ExecuteQuery();
int i = 0;
for (auto it = tagList.begin(); i < pil->GetInfoRetrievedCount() && it != tagList.end(); i+=4, it++)
{
//item = {0};
CString str(*it);
PwInfo info = pil->GetInfo(i);
CString p(info.szValue().c_str());
bool isAlarm = pil->GetInfo(i+1).bValue();
bool isAck = pil->GetInfo(i+2).bValue();
int priority = pil->GetInfo(i+3).iValue();
item = ItemInfo(str, p, isAlarm, isAck, priority);
//int r = sizeof(item);
mItemList->setInfo(str, item); // Set the details for the item of the List
}
delete pil;
pil = NULL;
}
I cannot seem to find a memory block requiring de-allocation here. Nor is there any allocation of memory when I step inside the following function :
mItemList->setInfo(str, item);
which is defined as :
void ItemList::setInfo(CString tagname, ItemInfo info)
{
int flag = 0;
COLORREF tempColour;
std::map<CString, ItemInfo>::iterator tempIterator;
if ( (tempIterator = mAlarmListMap.find(tagname)) !=mAlarmListMap.end() )
{
//remove the current iteminfo and insert new one
if(mAlarmListMap[tagname].getPriority() != info.getPriority() && (mAlarmListMap[tagname].getPriority()!=0))
{
mAlarmListMap[tagname].updatePriority(info.getPriority());
mAlarmListMap[tagname].mPrioChanged = TRUE;
}
else
{
mAlarmListMap[tagname].mPrioChanged = FALSE;
((mAlarmListMap[tagname].getPrevPriority() != 0)?(mAlarmListMap[tagname].ResetPrevPriority()):TRUE);
mAlarmListMap[tagname].setPriority(info.getPriority());
}
mAlarmListMap[tagname].setDescription(info.getDescription());
mAlarmListMap[tagname].setAlarm(info.getAlarmStat());
mAlarmListMap[tagname].setAlarmAck(info.getAckStat());
tempColour = mColourLogic->setUpdatedColour(mAlarmListMap[tagname].getAlarmStat(), mAlarmListMap[tagname].getAckStat(), flag);
mAlarmListMap[tagname].setColour(tempColour);
if(!(info.getAlarmStat() || info.getAckStat()))
{
flag = 1;
mAlarmListMap[tagname].mIsRTN = true;
mAlarmListMap[tagname].setDisplayCondition(false);
}
else
{
mAlarmListMap[tagname].setDisplayCondition(true);
}
//((mAlarmListMap[tagname].mIsRTN == true)?
}
else
{
tempIterator = mAlarmListMap.begin();
tempColour = mColourLogic->fillColourFirst(info.getAlarmStat(), info.getAckStat());
info.setColour(tempColour);
mAlarmListMap.insert(tempIterator, std::pair<CString,ItemInfo>(tagname,info));
}
}
I tried juggling with the allocations, but the increase is always a constant 4.
Could anyone kindly look and highlight where the issue could be?
Thanks a lot.
I'm trying to implement a simple k-d tree, but I'm either doing something wrong in terms of memory management, or that I'm trying to access something that isn't there (e.i. the program compiles, but crashes when I run it). Here is the part where I believe the problem is coming from:
void tree::addpoint (node* leaf, const my_vec &pointdata, int ref)
{
my_vec center(2);
int indicator;
indicator = findquad (leaf, pointdata);
if ( leaf->child[indicator] == NULL )
{
if ( (indicator%2) > 0)
center[0] = leaf->center[0] + leaf->boxsize/4;
else
center[0] = leaf->center[0] - leaf->boxsize/4;
if ( indicator > 1 )
center[1] = leaf->center[1] + leaf->boxsize/4;
else
center[1] = leaf->center[1] - leaf->boxsize/4;
leaf->child[indicator] = new node;
leaf->child[indicator]->point = pointdata;
leaf->child[indicator]->ref = ref;
leaf->child[indicator]->center = center;
leaf->child[indicator]->boxsize = leaf->boxsize/2;
leaf->child[indicator]->IsReal = true;
leaf->child[indicator]->child.resize(4);
for (int i=1; i<4; i++)
leaf->child[indicator]->child[i] = NULL;
}
else
addpoint (leaf->child[indicator], pointdata, ref);
if (leaf->IsReal)
{
leaf->IsReal = false;
addpoint (leaf, pointdata, ref);
}
}
int tree::findquad(node *leaf, const my_vec& pointdata)
// For a given node 'node', find the proper octraturequadrature for a point located at 'pointdata'.
{
bool north, east;
int indicator = 0, end;
end = pointdata.size() - 1;
east = pointdata[0] >= leaf->center[0];
north = pointdata[end] >= leaf->center[1];
if (east)
indicator = indicator + 2;
if (north)
indicator = indicator + 1;
return(indicator);
}
My feeble attempt at an A* Algorithm is generating unpredictable errors.
My FindAdjacent() function is clearly a mess, and it actually doesn't work when I step through it. This is my first time trying a path finding algorithm, so this is all new to me.
When the application actually manages to find the goal nodes and path (or so I think), it can never set the path (called from within main by pressing enter). I do not know why it is unable to do this from looking at the SetPath() function.
Any help would be hugely appreciated, here's my code:
NODE CLASS
enum
{
NODE_TYPE_NONE = 0,
NODE_TYPE_NORMAL,
NODE_TYPE_SOLID,
NODE_TYPE_PATH,
NODE_TYPE_GOAL
};
class Node
{
public:
Node () : mTypeID(0), mNodeCost(0), mX(0), mY(0), mParent(0){};
public:
int mTypeID;
int mNodeCost;
int mX;
int mY;
Node* mParent;
};
PATH FINDING
/**
* finds the path between star and goal
*/
void AStarImpl::FindPath()
{
cout << "Finding Path." << endl;
GetGoals();
while (!mGoalFound)
GetF();
}
/**
* modifies linked list to find adjacent, walkable nodes
*/
void AStarImpl::FindAdjacent(Node* pNode)
{
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
if (i != 0 && j != 0)
if (Map::GetInstance()->mMap[pNode->mX+i][pNode->mY+j].mTypeID != NODE_TYPE_SOLID)
{
for (vector<Node*>::iterator iter = mClosedList.begin(); iter != mClosedList.end(); iter++)
{
if ((*iter)->mX != Map::GetInstance()->mMap[pNode->mX + i][pNode->mY + j].mX && (*iter)->mY != Map::GetInstance()->mMap[pNode->mX + i][pNode->mY + j].mY)
{
Map::GetInstance()->mMap[pNode->mX+i][pNode->mY+j].mParent = pNode;
mOpenList.push_back(&Map::GetInstance()->mMap[pNode->mX+i][pNode->mY+j]);
}
}
}
}
mClosedList.push_back(pNode);
}
/**
* colour the found path
*/
void AStarImpl::SetPath()
{
vector<Node*>::iterator tParent;
mGoalNode->mTypeID = NODE_TYPE_PATH;
Node *tNode = mGoalNode;
while (tNode->mParent)
{
tNode->mTypeID = NODE_TYPE_PATH;
tNode = tNode->mParent;
}
}
/**
* returns a random node
*/
Node* AStarImpl::GetRandomNode()
{
int tX = IO::GetInstance()->GetRand(0, MAP_WIDTH - 1);
int tY = IO::GetInstance()->GetRand(0, MAP_HEIGHT - 1);
Node* tNode = &Map::GetInstance()->mMap[tX][tY];
return tNode;
}
/**
* gets the starting and goal nodes, then checks te starting nodes adjacent nodes
*/
void AStarImpl::GetGoals()
{
// get the two nodes
mStartNode = GetRandomNode();
mGoalNode = GetRandomNode();
mStartNode->mTypeID = NODE_TYPE_GOAL;
mGoalNode->mTypeID = NODE_TYPE_GOAL;
// insert start node into the open list
mOpenList.push_back(mStartNode);
// find the starting nodes adjacent ndoes
FindAdjacent(*mOpenList.begin());
// remove starting node from open list
mOpenList.erase(mOpenList.begin());
}
/**
* finds the best f
*/
void AStarImpl::GetF()
{
int tF = 0;
int tBestF = 1000;
vector<Node*>::const_iterator tIter;
vector<Node*>::const_iterator tBestNode;
for (tIter = mOpenList.begin(); tIter != mOpenList.end(); ++tIter)
{
tF = GetH(*tIter);
tF += (*tIter)->mNodeCost;
if (tF < tBestF)
{
tBestF = tF;
tBestNode = tIter;
}
}
if ((*tBestNode) != mGoalNode)
{
Node tNode = **tBestNode;
mOpenList.erase(tBestNode);
FindAdjacent(&tNode);
}
else
{
mClosedList.push_back(mGoalNode);
mGoalFound = true;
}
}
/**
* returns the heuristic from the given node to goal
*/
int AStarImpl::GetH(Node *pNode)
{
int H = (int) fabs((float)pNode->mX - mGoalNode->mX);
H += (int) fabs((float)pNode->mY - mGoalNode->mY);
H *= 10;
return H;
}
A few suggestions:
ADJACENCY TEST
The test in FindAdjacent will only find diagonal neighbours at the moment
if (i != 0 && j != 0)
If you also want to find left/right/up/down neighbours you would want to use
if (i != 0 || j != 0)
ADJACENCY LOOP
I think your code looks suspicious in FindAdjacent at the line
for (vector<Node*>::iterator iter = mClosedList.begin(); iter != mClosedList.end(); iter++)
I don't really understand the intention here. I would have expected mClosedList to start empty, so this loop will never execute, and so nothing will ever get added to mOpenList.
My expectation at this part of the algorithm would be for you to test for each neighbour whether it should be added to the open list.
OPENLIST CHECK
If you look at the A* algorithm on wikipedia you will see that you are also missing the section starting
if neighbor not in openset or tentative_g_score < g_score[neighbor]
in which you should also check in FindAdjacent whether your new node is already in the OpenSet before adding it, and if it is then only add it if the score is better.