Not the address I want content? - c++

I'm just getting more and more confused by wasting more time on my code. I just want the content of the iterator, not its address. Here is my code:
Peptides tempPep;
tempPep.set_PEPTIDE("AABF");
std::vector<Peptides>::iterator itPep = std::find_if (this->get_PepList().begin(), this->get_PepList().end(),boost::bind(&Peptides::Peptide_comparison, _1,tempPep));
if (itPep != this->get_PepList().end())
{
Spectra tempSp;
tempSp.set_Charge(1127);
tempSp.set_Snum(1);
std::cout << "without iterator "<< this->get_PepList()[0].get_New_S_num() << std::endl;
// output -> 0
std::cout << "with iterator" << itPep->get_New_S_num() <<std::endl;
//output -> 1129859637
}

Try changing your code to the following:
std::vector<Peptides> p = this->get_PepList();
std::vector<Peptides>::iterator itPep = std::find_if (p.begin(),
p.end(),boost::bind(&Peptides::Peptide_comparison, _1,tempPep));

If you want the content, point to it: *itPep
An iterator overloads the * operator and returns the data. (thanks for the correction, I did not know that!)

Related

QJsonArrays are not properly retrieved from QJsonObject

In the project I'm currently working on there I use Qt's JSON functionality to store the state of a graph, where every component of the system recursively calls the toJson-functions of its members for serialization. This works fine, but I run into a weird issue when deserializing the JSON file.
As a test that illustrates the problem, I've created the following example code:
#include <QtCore/QJsonArray>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtDebug>
int main() {
auto document{QJsonDocument::fromJson("{\n"
" \"o1\" : {\n"
" \"i1\" : [\"l1\", \"l2\", \"l3\"],\n"
" \"i2\": 3.14\n"
" },\n"
" \"o2\" : {\n"
" \"i2\": 2.718,\n"
" \"i1\" : [\"l1\", \"l2\", \"l3\"]\n"
" }\n"
"}")};
qDebug() << "is the document an object:" << document.isObject();
auto document_object{document.object()};
auto object_1_value{document_object.value("o1")};
qDebug() << "is o1 an object:" << object_1_value.isObject();
auto object_1{object_1_value.toObject()};
auto inner_1_value{object_1.value("i1")};
qDebug() << "is i1 an array:" << inner_1_value.isArray();
auto inner_1{inner_1_value.toArray()};
qDebug() << "i1:" << inner_1;
auto inner_1_inner_value{inner_1.at(0)};
qDebug() << "is i1[0] an array:" << inner_1_inner_value.isArray();
auto inner_1_inner{inner_1_inner_value.toArray()};
qDebug() << "i1[0]:" << inner_1_inner;
return 0;
}
Here, I am first querying o1, then try to get the array stored under i1.
However, I get the following output:
is the document an object: true
is o1 an object: true
is i1 an array: true
i1: QJsonArray([["l1","l2","l3"]])
is i1[0] an array: true
i1[0]: QJsonArray([["l1","l2","l3"]])
It seems like Qt stores the returned array into a useless one-element array; in my other code, at(0) solved the issue, but here even that does not work.
I would be very glad if someone could help me find a solution to reliably (and preferably hacklessly) read nested JSON arrays with Qt, as I truly do not understand the issue.
I am on Linux 5.6.11 with gcc 9.3.0 and Qt 5.14.2.
Your problem is the brace initialization. When you do assignment-style initialization instead, it works.
// instead of
auto inner_1{inner_1_value.toArray()};
// use
auto inner_1 = inner_1_value.toArray();
// same for all other brace inits
What I think happens is the classic clash between brace initialization and list initialization via a std::initializer_list constructor, in this case this one:
QJsonArray::QJsonArray(std::initializer_list<QJsonValue> args);
You want to brace-init a QJsonArray, but std::initializer_list takes precedence and what you actually instantiate is a QJsonArray with one item which is again a QJsonArray.
Often you see this problem explained with std::vector<int> and the two clashing ctors:
vector(size_type count);
vector(std::initializer_list<int> init);

