Iterating a vectors that are contained in a struct - c++

Struct that has multiple vectors within
struct data {
//char array1[20];
//char array2[20];
//char array3[20];
vector<string> playerID1;
vector<string> playerID2;
vector<string> overall;
}P1;
struct data P(string b) {
int i = 0;
player_attributes *tmp = new player_attributes;
tmp = head;
while (tmp != NULL) {
if (tmp->potential == b)
{
tmp->Id1 = P1.playerID1[i];
tmp->Id2 = P1.playerID2[i];
tmp->overrall_rating = P1.overall[i];
i++;
tmp = tmp->next;
}
return P1;
}
}
I used i++ initially but I kept getting a vector subscript error.
I really don't know how to iterator this to store values and access them later on.

You get error when i reaches end of vector. std::vector< >::operator[] does not do bound checking and does not create new elements. You have to make sure that you stop when end of vector reached.
Also, why struct of vectors? Why not a vector of structs? Organize it in this way:
#include <string>
#include <iostream>
#include <vector>
using std::string;
using std::vector;
struct data {
string playerID1;
string playerID2;
string overall;
data(const string &i1, const string &i2, const string &ov):
playerID1(i1),playerID2(i2),overall(ov) {}
};
vector<data> P1;
// a little demonsration
int main(int argc, const char *argv[])
{
P1.emplace_back("", "","test1");
P1.emplace_back("", "","test2");
for(auto it = P1.begin(); it != P1.end(); it++ )
{
std::cout << it->overall << std::endl;
}
}

Related

passing std::list from one function to another by value

I have a C++ program as given below. I am trying to pass a std::list from one function to another by value. I expect the list to be accessible in the caller function by means of an iterator? I expect that the return will call the copy constructor of std::list and it will be accessible in the caller. Is my assumption wrong ? If not why am I getting a segmentation fault.
#include <list>
#include <map>
#include <string>
#include <set>
#include <iterator>
#include <iostream>
const char *sy_path = "/var/log";
struct Setting
{
typedef std::list<const Setting*> List;
const char* path;
const char* filename;
const char* name;
int def;
int min;
int max;
struct Original
{
const char* filename;
const char* name;
Original(const char* filename_, const char* name_)
:filename(filename_), name(name_)
{
}
}original;
static const List settings();
};
const Setting::List Setting::settings()
{
const Setting c_settings[] =
{ //default min max
{ sy_path, "cs.cfg", "num_a", 1, 1, 29, Original("sys.cfg", "num_a") }
,{ sy_path, "cs.cfg", "num_b", 1, 1, 6, Original("sys.cfg", "num_b") }
,{ sy_path, "cs.cfg", "num_c", 1, 1, 29, Original("sys.cfg", "num_c") }
};
Setting::List lst;
int numelem = sizeof(c_settings) / sizeof(Setting);
for (int i = 0; i < numelem; i++)
{
const Setting & tmpSetting = c_settings[i];
lst.push_back(&tmpSetting);
}
return lst;
}
static int get_settings(void)
{
Setting::List lst;
lst = Setting::settings();
for (Setting::List::const_iterator it = lst.begin() ; it != lst.end(); ++it)
{
const Setting *cs = *it;
std::cout << "path: " <<cs->path << "filename: " <<cs->filename << "name: " << cs->name << std::endl;
}
}
int main()
{
get_settings();
return 0;
}
Yes, return lst; will return a copy of lst. The problem is that you put in lst pointers to data located on the stack (const Setting c_settings[] variable). These pointers become invalid once you return from function, hence the segmentation fault. The solution is to either allocate memory for your settings on heap, or use a std::list<Setting>.
typedef std::list<Setting> List;
lst.push_back(c_settings[i]); // make sure you have the right copy constructor
or
lst.push_back(new Setting(c_settings[i])); // make sure you have the right copy constructor
Also, I would avoid usage of const char * and use std::string instead.

XML Parsing using Structures in C++

