Outputting a vector of of lists in C++ - 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 << ", ";
}

Related

Setter not changing the data from a vector within a class

In my program, I have a class that holds a vector of type integer. It is used to store distances. I have a function, that when called, should set values in the vector to 0's. (used for initializing). But when I go to check the size of the vector, it still says the vector is empty.
I have created multiple functions that check whether the vector is adding any elements, and it is not. I have a function, that within main, I call to see if the vector is empty, and it returns 0 (the vector has 0 elements in it).
int MLB::getDistanceSize()
{
return distances.size();
}
void MLB::setInitialDistances(int size)
{
for(int i = 0; i < size; i++)
{
this->distances.push_back(0);
}
}
class MLB
{
public:
//constructor
MLB();
~MLB();
int getDistanceSize();
void setInitialDistances(int size);
private:
vector<int> distances;
};
The input file is a csv file with each line consisting of:
stadium1,stadium2,distance
so sample input file is:
AT&T Park,Safeco Field,680
AT&T Park,Oakland–Alameda County Coliseum,50
Angel Stadium,Petco Park,110
Angel Stadium,Dodger Stadium,50
Busch Stadium,Minute Maid Park,680
Busch Stadium,Great American Ball Park,310
Busch Stadium,Target Field,465
Busch Stadium,Kauffman Stadium,235
etc...
I am using qt, and this is where I am calling the functions themselves. All information is stored into a map, and the other getters work perfectly fine. Sorry for making this a lot more confusing than the problem really is, any help is greatly appreciated.
// key and value, key is the team name, value is the MLB stadium information
struct entry
{
string key;
MLB value;
};
class Map
{
public:
//Public default constructor
Map();
//Public default destructor
~Map();
// returns entry of the map
entry atIndex(int index);
// Inserts a key and its value using linear algorithm
void insert(const string& theKey, const MLB& value);
private:
vector<entry> thisTable;
int currentSize; //Integer variable for current size
};
functions for Map:
Map::Map()
{
currentSize = 0;
}
Map::~Map()
{
}
void Map::insert(const string& theKey, const MLB& value)
{
entry thisEntry;
thisEntry.key = theKey;
thisEntry.value = value;
thisTable.push_back(thisEntry);
currentSize+=1;
}
entry Map::atIndex(int index)
{
return thisTable.at(index);
}
//mainwindow constructor
mainWindow::mainWindow()
{
//Reads in input from first csv file, all works fine all data stored and can access it
string iStadium1;
string iStadium2;
string iDistance;
string previous;
int distance;
int index1;
int index2;
bool found;
ifstream csvFile2;
csvFile2.open("inputDistance.csv");
getline(csvFile2, iStadium1, ',');
while(!csvFile2.eof())
{
index1 = 0;
found = false;
while(!found)
{
if(thisMap.atIndex(index1).value.getStadiumName() == iStadium1)
{
thisMap.atIndex(index1).value.setInitialDistances(thisMap.mapSize());
cout << "Distance Size Test 1: " << thisMap.atIndex(index1).value.getDistanceSize() << endl;
found = true;
}
else
{
index1++;
}
}
previous = iStadium1;
while(iStadium1 == previous)
{
getline(csvFile2, iStadium2, ',');
getline(csvFile2, iDistance, '\n');
distance = stoi(iDistance);
index2 = 0;
found = false;
while(!found)
{
if(thisMap.atIndex(index2).value.getStadiumName() == iStadium2)
{
found = true;
cout << "Distance Size Test 2: " << thisMap.atIndex(index1).value.getDistanceSize() << endl;
// crashes here. Index out of bounds, size is 0 for some reason
thisMap.atIndex(index1).value.setDistance(index2, distance);
}
else
{
index2++;
}
}
getline(csvFile2, iStadium1, ',');
}
}
csvFile2.close();
}
I expect the vector to hold 30 slots (assuming the desired size passed into the function is 30) of value 0, rather than having an empty vector.
The code in your question works as expected after adding constructor and destructor (doing both nothing) :
#include <iostream>
#include <vector>
using namespace std;
class MLB
{
public:
//constructor
MLB();
~MLB();
int getDistanceSize();
void setInitialDistances(int size);
private:
vector<int> distances;
};
int MLB::getDistanceSize()
{
return distances.size();
}
void MLB::setInitialDistances(int size)
{
for(int i = 0; i < size; i++)
{
this->distances.push_back(0);
}
}
MLB::MLB() {
}
MLB::~MLB() {
}
int main()
{
MLB mlb;
mlb.setInitialDistances(30);
cout << mlb.getDistanceSize() << endl;
}
pi#raspberrypi:/tmp $ g++ d.cc
pi#raspberrypi:/tmp $ ./a.out
30
the vector is not empty but contains 30 times 0
if thisMap.atIndex(index1).value.setDistance(index2, distance); does nothing this is probably because atIndex(index1) returns a copy rather than a reference, so you modify a copy and the original is unchanged
For instance :
#include <iostream>
#include <vector>
using namespace std;
class C {
public:
vector<int> getv() { return v; } // return a copy
vector<int> & getvref() { return v; } // return the ref to the vector, not a copy
int len() { return v.size(); }
private:
vector<int> v;
};
int main()
{
C c;
c.getv().push_back(0); // modify a copy of v
cout << c.len() << endl;
c.getvref().push_back(0); // modify v
cout << c.len() << endl;
}
Compilation and execution :
pi#raspberrypi:/tmp $ g++ vv.cc
pi#raspberrypi:/tmp $ ./a.out
0
1
you edited you question and this is what I supposed :
entry Map::atIndex(int index)
{
return thisTable.at(index);
}
return a copy, must be
entry & Map::atIndex(int index)
{
return thisTable.at(index);
}

