Qtvector content modification not happening - c++

I have a struct functionStruct and a QVector<functionStruct> . I am doing following..
when I click on a button the slot calls this function.
when I click 1st time it prints "somedoc" (expected)
but when I click 2nd time (and onwards) it prints nothing ( member is null)
int s = 0;
void foo()
{
if(!s) {
functionStruct *newp = new functionStruct;
functionStruct old = function_list.at(0);
newp->function_string.append(old.function_string);
newp->start = old.start;
newp->function_doc = "somedoc";
function_list.replace(0,*newp);
s = 1;
}
qDebug() << "pd0 contents " << function_list.at(0).function_doc
}

Related

QList request item from array not giving correct reference

Apologies if the title is incorrectly phrased - I am not too sure what is causing the problem
I am testing QList array access and came across this. It is a straight forward example of using referencing QList append() function and QList[] operator.
Aim:
I am trying to find out whether adding the same object (created with new) to 2 QList<int> and changing one of those objects (or references rather) will change the other.
What I found seems to indicate this is not true given my example and the output below:
// Some structure to simluate an object
struct IntStream {
int i;
};
// Create our lists
QList<IntStream> newlist = QList<IntStream>();
QList<IntStream> another = QList<IntStream>();
// Add 3 IntStream objects to the 2 lists using the same object, printing out the object and its reference
for (int i = 0; i < 3; i++) {
IntStream *s = new IntStream;
s->i = i;
newlist.append(*s);
another.append(*s);
qDebug() << QString("%1[%2] = %3 (").arg("newList", QString::number(i), QString::number(i)) << &another[i] << ")";
qDebug() << QString("%1[%2] = %3 (").arg("another", QString::number(i), QString::number(i)) << &another[i] << ")";
}
// Alter bject at index 1 with some arbitrary value
for (int i = 0; i < 3; i++) {
if(newlist.at(i).i == 1) {
qDebug() << "another[1] = " << &another[i];
qDebug() << "newList[1] = " << &newlist[i];
another[i].i = 4;
}
}
// Here, I should see the 2 values match, they do not
qDebug() << QString("%1 == %2 ???").arg(QString::number(newlist.at(1).i), QString::number(another.at(1).i));
The output of this is:
"newList[0] = 0 (" 0x27c75f88 )
"another[0] = 0 (" 0x27c75f88 )
"newList[1] = 1 (" 0x27c755d0 )
"another[1] = 1 (" 0x27c755d0 )
"newList[2] = 2 (" 0x27c75630 )
"another[2] = 2 (" 0x27c75630 )
another[1] = 0x27c755d0
newList[1] = 0x27c76ef0
"1 == 4 ???"
Should I expect to see 4 == 4 or did I do something wrong somewhere?
Notes:
I am using the T &QList::operator[](int i), not const T &QList::operator[](int i) const
Creating new objects rather than storing scoped objects
qDebug() << QString("%1[%2] = %3 (").arg("newList", QString::number(i), QString::number(i)) << &another[i] << ")";
qDebug() << QString("%1[%2] = %3 (").arg("another", QString::number(i), QString::number(i)) << &another[i] << ")";
You compared twice the &another[i]. You should write &newlist[i] instead in the first line.
And when you call newlist.append(*s); you made a copy of your IntStream instance.
To answer to your need :
"I am trying to find out whether adding the same object (created with new) to 2 QList and changing one of those objects (or references rather) will change the other."
Use a shared_ptr to shared your instance between multiple list.
Something like :
struct IntStream {
int i;
};
// Create our lists
QList<std::shared_ptr<IntStream >> newlist = QList<std::shared_ptr<IntStream >>();
QList<std::shared_ptr<IntStream >> another = QList<std::shared_ptr<IntStream >>();
// Add 3 IntStream objects to the 2 lists using the same object, printing out the object and its reference
for (int i = 0; i < 3; i++) {
std::shared_ptr<IntStream > s = std::make_shared<IntStream >();
s->i = i;
newlist.append(s);
another.append(s);

QT printing binary tree instruction messages

I am having an issue trying to display correct debugging messages in my GUI on qt. I am implementing a binary tree based on words that are entered by a user. And for each word that is entered an appropriate debugging message should display.
For example:
user enters : a
then user enters b
debugging message word is greater than a
The problem that I am having is that if the user was to then type a third word in the debugging message is incorrect.
user enters c
debugging message still displays as word is greater than a
But I would like it to display word is greater than b instead.
If the user inputs a duplicate word the message should display 'word' has already been detected. This message only works if its the original word that the user has entered and is duplicating. For the example above if the user enters a again the correct message appears. If they enter b again the duplicate message does not appear.
How can I fix this?
QStringList tree::VerboseModeinsert(NodePtr &ptr, QString aWord)
{
aWord.remove(QRegExp("[[]"));
aWord.remove(QRegExp("[]]"));
if(!(aWord.contains(QRegExp("[0123456789]"))))
{
aWord = aWord.toLower();
if(ptr != NULL)
{
if(aWord < ptr->word)
{
insert(ptr->below, aWord);
QString a = "Word is less than ";
QString b = ptr->word;
verboseList << a + b;
}
else if(aWord > ptr->word)
{
insert(ptr->above, aWord);
QString a = "Word is greater than ";
QString b = ptr->word;
verboseList << a + b;
}
else
{
ptr->occurence++;
QString c = " has already been detected";
verboseList << aWord + c;
}
}
else
{
ptr = new WordTree;
ptr->word = aWord;
ptr->below = NULL;
ptr->above = NULL;
ptr->occurence = 1;
}
}
return verboseList;
}
Seems you forgot to update the pointer to the last inserted,
Try this:
...
if(aWord < ptr->word)
{
...
ptr = ptr->below;
}
else if(aWord > ptr->word)
{
...
ptr = ptr->above;
}
...
PS: I'm not completly sure what I'm doing beacause you don'n provide a MCVE, but I think the post is suficient to infer that you are not changing the pointer to the last inserted.

Getting an error when i call a structure variable by using pointer with array subscription

// Menu Structure
struct Menu
{
char* name;
void (*func) ();
};
Menu* tmpPtr = NULL;
// Menu Function prototypes
void fileFunction();
void editFunction();
void viewFunction();
void exitFunction();
int main(int argc, char *argv[])
{
unsigned selection = 0 ;
Menu menuStruct[] = {
{"file", fileFunction},
{"edit", editFunction},
{"view", viewFunction},
{"exit", exitFunction} };
tmpPtr = menuStruct;
while(selection != 4)
{
for(int i = 0 ; i < 4 ; i++)
{
std::cout << i+1 <<" : " << tmpPtr->name << std::endl;
tmpPtr++;
}
tmpPtr = menuStruct;
std::cout<< "Enter Selection Value: " ;
std::cin>>selection;
if(selection <= 4)
*(tmpPtr[selection-1]->func)();
}
return 0;
}
Error received: base operand of '->' has non pointer type Menu
But it is working when i use (**(tmpPtr+selection-1)->func)(); as far as my knowledge both are same,
I donno why this error is coming, please help me to figure out the mistake am doing?
The line
*(tmpPtr[selection-1]->func)();
is a problem since the type of tmpPtr[selection-1] is Menu, not Menu*. You need to use:
*(tmpPtr[selection-1].func)();
Update
Due to operator precedence, the line
*(tmpPtr[selection-1].func)();
is the same as
*((tmpPtr[selection-1].func)());
Since the return type of Menu:func is void, that line is equivalent to:
*(void)
which is not right.
You can use:
(*tmpPtr[selection-1].func)();
or, simply:
tmpPtr[selection-1].func();

Synchronizing MapB to MapA in C++

I have a std::map that I generate from a json and a map that I generate from sqlite.
I want to compare the two maps and make changes to the sqlite so that it matches the json. I originally used the map.find(key) method through both maps to figure out what to add and what to delete but my friend told me that map was sorted from least to greatest key and so I could just run through it once.
I came up with two methods. Do you have any advice on which algorithm would be preferred and why? I am thinking the one I have uncommented is faster as (and please correct me if I'm wrong) I believe the uncommented one is O(n) worst case while the latter is O(n^2) worst case.
Also, my friend had mentioned that I didn't need the second 'clean up' while loop to reconcile the remaining sqlMap items, but I really think I need it. Is he right?
Here's my code:
void SqlSync::syncEvents() {
int added = 0;
int replaced = 0;
int deleted = 0;
int skipped = 0;
// get categories from Apsiva
std::map<int, Event> jsonMap = _apsivaRest->getEvents();
// get categories from sqlite
std::map<int, Event> sqlMap = _sqliteConnection->getEventMap(true);
// COMPARE
map<int, Event>::iterator jsonIter = jsonMap.begin();
map<int, Event>::iterator sqlIter = sqlMap.begin();
while (jsonIter != jsonMap.end() && sqlIter != sqlMap.end()) {
int jsonId = jsonIter->first;
Event jsonObj = jsonIter->second;
int sqlId = sqlIter->first;
if (jsonId < sqlId) {
// add
_sqliteConnection->addEvent(jsonObj);
++added;
++jsonIter;
} else if (jsonId > sqlId) {
// remove
_sqliteConnection->deleteEvent(sqlId);
++deleted;
++sqlIter;
} else {
if (jsonObj.isNewerThan(sqlIter->second)) {
_sqliteConnection->updateEvent(jsonObj);
++replaced;
} else {
// ignore
cout << "Skipped event b/c not newer" << endl; // delete when verified
++skipped;
}
++jsonIter;
++sqlIter;
}
}
// int jRemaining = std::distance(jsonIter, jsonMap.end());
// int sRemaining = std::distance(sqlIter, sqlMap.end());
// add remaining jsonMap Objects
while (jsonIter != jsonMap.end()) {
Event jsonObj = jsonIter->second;
_sqliteConnection->addEvent(jsonIter->second);
++added;
++jsonIter;
}
// delete remaining sqlMap Objects
while (sqlIter != sqlMap.end()) {
_sqliteConnection->deleteEvent(sqlIter->first);
++deleted;
++sqlIter;
}
// OLD WAY TO COMPARE.
// // add/replace keys found in json
// for (map<int, Event>::const_iterator jsonIter = jsonMap.begin(); jsonIter != jsonMap.end(); ++jsonIter) {
// map<int,Event>::const_iterator it = sqlMap.find(jsonIter->first);
// Event jsonObj = jsonIter->second;
// if (it != sqlMap.end()) {
// Event sqlObj = it->second;
// if (jsonObj.isNewerThan(sqlObj)) {
//// _sqliteConnection->updateEvent(jsonObj);
// ++replaced;
// } else {
// // ignore
// cout << "Skipped category b/c not newer" << endl; // delete when verified
// ++skipped;
// }
// } else {
//// _sqliteConnection->addEvent(jsonObj);
// ++added;
// }
// }
//
// // delete sqlmap CategoryRows not in jsonMap
// for (map<int, Event>::const_iterator sqlObj = sqlMap.begin(); sqlObj != sqlMap.end(); ++sqlObj) {
// if (jsonMap.find(sqlObj->first) == jsonMap.end()) {
//// _sqliteConnection->deleteEvent(sqlObj->first);
// ++deleted;
// }
// }
#ifdef DEBUG
cout << "CATEGORIES SYNC:" << endl;
cout << "---------------" << endl;
cout << "Added: " << added << " | Replaced: " << replaced
<< " | Deleted: " << deleted << " | Skipped: " << skipped << endl;
#endif //DEBUG
}
The uncommented way is more efficient. The complexity will be O(n+m) when n and m are sizes of json and SQLite maps.
You will need the last loop, since when you exit the first loop you don't know which map end you reached first. Consider next case - json map has ids 1,2,4,5 and SQLite has ids 1,2,6,7.
You will need the last loop in order to delete items 6 and 7.

Pointer becomes NULL immediately

I have the following LLVM code. The strange thing is that the si variable of type StoreInst becomes null(0) immediately after it is allocated with new instruction outside the if block, whereas I have declared it at an outer scope. What is going on here?
Value *OldVal = NULL;
StoreInst* si = NULL;
if ( ... )
{
if ( ... )
{
....
if ( ... )
{
...
StoreInst* si = new StoreInst(...);
errs() << "si = " << si << "\n"; // Get some address here
}
errs() << "-->SI = " << si << "\n"; // Here I get NULL, why?
}
...
}
I get an output like this,
si = 0x1822ba0
-->SI = 0x0
StoreInst* si = new StoreInst(...); - You hidden the previos name si here
When the scope is ended } - you see the value of another pointer
Here is an example of what you did:
int val = 0; //first val
{
int val = 10; //other val (let's call it second)
cout << val; //second val
} // second val is destroyed here
cout << val; //first val
I've used int in the example for simplicity. Actually it can be any type