I have tried to parse an xml file using tinyxml API in C++ through structure implementation, but my below code does not produce the result which i am expected. Below is the My code.
#include<iostream>
#include<list>
#include<string>
#include"tinyxml.h"
using namespace std;
struct accsys
{
string name;
string type;
float rate;
};
void parser(struct accsys acc)
{
list<accsys> l;
TiXmlDocument* doc= new TiXmlDocument();
doc->LoadFile("accountsys.xml");
TiXmlElement* root=doc->RootElement();
TiXmlElement* accountElement=root->FirstChildElement();
while(accountElement)
{
TiXmlElement* nameElement=accountElement->FirstChildElement();
acc.name=nameElement->GetText();
TiXmlElement* typeElement=nameElement->NextSiblingElement();
acc.type=typeElement->GetText();
TiXmlElement* rateElement=typeElement->NextSiblingElement();
acc.rate=atof(rateElement->GetText());
l.push_back(acc);
accountElement=accountElement->NextSiblingElement();
}
}
void display(struct accsys acc)
{
list<accsys> l;
list<accsys>::iterator i;
i=l.begin();
while(i!=l.end())
{
cout<<"name:"<<i->name<<endl;
cout<<"type:"<<i->type<<endl;
cout<<"rate:"<<i->rate<<endl;
i++;
}
}
int main()
{
struct accsys acc;
parser(acc);
display(acc);
return 0;
}
Can any one answer please!
Firstly, pass a reference to the std::list, not a empty struct, which won't live longer than in the function you make it. Neither can you make a list in one function and expect it to be there in another.
Fixed formatting, removed this ugly using namespace std;, and corrected your code. I assume this is what you want.
#include <iostream>
#include <list>
#include <string>
#include "tinyxml.h"
struct accsys
{
std::string name;
std::string type;
float rate;
};
void parser(std::list<accsys> &acc)
{
TiXmlDocument *doc = new TiXmlDocument();
doc->LoadFile("accountsys.xml");
TiXmlElement *root = doc->RootElement();
TiXmlElement *accountElement = root->FirstChildElement();
while (accountElement)
{
struct accsys structAcc;
TiXmlElement *nameElement = accountElement->FirstChildElement();
structAcc.name = nameElement->GetText();
TiXmlElement *typeElement = nameElement->NextSiblingElement();
structAcc.type = typeElement->GetText();
TiXmlElement *rateElement = typeElement->NextSiblingElement();
structAcc.rate = atof(rateElement->GetText());
acc.push_back(structAcc);
accountElement = accountElement->NextSiblingElement();
}
}
void display(std::list<accsys> &acc)
{
for (std::list<accsys>::iterator itr = acc.begin(); itr != acc.end(); ++itr)
{
std::cout << "name: " << itr->name << std::endl;
std::cout << "type: " << itr->type << std::endl;
std::cout << "rate: " << itr->rate << std::endl;
}
}
int main()
{
std::list<accsys> acc;
parser(acc);
display(acc);
return 0;
}
I can see at least 3 big errors in your code:
1) As marcinj has alrteady pointed out you are passing to your parser() function a copy of the struct accsys and whatever you fill in that structure you will never find it outside the function.
2) Again in parser you declare a list of your accsys struct which is local to the function, whatever you put in the list you will never see it outside the function, moreover in the while loop you keep overwriting values in your acc struct so even in the best case you would only see the last line of you xml file.
3) In the display function you pass an accsys struct to the function and the you forget it and try to print the content of a list of struct just created which is obviously empty.
So supposing the xml parser is correct your code would have to be more or less like this:
#include<iostream>
#include<list>
#include<string>
#include"tinyxml.h"
using namespace std;
struct accsys
{
string name;
string type;
float rate;
};
void parser(list<struct accsys *> &accList)
{
TiXmlDocument* doc= new TiXmlDocument();
doc->LoadFile("accountsys.xml");
TiXmlElement* root=doc->RootElement();
TiXmlElement* accountElement=root->FirstChildElement();
while(accountElement)
{
struct accsys *acc = new struct accsys;
TiXmlElement* nameElement=accountElement->FirstChildElement();
acc->name=nameElement->GetText();
TiXmlElement* typeElement=nameElement->NextSiblingElement();
acc->type=typeElement->GetText();
TiXmlElement* rateElement=typeElement->NextSiblingElement();
acc->rate=atof(rateElement->GetText());
l.push_back(acc);
accountElement=accountElement->NextSiblingElement();
}
}
void display(list<struct accsys *> &l)
{
list<struct accsys *>::iterator i;
i=l.begin();
while(i!=l.end())
{
cout<<"name:"<<i->name<<endl;
cout<<"type:"<<i->type<<endl;
cout<<"rate:"<<i->rate<<endl;
i++;
}
}
int main()
{
list <struct accsys *> acc;
parser(acc);
display(acc);
return 0;
}

Outputting a vector of of lists in C++