list<pair<float,float>> iterating through a list that holds pairs?

As a part of runtime analysis I've got a small game that after calculating every Frame puts a new element in this list:
typedef std::list<std::pair<float, float>> PairList;
PairList Frames; //in pair: index 0 = elapsed time, index 1 = frames
The txt file is later used to draw a graph.
I decided to use a list, because while playing I do not need to process data held in the list and I think lists are the fastest containers when it comes to only adding or deleting items. As a next step I want to write the frames in an external txt file.
void WriteStats(PairList &pairList)
{
// open a file in write mode.
std::ofstream outfile;
outfile.open("afile.dat");
PairList::iterator itBegin = pairList.begin();
PairList::iterator itEnd = pairList.end();
for (auto it = itBegin; it != itEnd; ++it)
{
outfile << *it.first << "\t" << *it.second;
}
outfile.close();
}
With normal lists the pointer to "it" should return the item right?
Except visual studio says pair<float, float>* does not have a member called first
How do I want to do it then, when access via my iterator does not work? Is it because I pass in the reference to the list?
*it.first is parsed as *(it.first).
You need (*it).first or, better yet it->first.
Or, even better yet use range for:
for (auto& elem : pairList)
{
float a = elem.first;
}
I decided to use a list, because [...] I think lists are the fastest containers when it comes to only adding or deleting items.
The first go-to container should be std::vector. In practice it will outperform std::list even on algorithms that on paper should be faster on std::list because of cache locality. So I would test your theory with a good-ol benchmarking if performance is a concern.
The issue is one of operator precedence. Specifically, the member access operator '.' has higher precedence than indirection '*' so *it.first is effectively parsed as...
*(it.first)
Hence the warning. Instead use...
it->first
Use a range-based for loop instead of messing with iterators:
void WriteStats(const PairList &pairList)
{
// open a file in write mode.
std::ofstream outfile("afile.dat");
for (const auto &elem : pairList) {
outfile << elem.first << "\t" << elem.second << '\n';
}
}

return of an function is LPVOID or better a pointer to a list

i am using c++ to develope an extension for a tool we are using. from the api of the tool i call a function, which returns a LPVOID. from the documentation i know it is a list of pairs(int 16bit, int 32bit).
i know created a local pointer to this list with :
list<pair<INT16, INT32>> * ptrList = (list<pair<INT16, INT32>>*) functionToGetList();
now my question is how can i iterate trough the list?
std::list<pair<INT16, INT32>>::iterator * it;
for (it = *ptrList .begin(); it != ptrList .end(); it++) {
}
i tried something like this but just got the error call, that it has to be a class.
can someone pls help me with my problem?
with kind regards
for (auto const& item : *ptrList)
std::cout << item.first << ',' << item.second << '\n';

C++: vector size is wrong and higher than the number of elements

