I have a map named monthly_volumes within an object's member function and every time it finishes making the assignments to the map's value fields, the values are reset to 0(the value i initialized the map with before)
for (auto i : monthly_volumes) {
i.second = get_monthly_volume(i.first, year);
cout << "Month check during loop" << i.first << ":" << i.second << endl;
}
for (auto i : monthly_volumes) {
//i.second = get_monthly_volume(i.first, year);
cout << "Month Check After loop" << i.first << ":" << i.second << endl;
}
This is the
Output of the code
You need to iterate through the map with a reference, like this:
for (auto &i : monthly_volumes)
// changes to i, changes monthly_volumes
Also, in c++17 you could use structured bindings to make the code easier to read:
for (auto &[k, v] : monthly_volumes) {
v = get_monthly_volume(k, year);
cout << "Month check during loop" << k << ":" << v << endl;
}
You need a reference to the map entries to change them. Your code is changing a copy of the map entry.
for (auto& i : monthly_volumes) {
i.second = get_monthly_volume(i.first, year);
cout << "Month check during loop" << i.first << ":" << i.second << endl;
}
Related
so I have a structure array with various variables.
struct Data
{
char name[11];
int ID;
int life;
int date;
float avgWindSpeed;
float avgRainFall;
int tornadoes;
int stormCategory;
};
I am looking to sort all the information based on char name[11]. The data that is stored in struct Data comes from a file named storms.txt. Currently, I have everything to make up perfectly but still struggling with sorting everything alphabetically. Also, I named my ofstream outfile and counter contains the total number of storms inside the file.
My current code is:
//--------------------------------------------------------------------------------------------------------------------------------------------------
//Start of Hurricane Level 1
int totalLevel1 = 0; //Will hold the number of storms that are level 1
//This is just setting the top part of the chart
outfile << setw(70) << "Hurricane Level 1" << endl << endl;
outfile << "Name" << setw(10) << "ID" << setw(20) << " Life " << setw(20) << " Average " << setw(20) << " Average " << setw(20) << "Tornadoes" << setw(19) << " Date " << endl;
outfile << " " << setw(10) << " " << setw(20) << "in days" << setw(20) << "wind speed" << setw(20) << "rain fall" << setw(20) << " spawned " << setw(20) << " " << endl;
outfile << endl << endl;
float avgLifeSpan, avgRainFall, avgTornadoes, avgWindSpeed, life = 0, rain= 0, tornado= 0, wind= 0;
//Starting to process the information and printing it in its proper location
for(int i = 0; i < counter; i++)
if(hurricanes[i].stormCategory == 1)
{
totalLevel1++;
life = life + hurricanes[i].life;
rain = rain + hurricanes[i].avgRainFall;
tornado = tornado + hurricanes[i].tornadoes;
wind = wind + hurricanes[i].avgWindSpeed;
outfile << hurricanes[i].name << setw(5) << hurricanes[i].ID << setw(15) << hurricanes[i].life << setw(21) << hurricanes[i].avgWindSpeed
<< setw(20) << hurricanes[i].avgRainFall << setw(19) << hurricanes[i].tornadoes << setw(21) << hurricanes[i].date << endl;
}
//Printing the extra information for HURRICANE LEVEL 1
outfile << endl << endl << "Total number of Level 1 hurricanes is " << totalLevel1 << "." << endl;
outfile << "Average Life span in days of Level 1 hurricanes is " << life / float(totalLevel1) << "." << endl;
outfile << "Average rain fall for Level 1 hurricanes is " << rain / float(totalLevel1) << "." << endl;
outfile << "Average tornadoes spawned for Level 1 hurricanes is " << tornado / float(totalLevel1) << "." << endl;
outfile << "Average wind speed for Level 1 hurricanes is " << wind / float(totalLevel1) << "." << endl;
outfile << endl << endl;
//End of the Hurricane Level 1
//--------------------------------------------------------------------------------------------------------------------------------------------------
How to do I make so that everything that gets printed out on the output file is sorted alphabetically with its correct information? Could someone give me some suggestions?
It depends on how you've defined hurricanes. If it is a C array, then you'll be wanting something like this:
std::sort(hurricanes, hurricanes + counter,
[](const Data& a, const Data& b) { return std::strcmp(a.name, b.name) < 0; });
If however it is a std::vector or std::array, then...
std::sort(hurricanes.begin(), hurricanes.end(),
[](const Data& a, const Data& b) { return std::strcmp(a.name, b.name) < 0; });
I don't see what type of container you use ( I suggest to use std::vector), but you may do couple of nice things to make you life easier in this code.
First overload operators in Data structure like:
ostream& operator<<(ostream& os, const Data& a_data) for easily sending your struct to ostream (without need of encapsulating all it's members).
bool T::operator <(const T2 &b) const; , bool T::operator >(const T2 &b) const; : for comparison in standard algorithms.
Take look at reference : link You will write it only once but could use it in every part of program.
Second suggestion is to use std::sort algorithm to sort your data structure.
std::sort(hurricanes.begin(), hurricanes.end(), greater<Data>());
Syntax of your code will be much easier to understand and read for you wen you come back to project in 6 (or so) months.
I am trying to display struct members of a list in OMNeT++, all members are displayed correctly unless the member which is of type const char*. I am confused because after three push_back in the list, when I display. All the members of the last pushed element is displayed correctly even the one of type const char*. But for the two first pushed elements, the member of type cont char* display nothing, garbage or "DETAIL (Ipv4)Drones.host[3].ipv4.ip".
Ipv4Address srcAddress = recMtlsd->getSrcAddress();
Ipv4Address dstAddress = recMtlsd->getDstAddress();
const char* position = recMtlsd->getPosition();
simtime_t time = recMtlsd->getTime();
int srcID = recMtlsd->getId();
EV_DEBUG << "Source : " << srcAddress << endl;
EV_DEBUG << "Destination : " << dstAddress << endl;
EV_DEBUG << "Position : " << position << endl;
EV_DEBUG << "Time : " << time << endl;
EV_DEBUG << "Source ID: " << srcID << endl;
// All precedent displays are working correctly
/*typedef struct Mtlsd{
Ipv4Address originatorAddr, destinationAddr;
const char *position;
int originatorId;
simtime_t time;
}MTLSD;*/
MTLSD recitem;
recitem.originatorAddr = srcAddress;
recitem.originatorId = srcID;
recitem.destinationAddr = dstAddress;
recitem.position = position;
recitem.time = time;
EV_DEBUG << "Source : " << recitem.originatorAddr << endl;
EV_DEBUG << "Destination : " << recitem.dstinationAddr << endl;
EV_DEBUG << "Position : " << recitem.position << endl;
EV_DEBUG << "Time : " << recitem.time << endl;
EV_DEBUG << "Source ID: " << recitem.srcID << endl;
// All precedent displays are working correctly
/*typedef struct Mtlsd_data{
list<MTLSD> q;
int ID;
}MTLSD_DATA;*/
list<MTLSD_DATA> mtlsd_file;
auto node = find_if(mtlsd_file.begin(), mtlsd_file.end(), [=] (MTLSD_DATA const& i){return (i.ID == srcID);});
bool found = (node != mtlsd_file.end());
if (!found)
{
MTLSD_DATA recdata;
recdata.ID = srcID;
recdata.q.push_back(recitem);
mtlsd_file.push_back(recdata);
EV_DEBUG << "For node " << srcID ;
for(auto claim=mtlsd_file.back().q.begin(); claim!=mtlsd_file.back().q.end();++claim)
{
EV_DEBUG << "(" << string(claim->position) << ", " << claim->time << ");" << endl;
}
// The precedent display works correctly
}
else
{
EV_DEBUG << "I already have data about the node " << node->ID << endl;
if (node->q.size() == 3)
{
EV_DEBUG << "I already have three time-location claim in the queue" << endl;
EV_DEBUG << "Here they are: ";
EV_DEBUG << "For node " << (*node).ID << endl;
for(auto fileclaim=(*node).q.begin(); fileclaim!=(*node).q.end();++fileclaim)
EV_DEBUG << "(" << string((*fileclaim).position) << ", " << (*fileclaim).time << ");" << endl;
EV_DEBUG << "I will delete the old one (" << node->q.front().position << ", " << node->q.front().time << ")" << endl;
node->q.pop_front();
}
node->q.push_back(recitem);
EV_DEBUG << "I have pushed this new one : (" << string(node->q.back().position) << ", " << node->q.back().time << ")" << endl;
}
EV_DEBUG << "Here they are all time-location claims in the queue : ";
for(auto fileclaims=node->q.begin(); fileclaims!=node->q.end();++fileclaims)
{
EV_DEBUG << "(" << string(fileclaims->position) << ", " << fileclaims->time << ");" << endl;
}
// The last element is displayed correctly, but those before not.
.
.
.
I have been at this for days now and I just can't seem to find out why my last two things won't print. The code is quite long so I won't post it all , but if you need it I am willing to provide the entire source.
Basically I call the print function after adding 1 element to each of the listed elements. It will print them all EXCEPT the last two Spouse and Child. Those two are the most complicated as they are their own lists as well. When I tested the for loop for child it showed that no matter how many children I add to the Vector it reads the size as 0. Why is this?
void AddressNode::PrintFull()
{
cout << setfill(' ') << endl;
cout << setw(15) << "UID " << "ID" << setfill('0') << setw(3) << id_ << setfill(' ')<< endl;
cout << setw(15) << "NAME:" << firstName_ << " " << lastName_ << endl;
cout << setw(15) << "Address1:" << address_ << endl;
cout << setw(15) << "City:" << city_<< " " << endl;
cout << setw(15) << "State:" << state_<< " " << endl;
cout << setw(15) << "Zip:" << zip_<< " " << endl;
cout << setw(15) << "Date_Birth:" << dob_<< " " << endl;
cout << setw(15) << "Date_Death:" << dod_<< " " << endl;
cout << setw(15) << "Date_Wedding:" << dow_<< " " << endl;
cout << setw(15) << "Spouse:" << (spouse_ ? spouse_->GetFirstName() : "") << " " << (spouse_ ? spouse_-> GetLastName() : "") << endl;
for(unsigned int i = 0; i < children_.size(); i++)
{
cout << setw(15) << "Child: " << i << ": " << children_[i]->GetFirstName()<< " " << children_[i]->GetLastName()<< endl;
}
}
private:
std::string firstName_;
std::string lastName_;
std::string city_ ;
std::string state_ ;
std::string zip_ ;
std::string dob_ ;
std::string dow_;
std::string dod_;
std::string address_;
std::string spouseTempString;
std::vector<AddressNode*> children_;
AddressNode* spouse_;
unsigned int id_;
void AddressNode::AddChild(AddressNode& child)
{
vector<AddressNode*>::iterator iter;
if((iter = find(children_.begin(), children_.end(), &child)) != children_.end())
return;
children_.push_back(&child);
if (spouse_)
spouse_->AddChild(child);
}
public:
AddressNode(const std::string& firstName, const std::string& lastName, int id)
: children_(), id_(id)
{
firstName_= "";
firstName_+= firstName;
lastName_="";
lastName_+= lastName;
}
There's not enough code here to tell, but passing an object by reference and then storing its address is always fishy.
If a stack object gets passed to that function you'll get all kind of weird results.
Since your error only occur on pointer objects, I'm even more inclined to think you've got memory management issues somewhere.
If you really want to store a pointer, pass the pointer in the first place, or pass a const reference and store a copy?
I am looking for an elegant solution to replacing a nodes pcdata using pugixml (version 1.6). For example, iterating through a node set and updating the child value to something.
pugi::xpath_node_set nodes = document.select_nodes("//a");
for (auto it = nodes.begin(); it != nodes.end(); it++)
{
std::cout << "before : " << it->node().child_value() << std::endl;
// SOME REPLACE GOES HERE
std::cout << "after : " << it->node().child_value() << std::endl;
}
I have used the:
it->node().append_child(pugi::node_pcdata).set_value("foo");
but as the name suggests it just appends the data but I can't find any functions along the lines of:
it->node().remove_child(pugi::node_pcdata);
Another note is that the attributes on the node are important and should remain unchanged.
Thanks for your help.
xml_text object is made for this purpose (among others):
std::cout << "before : " << it->node().child_value() << std::endl;
it->node().text().set("contents");
std::cout << "after : " << it->node().child_value() << std::endl;
Note that you can also use text() instead of child_value(), e.g.:
xml_text text = it->node().text();
std::cout << "before : " << text.get() << std::endl;
text.set("contents");
std::cout << "after : " << text.get() << std::endl;
This page has more details: http://pugixml.org/docs/manual.html#access.text
I have a map declared as follows
map<string, int> symbolTable;
if(tempLine.substr(0,1) == "("){
symbolTable.insert(pair<string, int>(tempLine, lineCount));
}
How do I std::cout all of the things in my symbol table?
In modern C++:
for (auto&& item : symbolTable)
cout << item.first << ": " << item.second << '\n';
If you only have access to a pre-C++11 compiler the code would be:
for ( map<string, int>::const_iterator it = symbolTable.begin(); it != symbolTable.end(); ++it)
cout << it->first << ": " << it->second << '\n';
Here's an alternative if your compiler isn't C++11 compliant:
for (map<string, int>::iterator it = symbolTable.begin();
it != symbolTable.end(); ++it)
{
cout << it->first << " " << it->second << endl;
}
And for completeness, if it is:
for (auto& s : symbolTable)
{
cout << s.first << " " << s.second << endl;
}
You can use a loop to print all the key/value pairs. The code following is an example in C++11
for (const auto& kv : symbolTable) {
std::cout << kv.first << " " << kv.second << '\n';
}
ps: Both of other two answers pay little attention to const, which is quite sad...