I'm having trouble outputting my vector of lists:
class index_table {
public:
index_table() { table.resize(128);}
void insert(string &, int );
private:
class entry
{
public:
string word;
vector <int> line;
};
vector< list <entry> > table;
};
I've got it so that it will fill up:
int main ()
{
index_table table;
string word,
int num = 5; //this is going to a random number. 5 is a temp. place holder.
while (cin >> word)
table.insert(word, num);
}
but how to output it? I've tried many different approaches, but a lot of them are giving me errors.
Do I have to overload the operator? I'm not entirely sure how I will be able to do it.
Assuming you really have a good reason to use std::vector< std::list<entry> >, then based on the given structure, printing of words might look like this:
class index_table {
public:
void print() {
for (size_t i = 0; i < table.size(); ++i) {
std::list<entry>::iterator li;
for (li = table[i].begin(); li != table[i].end(); ++li)
std::cout << li->word << " ";
}
}
...
private:
std::vector< std::list<entry> > table;
...
};
If your compiler supports C++11, you can use two range based nested for loops. Look in the function void index_table::dump().
// Output function
void index_table::dump() {
for (list<entry> &le : table) {
for (entry &e : le) {
e.dump();
}
}
}
I also created a function dump() in the entry class, which outputs the contents of two variables, which is now made private.
class index_table {
public:
index_table() {
table.resize(128);
}
void insert (int,string&,int);
void dump();
private:
class entry {
private:
string word;
int value;
public:
entry (string word, int value) {
this->word = word;
this->value = value;
}
void dump() {
cout << "Word/value is: " << word << "/" << value << endl;
}
};
vector< list <entry> > table;
};
void index_table::insert(int c, string &key, int value) {
//void index_table::insert(string &key, int value) {
entry obj(key, value);
table[c].push_back(obj);
}
// Output function
void index_table::dump() {
for (list<entry> &le : table) {
for (entry &e : le) {
e.dump();
}
}
}
int main (int argc, char **argv) {
index_table mytable;
string a = "String 0-A";
string b = "String 0-B";
string c = "String 1-A";
string d = "String 1-B";
string e = "String 6-A";
string f = "String 6-B";
mytable.insert(0, a, 1);
mytable.insert(0, b, 2);
mytable.insert(1, c, 3);
mytable.insert(1, d, 4);
mytable.insert(6, e, 3);
mytable.insert(6, f, 4);
mytable.dump();
}
Program outputs:
Word/value is: String 0-A/1
Word/value is: String 0-B/2
Word/value is: String 1-A/3
Word/value is: String 1-B/4
Word/value is: String 6-A/3
Word/value is: String 6-B/4
PS: I also changed your code a bit to make it run more easily for my test.
//This is the simple solution for outputting vector of lists.
#include <bits/stdc++.h>
using namespace std;
main()
{
vector<list<int>> my_vector; //creating vector of lists;
list<int> my_list;
for(int i = 0; i < 5; i++)
my_list.push_back(i);
my_vector.push_back(my_list); // pushing a list y to a vector
for (vector<list<int>>::iterator it = my_vector.begin(); it != my_vector.end(); ++it)
for (list<int>::iterator it2 = it->begin(); it2 != it->end(); ++it2)
cout << *it2 << ", ";
}

Fail to store values to the list