In my attempt to load .OBJ-files I load vertex data into std::vectors to send them to the GPU later. I fill three vectors, for normals, vertices and texture coordinates. The size of the normal vector is far higher than the size of the other two vectors, even if its filled with the same number of elements.
Code:
SceneTree* generateSceneTree(OBJScene* scene){
PostProcessing::triangulateFaces(scene);
SceneNode* node = new SceneNode;
vector<Vec<3>>& sceneNormals = scene->attributeData[Attribute::Normal];
vector<Vec<3>>& sceneVertices = scene->attributeData[Attribute::Position];
vector<Vec<3>>& sceneTexCoords = scene->attributeData[Attribute::TexCoord];
map<string,MaterialInfo*> mtls;
for(string s : scene->mtlLibs){
auto temp = loadMTL(s);
mtls.insert(temp.begin(),temp.end());
}
vector<Vec<3>> meshNormals; <-- creating vectors here.
vector<Vec<3>> meshVertices;
vector<Vec<2>> meshTexCoords;
for(auto g : scene->groups){
meshNormals.clear();
meshNormals.reserve(g.faces.size()*3);
meshVertices.clear();
meshVertices.reserve(g.faces.size()*3);
meshTexCoords.clear();
meshTexCoords.reserve(g.faces.size()*3);
AABB bBox;
cout << "num of faces: " << g.faces.size() << endl;
for(auto f : g.faces){
for(auto p : f.points){
uint vIndex = p.indices[Attribute::Position];
uint nIndex = p.indices[Attribute::Normal];
uint tIndex = p.indices[Attribute::TexCoord];
Vec<3> n = sceneNormals.at(nIndex);
Vec<3> v = sceneVertices.at(vIndex);
Vec<3> t = sceneTexCoords.at(tIndex);
meshNormals.push_back(n);
meshVertices.push_back(v);
meshTexCoords.push_back(t.toVec<2>());
bBox += meshVertices.back();
}
}
cout << "meshNormals size: " << meshNormals.size() << endl;
cout << "meshVertices size: " << meshVertices.size() << endl;
cout << "meshTexCoords size: " << meshTexCoords.size() << endl;
Mesh* m = new Mesh({
{meshVertices,Attribute::Position},
{meshNormals,Attribute::Normal},
{meshTexCoords,Attribute::TexCoord}
},GL_TRIANGLES);
SceneLeaf* leaf = new SceneLeaf;
leaf->nodeData = {Matrix4(),bBox};
leaf->leafData = {m, mtls[g.mtlName]};
node->addChild(leaf);
}
return node;
}
Output:
num of faces: 1087474
meshNormals size: 2958875950
meshVertices size: 3262422
meshTexCoords size: 3262422
This seems highly illogical. The program crashs afterwards with a std::bad_array_new_length exception because the Mesh class cant create an array of size 2958875950 to send to the GPU.
Update:
If I swap the declarations of meshVertices and meshNormals, meshVertices has the wrong size. So the first created vector is affected.
If I use std::list instead of std::vector, everything works.
If I comment out the ....reserve(g.faces.size()*3); lines, a std::bad_alloc is thrown.
My guess is that you have a memory corruption bug "somewhere" that is overwriting the meshNormals variable on the stack. The fact that swapping the meshNormals and meshVertices declarations leads to meshVertices becoming bad matches that theory.
To narrow in on the problem you can do a few things:
Comment out all lines in the inner for(auto p : f.points) loop and see if the error still occurs.
Assuming it doesn't, start uncommenting lines one-by-one until the error shows up again.
Try making a minimal, stand-alone test code example that duplicates the problem (it would help immensely if you did this before posting a SO question).
The simple answer is that your pointers at the start are pointing to somewhere else, either:
You are casting the "scene" structure.
You have junk or unset pointer in the scene structure for normal vector. Could be that you put junk there far before entring the function.
You did notice the 2958875950 is junk/negative integer?

std::vector<> assignment operation not working; need 'clear' operation first

I am confused by what I thought should be a very simple operation. I call a method that creates a std::vector and returns it. Then I set an existing std::vector to that result, expecting the = operator to work. The code looks like this:
std::vector<BTLECharDecl> charDeclList;
charDeclList.clear();
// get the services on the agent
// It loads the discovered services into the class variable 'serviceList'
if((result = discoverServices()) != rc_SUCCESS)
{
std::cout << "Discovering service failed. Function returned message "
<< eResultCode2str(result) << "(" << hex << result << dec << ")" << endl;
return result;
}
if(serviceList.size() > 0)
{
for(uint16 i = 0; i < serviceList.size(); i++)
{
// Get chararcteristic Declaration List as Objects for each service
startHandle = serviceList.at(i).getServiceData().startHandle;
endHandle = serviceList.at(i).getServiceData().endHandle;
if(startHandle < endHandle)
{
// !! WHY DO I NEED THIS clear()?? !!
charDeclList.clear();
charDeclList = discoverCharDecl(serviceList.at(i).getServiceData().startHandle, endHandle);
}
If I do not invoke the charDeclList.clear() method before the call to the method that returns this type of object, I will get leftover garbage from previous loops. Not always, but sometimes. I would have expected the assignment operator to completely replace whatever was there with that which is returned by the called method. What is wrong with my thinking? (Invoking the clear() solves the problem but it is unsettling.) Working with MS Visual Studio 2008.