Using Member Functions to Print Object

I have a class that contains a tree structure implemented by a vector< vector< Node > > where Node contains a bunch of attributes exposed via getters/setters.
class Tree
{
vector< vector< Node > > mGrid;
printTree(std::ostream& output = std::cout);
};
class Node
{
double property1 { return mProp1; }
double property2 { return mProp2; }
};
printTree() is currently hardwired to use property tstep:
void Tree::printTree( ostream& output )
{
...
for (unsigned t = 0; t < mGrid.size(); ++t)
{
toPrint = "";
for (unsigned state = 0; state < mGrid[t].size(); ++state)
{
toPrint += to_string_with_precision( mGrid[t][state].tstep(), 1 );
...
Is there some slick / convenient / object-oriented way of generalizing this function so that it can print out any of Node's properties (rather than only spitting out the hardwired tstep() property or essentially doing the same thing via if/then statements).
I've done things like this in C using function pointers, but this is C++ and the C++ FAQ says not to mess with pointers to member functions.
You might want template function:
class Tree
{
vector< vector< Node > > mGrid;
public:
template <typename F>
void ForEachNode(F&& f) {
int i = 0;
for (auto& v : mGrid) {
int j = 0;
for (auto& node : v) {
f(node, i, j);
++j;
}
++i;
}
}
};
Then you may do
void printTreeProp1(Tree& tree) {
tree.ForEachNode([](const Node& node, int i, int j) {
if (i != 0 && j == 0) {
std::cout << std::endl;
}
std::cout << node.property1() << " ";
});
}
1st op all you loops are ignoring the first element. vector is zero based and you are using ++t and ++state which increases the values on top of the loop. That means you are never accessing the 0th element (mGrid[0] and mGrid[t][0]).2nd, you did noy include the definition of tstep(), so we don't know what you are getting back. Assuming you want to print each dimension of your 2 dimension array, I think you have to break it to peaces. Something like this:
class Node
{
protected:
double mProp1;
double mProp2;
public:
double GetProp1(void) {return mProp1;}
double GetProp2(void) {return mProp2;}
String tStep(void) {return L"";} // add your code here
};
class NodeRow : public std::vector<Node>
{
public:
void Print(std::ostream& output)
{
iterator i;
String tStr;
for(i = begin(); i != end(); i++)
tStr += /*to_string_with_precision(*/i->tStep()/*, 1)*/;
output << tStr.c_str() << L"\r\n";
}
};
class Node2D : public std::vector<NodeRow>
{
public:
void Print(std::ostream& output = std::cout)
{
iterator i;
for(i = begin(); i != end(); i++)
i->Print(output);
}
};

getting error on vector<unique_ptr<X>> v

I´m quiet new on C++ and currently learning to understand smart pointers.Therefore I`m currently working on a little console-program for inserting,searching and deleting songs ... for learning purposes to get used to the stuff =)
Here is my code:
Song.hpp
#pragma once
#include <vector>
#include <memory>
#include <string>
class Song
{
public:
typedef std::unique_ptr<Song> pSong;
public:
Song();
~Song();
void setTitle(std::string title);
void setArtist(std::string artist);
void checkSong(std::string item, int iterator);
void get();
private:
std::string _title;
std::string _artist;
};
Song.cpp
#include "Song.hpp"
#include <iostream>
Song::Song()
{
}
Song::~Song()
{
}
void Song::setTitle(std::string title)
{
_title = title;
}
void Song::setArtist(std::string artist)
{
_artist = artist;
}
void Song::checkSong(std::string item, int iterator)
{
if (_artist == item || _title == item)
{
std::cout << "Item found on Slot: " << iterator << std::endl;
}
else
{
std::cout << "No item found!" << std::endl;
}
}
void Song::get()
{
std::cout << _artist << " - " << _title << std::endl;
}
Main.cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <memory>
#include "Song.hpp"
//prototype
void IntVector();
void SongVector();
Song* setSong(std::string title, std::string artist);
void find(std::string item, std::vector<Song::pSong> v);
std::vector<Song::pSong> SongList;
int main()
{
int k;
SongVector();
std::cin >> k;
return 0;
}
void IntVector()
{
// Create Vector
std::vector<std::unique_ptr<int>> v;
// Create a few unique_ptr<int> instances and fill them with ints
v.push_back(std::unique_ptr<int>(new int(30)));
v.push_back(std::unique_ptr<int>(new int(600)));
v.push_back(std::unique_ptr<int>(new int(200)));
v.push_back(std::unique_ptr<int>(new int(20)));
v.push_back(std::unique_ptr<int>(new int(200)));
v.push_back(std::unique_ptr<int>(new int(160)));
v.push_back(std::unique_ptr<int>(new int(4)));
v.push_back(std::unique_ptr<int>(new int(5)));
v.push_back(std::unique_ptr<int>(new int(315)));
// define vector<int> for storing values of the unique_ptr
std::vector<int> intList;
for (int i = 0; i < v.size(); i++)
{
// get memory-adress of each element
auto result = v[i].get();
// store value of result-pointer in Vector
intList.push_back(*result);
std::cout << *result << std::endl;
}
// Sort int of new Vector
std::sort(intList.begin(), intList.end());
// Loop through intList and cout
for (int i = 0; i < intList.size(); i++)
{
std::cout << intList[i] << std::endl;
}
}
void SongVector()
{
Song* first = setSong("Afroki","Steve Aoki");
Song* secound = setSong("Hype", "Steve Aoki");
Song* third = setSong("Madness", "Steve Aoki");
Song* fourth = setSong("Cake Face", "Steve Aoki");
SongList.push_back(Song::pSong(first));
SongList.push_back(Song::pSong(secound));
SongList.push_back(Song::pSong(third));
SongList.push_back(Song::pSong(fourth));
for (const auto& song : SongList)
{
song->get();
}
find("Madness", SongList);
}
Song* setSong(std::string title, std::string artist)
{
Song* song = nullptr;
song = new Song;
song->setArtist(artist);
song->setTitle(title);
return song;
}
void find(std::string item, std::vector<Song::pSong> v)
{
int i = 0;
for (const auto& song : v)
{
song->checkSong(item,i);
i++;
}
}
I got following error:
std::unique_ptr<Song,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function
1> with
1> [
1> _Ty=Song
1> ]
I found out, that this error only occurs, when calling my find(...)-method, so I´m guessing that somewhere in there is my mistake, but I just cant find out, what Ive done wrong. Would appreciate your help.
std::unique_ptr provide unique ownership (hense the name) which means beside other you cannot copy instance of std::unique_ptr - which would mean shared ownership. When you passing std::vector<std::unique_ptr<whatever>> by value you creating a copy of vector instance, which tries to copy each element. So simplest solution would be to pass std::vector instance by const reference (as you do not have intention to modify vector):
void find( const std::string &item, const std::vector<Song::pSong>& v);
beside fixing your problem passing by (const) reference is more efficient for non trivial objects, so you can also use it for std::string
in your intVector() function:
for (int i = 0; i < v.size(); i++)
{
// get memory-adress of each element
auto result = v[i].get();
// store value of result-pointer in Vector
intList.push_back(*result);
std::cout << *result << std::endl;
}
you do not really need to get raw pointer, just use std::unique_ptr itself:
for (int i = 0; i < v.size(); i++)
{
// get smart pointer for each element
const auto &result = v[i];
// store value of result-pointer in Vector
intList.push_back(*result);
std::cout << *result << std::endl;
}
void find(std::string item, std::vector<Song::pSong> v)
You need to pass vectors by reference. Add &.
void find(std::string item, std::vector<Song::pSong>& v)
Don't forget to also change the prototype of the function.

STXXL Dealing with strings

i am dealing with large dataset. May i ask you how it is possible to store strings in the classes i want to use with stxxl? I have read several discussions and everywhere was said that string is not POD type therefore it cannot be stored in the stxxl::vector, but i am not sure,because i tried it and i checked the data and everything seems to be fine. i have also saw an approach here https://github.com/Project-OSRM/osrm-backend/blob/725b93a961625a7b04d54806d7e0f80252a6bcd0/extractor/extraction_containers.hpp and they use stxxl::vector, so maybe the library got updated to support std::string?
class HighWay
{
private:
uint64_t id;
string name;
int speed;
string attributes; //additional attributes of way
string edges; //written uint64_t from,uint64_t to, int distance written as string
string nodes; //vector<uint64_t> written as string
public:
HighWay() = default;
void setId(uint64_t _id) {
id = boost::lexical_cast<string>(_id);
}
void setName(string _name) {
name = _name;
}
void setSpeed(int _speed) {
speed = _speed;
}
void setAttributes(string _attributes) {
attributes = _attributes;
}
void setEdges(string _edges) {
edges = _edges;
}
void setNodes(vector<uint64_t>refs) {
stringstream s;
uint64_t i = 0;
for (; i < refs.size()-1;i++) {
s << boost::lexical_cast<uint64_t>(refs[i]) << " ";
}
s << boost::lexical_cast<uint64_t>(refs[i]);
nodes = s.str();
}
uint64_t getId() {
return id;
}
string getName() {
return name;
}
int getSpeed() {
return speed;
}
string getAttributes() {
return attributes;
}
string getEdges() {
return edges;
}
std::vector<int64_t> getNodes() {
stringstream s(nodes);
uint64_t node;
std::vector<int64_t> result;
while (s >> node) {
result.push_back(static_cast<int64_t>(node));
}
return result;
}
};
I have also created code which stores the strings as POD,storing the string in vector of char and in map remembering lower and upper bound index in the array. But this approach leads to many std::maps used in the application.
//class to store in map
struct TypeName{
uint64_t start;
uint64_t end;
};
std::istream& operator >> (std::istream& i, TypeName& entry)
{
i >> entry.start;
i >> entry.end;
return i;
}
std::ostream& operator << (std::ostream& i, const TypeName& entry)
{
i << entry.start << " ";
i << entry.end;
return i;
}
struct PoiCategories{
uint64_t start;
uint64_t end;
};
std::istream& operator >> (std::istream& i,PoiCategories& entry)
{
i >> entry.start;
i >> entry.end;
return i;
}
std::ostream& operator << (std::ostream& i, const PoiCategories& entry)
{
i << entry.start << " ";
i << entry.end;
return i;
}
//object i want to store
struct Poi {
Poi() = default;
uint64_t id;
char type;
uint64_t id_in_pois; //id in vector pois
void addCategories(
vector<int> &kats, //categories to insert
stxxl::vector<uint64_t> &categories, //vector to store category
std::unordered_map <uint64_t, PoiCategories> &idPoi_categories //index to vector categories to retrieve all categories for Poi
)
{
size_t start = categories.size();
for (auto & kat : kats) {
categories.push_back(kat);
}
size_t end = categories.size() - 1;
idPoi_categories.insert(make_pair(id, PoiCategories{start, end }));
}
vector<int> getCategories(
stxxl::vector<uint64_t> &categories,
std::unordered_map <uint64_t, PoiKategorie> &idPoi_categories
)
{
std::vector<int> result;
PoiCategories bounds = idPoi_categories.find(id)->second;
for (size_t i = bounds.start; i <= bounds.end; i++) {
result.push_back(categories[i]);
}
return result;
}
};
Problem in my application is that i am storing a few string data, which are mainly names of streets and POIs. Maybe i am using wrong library. If so,can you recommend me a better approach to store data while preprocessing?
It's indeed banned, but the symptoms of violating the no-POD rule are generally unpredictable. It may very well appear to work as long as the strings all fit in memory, but in that case you didn't need the STXXL anyway.

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.