It seems the attribute test aisbn is successfully storing the data invoking setCode(), setDigit(). But The trouble starts failing while I attempt these values to store into list<test> simul
The list attribute takes the value of digit after setDigit() but the code. How can I put both code and digit into the list attribute? I can't see where the problem is. The code:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <list>
using namespace std;
class test
{
private:
string code;
int digit;
public:
//constructor
test(): code(""), digit(0) { }
//copy constructor
test(const test &other):
digit(other.digit)
{
for(unsigned int i=0; i < code.length(); i++)
code[i] = other.code[i];
}
//set up the private values
void setCode(const string &temp, const int num);
void setCode(const string &temp);
void setDigit(const int &num);
//return the value of the pointer character
const string &getCode() const;
const unsigned int getDigit() const;
};
const string& test::getCode() const
{
return code;
}
const unsigned int test::getDigit() const
{
return digit;
}
void test::setCode(const string &temp, const int num)
{
if((int)code.size() <= num)
{
code.resize(num+1);
}
code[num] = temp[num];
}
void test::setCode(const string &temp)
{
code = temp;
}
void test::setDigit(const int &num)
{
digit = num;
}
int main()
{
const string contents = "dfskr-123";
test aisbn;
list<test> simul;
list<test>::iterator testitr;
testitr = simul.begin();
int count = 0;
cout << contents << '\n';
for(int i=0; i < (int)contents.length(); i++)
{
aisbn.setCode(contents);
aisbn.setDigit(count+1);
simul.push_back(aisbn);
count++;
}
cout << contents << '\n';
/*for(; testitr !=simul.end(); simul++)
{
cout << testitr->getCode() << "\n";
}*/
}
It looks like you are having issues with your for loop, you need to modify your for loop like so:
for(testitr = simul.begin(); testitr !=simul.end(); testitr++)
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^
although, push_back does not invalidate iterators for std::list I think it is more readable to set the iterator where you are using it. Based on your response you also need to modify the copy constructor:
test(const test &other): code(other.code), digit(other.digit) {}
^^^^^^^^^^^^^^^^
how about using the vector
std::vector<test> simul;
for(int i=0; i < (int)contents.length(); i++)
{
aisbn.setCode(contents);
aisbn.setDigit(count+1);
simul.push_back(aisbn);
count++;
}
iterators, pointers and references related to the container are invalidated.
Otherwise, only the last iterator is invalidated.

C++ for_each loop can't find pointed to map element

I'm building a huffman coding program and when I try and run the code I have so far it just gives me a warning that the freq map object .begin() doesn't exist.
Huff.h
#ifndef HuffPuff_Huff_h
#define HuffPuff_Huff_h
//---Include---
#include <iostream>
#include <vector>
#include <set>
using namespace std;
//---Node---
struct Node {
int weight;
char litteral;
string symbol;
Node* childL;
Node* childR;
void set_node(int w, char l, Node* L, Node* R){
weight = w;
litteral = l;
childL = L;
childR = R;
}
bool operator>(Node & r){
if(this->weight > r.weight)
return true;
return false;
}
};
//---Code---
struct Code {
string symbol;
char content;
};
//---HuffClass---
class Huff {
private:
typedef pair<char, int> c_pair;
vector<Code> code;
string content;
void copy_to(c_pair c);
public:
Huff(string);
~Huff();
string compress();
bool set_content();
string get_content();
string get_compress();
};
#endif
Huff.cpp
//---Include---
#include <iostream>
#include <vector>
#include "Huff.h"
#include <map>
#include <set>
using namespace std;
//---|+ -|---
Huff::Huff(string c): content(c){}
Huff::~Huff(){}
//---Compress---
struct CopyTo {
vector<Node*>* & nodes;
CopyTo(vector<Node*>* & c):nodes(c){}
void operator()(pair<char, int> c){
Node * n = new Node;
n->set_node(c.second, c.first, NULL, NULL);
nodes->push_back(n);
}
};
void show_freq(pair<char, int> p) {
cout << p.first << "\t" << p.second << endl;
}
/*void show_freq(Node* p) {
cout << p->litteral << "\t" << p->weight << endl;
}*/
string Huff::compress(){
vector<Node *>* nodes; // Vector of nodes for later use
map<char, int>* freq = new map<char, int>; // Map to find weight of nodes
for(int i = 0; i < content.length(); i++)
(*freq)[content[i]]++;
for_each(freq->begin(), freq->end(), show_freq);
CopyTo copyto(nodes); //Copy map elements to nodes in this and next one
for_each(freq->begin(), freq->end(), copyto);
delete freq;
Node p;
while(nodes->size() != 1){ //Sorts nodes by weight and then removes two of them and replaces them with one
sort(nodes->begin(), nodes->end());
vector<Node *>::iterator beg = nodes->begin();
int w= (**beg).weight + (**beg++).weight;
Node* p = new Node;
p->set_node(w, '*', *nodes->begin(), *(nodes->begin()++));
nodes->erase(nodes->begin(), nodes->begin()+2);
nodes->push_back(p);
//for_each(nodes->begin(), nodes->end(), show_freq);
cout << "--------------" << endl;
}
Node* root = *nodes->begin();
return "110";
}
Main.cpp
int main(){
Huff mike("Testing-");
mike.compress();
}
Where is including of algorithm header?
online compiler
results
Compilation output:
source.cpp: In member function 'std::string Huff::compress()':
source.cpp:76:39: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
source.cpp:94:11: warning: unused variable 'root' [-Wunused-variable]
Execution output:
- 1
T 1
e 1
g 1
i 1
n 1
s 1
t 1