STXXL Dealing with strings - c++

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.

Related

LinkedQueue implementation used to store flights

I'm trying to implement a LinkedQueue Structure in c++ to store the data of some flights.
So, first of all I have to read a csv file, what provides the data to store.
The LinkedQueue must work this way: the atributes of each Flight has to be stored using the Flight class, and then the LinkedQueue must have a specific nodes called FlightNode to finally store flights.
My code isn't compiling because i can't implement the getNext() function in a correct way.
I'm giving my code below with the implementation of each class. If you guys can make any suggestion it will be very helpfull.
Thank you a lot!!
This is my header class for Flight.h:
class Flight {
public:
Flight();
virtual ~Flight();
string getID();
void setID(string new_id);
string getOrigen();
void setOrigen(string new_origen);
string getDesti();
void setDesti(string new_desti);
string getHora();
void setHora(string new_hora);
private:
string id;
string origen;
string desti;
string hora_sortida;
};
Flight.cpp:
Flight::Flight() {
}
Flight::~Flight() {
}
string Flight::getID(){
return id;
}
string Flight::getOrigen(){
return origen;
}
string Flight::getDesti(){
return desti;
}
string Flight::getHora(){
return hora_sortida;
}
void Flight::setID(string new_id){
id = new_id;
}
void Flight::setOrigen(string new_origen){
origen = new_origen;
}
void Flight::setDesti(string new_desti){
desti = new_desti;
}
void Flight::setHora(string new_hora){
hora_sortida = new_hora;
}
FlightNode.h:
class FlightNode {
public:
FlightNode(Flight& f);
FlightNode(const FlightNode& orig);
virtual ~FlightNode();
FlightNode* getNext();
void setNext(FlightNode* n);
Flight& getElement();
private:
Flight* _element;
FlightNode* _next;
};
FlightNode.cpp:
FlightNode::FlightNode(Flight& f) {
this->_element = &f;
this->_next = nullptr;
}
FlightNode::FlightNode(const FlightNode& orig) {
}
FlightNode::~FlightNode() {
}
FlightNode* FlightNode::getNext(){
return this->_next;
}
void FlightNode::setNext(FlightNode* n){
this->_next = n;
}
Flight& FlightNode::getElement(){
//Don't know how to implement this one, because I declared _element as a pointer but what I need here is to return a reference.
}
main.cpp:
string id;
string origen;
string desti;
string hora;
fstream fin;
fin.open("flights.csv", ios::in);
string line, word;
string id, origen, desti, hora;
while (getline(fin, line)) {
stringstream in(line);
Flight* new_flight = new Flight;
for (int i = 0; getline(in, word, ','); ++i) {
switch (i) {
case 0:
new_flight->setID(word);
break;
case 1:
new_flight->setOrigen(word);
break;
case 2:
new_flight->setDesti(word);
break;
case 3:
new_flight->setHora(word);
break;
}
}
cout << "id:" << new_flight->getID() << " origen:" << new_flight->getOrigen() << " desti: " << new_flight->getDesti() << endl;
queue.enqueue(*new_flight);
}
You can just return the reference behind the pointer:
return *_element;
However, if you plan to do so please ensure that the pointer is not null at the time of the above dereference.

C++ Indexing structs

I'm wondering if there is a way to index structs in order to run through the member variables in a for-loop. I'm asking repeatingly for stuff and get input via cin>>:
struct Fruits {
string name;
int weight, diameter, prize;
string colour, smell, taste;
}apple;
cout << "Apple Name?"; cin >> apple.name;
cout << "Apple weight?"; cin >> apple.weight;
.
.
you get the idea. I want sth like
vector<string> questions {"Apple Name?", "Apple weight?", ... };
for (int j = 0; j < "StructureSize of Fruits"; j++)
{
cout << questions[j]; cin >> apple.j; //apple.j is the key point I want to know
}
thank you very much!
you can't.
Arrays access works on the following way.
int A[4];
A[0] = 5;
A[1] = 7;
A[3] = 8;
You know a int (in some archytectures) use 4 bytes. So, the first element of A is in the address A, the next element of A is in the address A+4 what is equal to say A+sizeof(int)
When you do the first assignment A[0] the code is really something like A+sizeof(int)*0, in the next A[1] is something like A+sizeof(int)*1 If you see, any adjacent space of the array sums 4 bytes ( or sizeof(int) ) and goes on. If you see, you know that A have integers inside of it and you know the pattern to access each element the general pattern in a for loop would be A+sizeof(int)*j in your struct you don't know what is inside, you can't do A+sizeof(X)*j becouse X isn't fixed, so, if you want to do that you must implement it yourself, but It would be a pain becouse you have mixed datatypes.
If your struct is fixed, the strings for the user should also be fixed, then why you try to print them from a loop?, The vector need to allocate and that use spaces and gpu, I think is better if you just print each option and then read the user input.
You can.
But not without overkilling it.
#include <string>
#include <iostream>
#include <memory>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/for_each.hpp>
struct Fruit {
std::string name;
int weight, diameter, price;
std::string colour, smell, taste;
};
BOOST_FUSION_ADAPT_STRUCT(
Fruit,
(std::string, name)
(int, weight)
(int, diameter)
(int, price)
(std::string, colour)
(std::string, smell)
(std::string, taste)
)
std::array<char const *const, 7> questions = {
"Name ?",
"Weight ?",
"Diameter ?",
"Price ?",
"Colour ?",
"Smell ?",
"Taste ?"
};
int main() {
Fruit apple;
auto input = [i = std::size_t{0u}](auto &field) mutable {
do {
std::cout << questions[i] << ' ';
} while(!(std::cin >> field));
++i;
};
boost::fusion::for_each(apple, std::ref(input));
std::cout << "----------\n";
auto output = [i = std::size_t{0u}](auto const &field) mutable {
std::cout << questions[i] << ' ' << field << '\n';
++i;
};
boost::fusion::for_each(apple, std::ref(output));
}
I just learned that boost::fusion::for_each can't accept a mutable functor, hence the weird and a bit dangerous use of std::ref()... It's a shame, really.
Output :
Name ? Apple
Weight ? 150
Diameter ? 8
Price ? 1
Colour ? red
Smell ? good
Taste ? sweet
----------
Name ? Apple
Weight ? 150
Diameter ? 8
Price ? 1
Colour ? red
Smell ? good
Taste ? sweet
enum FruitValueProperty { weight=0, diameter, prize, lastValueProperty };
enum FruitStringProperty { name=0, colour, smell, taste, lastStringProperty };
struct Fruit {
int ValueProperty[3];
string StringProperty[4];
int Weight() { return ValueProperty[weight]; }
int Diameter() { return ValueProperty[diameter]; }
int Prize() { return ValueProperty[prize]; }
string Name() { return StringProperty[name]; }
string Colour() { return StringProperty[colour]; }
string Smell() { return StringProperty[smell]; }
string Taste () { return StringProperty[taste ]; }
};
Fruit fruit;
vector<string> questions {"Fruit weight?", ... "Fruit name?", ... };
for (int i=0; i<lastValueProperty; i++) {
cout << questions[j];
cin >> fruit.ValueProperty[i];
}
for (int j=0; i<lastStringProperty; i++) {
cout << questions[lastValueProperty+j];
cin >> fruit.StringProperty[j];
}
int dim = fruit.Diameter();
string sm = fruit.Smell();
If you used enums for the string properties (limiting the scope of what the values could be i.e an enum for names, enum for colors etc) then you could get your result by condensing the two loops down to one.
Alternatively you could have set property for the int values that takes a string and parses it to int and go that route but I honestly thing the above is the simplest and clearest means to almost achieve what you want.
This is my take on the matter using just vanilla c++ and evil macros and casts. Still definitely overkill though.
The basic plan is to provide an operator[] to return a variant-type proxy class which in turn handles the io streams.
This interface allows you the ability to expose the class members as you choose and in the order you want.
In order not to repeat myself and to avoid having the burden of keeping things in sync I declare the fields I want in a separate header and include the header twice but changing the macro between includes. If I now add a new field or remove one then I only have to change one place.
fruit_fields.h
//NO Header Guards desired since we want to include multiple times
DECLARE_FIELD(std::string, Fruit, name)
DECLARE_FIELD(int, Fruit, weight)
DECLARE_FIELD(int, Fruit, diameter)
DECLARE_FIELD(int, Fruit, prize)
DECLARE_FIELD(std::string, Fruit, colour)
DECLARE_FIELD(std::string, Fruit, smell)
DECLARE_FIELD(std::string, Fruit, taste)
Utility Classes
#include <iostream>
#include <string>
#include <assert.h>
#include <vector>
#include <array>
#include <typeinfo>
//TypeId info
namespace FieldType
{
static const size_t String = typeid(std::string).hash_code();
static const size_t Integer = typeid(int).hash_code();
};
/*
Field Proxy is a simple variant class
If you want to support more field types then more code is needed
*/
class FieldProxy
{
public:
FieldProxy(int* value)
: m_typeHash( typeid(int).hash_code() )
, m_intValue(value)
{}
FieldProxy(std::string* value)
: m_typeHash(typeid(std::string).hash_code())
, m_stringValue(value)
{}
operator int() const
{
assert(m_typeHash == typeid(int).hash_code());
return *m_intValue;
}
operator std::string() const
{
assert(m_typeHash == typeid(std::string).hash_code());
return *m_stringValue;
}
friend std::ostream& operator<<(std::ostream& os, const FieldProxy& field);
friend std::istream& operator>>(std::istream& os, FieldProxy& field);
private:
size_t m_typeHash;
union
{
int* m_intValue;
std::string* m_stringValue;
};
};
std::ostream& operator<<(std::ostream& os, const FieldProxy& field)
{
if (field.m_typeHash == FieldType::Integer)
{
os << *(field.m_intValue);
}
else if (field.m_typeHash == FieldType::String)
{
os << *(field.m_stringValue);
}
return os;
}
std::istream& operator>>(std::istream& is, FieldProxy& field)
{
if (field.m_typeHash == FieldType::Integer)
{
is >> *(field.m_intValue);
}
else if (field.m_typeHash == FieldType::String)
{
is >> *(field.m_stringValue);
}
return is;
}
//data to obtain pointer to given field
struct FieldInfo
{
size_t fieldType;
size_t offset;
};
Fruit Class
//The struct we actually care about
struct Fruit
{
public:
static size_t getNumberFields()
{
return m_numberFields;
}
FieldProxy operator[](size_t index);
private:
//First include just declares the class members as you might expect
// string name;
// int weight; etc
#define DECLARE_FIELD(t, c, f) t f;
#include "fruit_fields.h"
#undef DECLARE_FIELD
static FieldInfo m_fields[];
static const size_t m_numberFields;
};
//Work out where the fields are positioned in the class
FieldInfo Fruit::m_fields[] =
{
//second time around - define the macro to generate the data
//needed to build the FieldProxy
#define DECLARE_FIELD( t, c, f) {typeid(t).hash_code(), offsetof(c,f)},
#include "fruit_fields.h"
#undef DECLARE_FIELD
};
//calculate how many fields there are
const size_t Fruit::m_numberFields = sizeof(Fruit::m_fields) / sizeof(Fruit::m_fields[0]);
//Index to a FieldInfo object and use it to create a FieldProxy variant
FieldProxy Fruit::operator[](size_t index)
{
assert(index < m_numberFields);
auto& fieldInfo = m_fields[index];
if (fieldInfo.fieldType == FieldType::Integer)
{
return FieldProxy(reinterpret_cast<int*> (reinterpret_cast<char*>(this) + fieldInfo.offset));
}
else if (fieldInfo.fieldType == FieldType::String)
{
return FieldProxy(reinterpret_cast<std::string*> (reinterpret_cast<char*>(this) + fieldInfo.offset));
}
else
{
assert(false);
return FieldProxy((int*)nullptr);
}
}
Main
You can now index in to the fruit class quite simply:
int main()
{
Fruit apple;
std::array<std::string, 7> questions = {
"Name ?",
"Weight ?",
"Diameter ?",
"Price ?",
"Colour ?",
"Smell ?",
"Taste ?"
};
assert(questions.size() == Fruit::getNumberFields());
for (size_t index = 0; index < Fruit::getNumberFields(); ++index)
{
bool succeeded = false;
do {
std::cout << questions[index] << ' ';
if (!(std::cin >> apple[index]))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<int>::max(), '\n');
}
else
{
succeeded = true;
}
} while (!succeeded);
}
std::cout << "----------" << std::endl;
for (size_t index = 0; index < Fruit::getNumberFields(); ++index)
{
std::cout << questions[index] << ' ' << apple[index] << std::endl;
}
return 0;
}
OK it is long since the thread was started.
For indexing a Struct with values of same type I have written this code:
struct DataValues
{
int Value1;
int Value2;
int Value3;
int Value4;
int Value5;
int Value6;
int Value7;
int Value8;
// the operator
// return the reference to make it settable.
int& operator[](int n)
{
// the idea, get the pointer of the first element
// and treat it as an array
return (&Value1)[n];
}
};
usage:
int main()
{
DataValues values;
values.Value4 = 6;
values[1] = 3;
values[0] = sizeof(DataValues);
return 0;
}
The downside is that you have to check the input parameter to avoid accessing memory which does not belong to the struct.
Chears

C++ Block type is valid error

My code:
class item{
int plu;
char * name;
double price;
double inv;
public:
void setPLU(int g) { plu = g; }
void setName(const char * p) { name = copyStr(p); }
void setPrice(double g) { price = g; }
void setInventory(double g) { inv = g; }
int getPlu() { return plu; }
char*getName() { return name; }
double getPrice() { return price; }
double getInventory() { return inv; }
item(){
name = nullptr;
}
~item(){
delete name;
}
};
class puItem : public item{
bool type;
public:
void setType(bool g) { type = g; }
bool getType() { return type; }
};
class nodeU{
puItem fruit;
nodeU * next;
public:
nodeU * getNext(){ return next; }
puItem getFruit(){ return fruit; }
void setNext(nodeU * g){ next = g; }
void setFruit(puItem g) { fruit = g; }
nodeU(){
next = nullptr;
}
};
class linkedListU{
nodeU * head;
int size;
public:
nodeU * getHead(){
return head;
}
void setHead(nodeU * n){
head = n;
}
//Append
void appendNode(nodeU * n){
if (head == nullptr){
head = n;
}
else{
nodeU * iter = head;
while (iter){
iter = iter->getNext();
}
iter->setNext(n);
}
size++;
}
linkedListU()
{
head = nullptr;
size = 0;
}
puItem * pluLookup(int g){
nodeU * iter = head;
while (iter)
{
if ((iter->getFruit()).getPlu() == g)
return &(iter->getFruit());
iter = iter->getNext();
}
return nullptr;
}
};
void checkout(linkedListP, linkedListU);
linkedListU unitList;
linkedListP poundList;
nodeU * inputU=new nodeU;
int main()
{
ifstream infile;
ofstream outfile;
int tempPlu;
string tempName;
bool tempType;
double tempPrice, tempInv;
infile.open("products.txt");
puItem unit;
infile >> tempPlu;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempName;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempType;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempPrice;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempInv;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
if (tempType == 0){
unit.setInventory(tempInv);
unit.setName(tempName.c_str());
unit.setPLU(tempPlu);
unit.setType(tempType);
unit.setPrice(tempPrice);
inputU->setFruit(unit);
unitList.appendNode(inputU);
}
checkout(poundList, unitList);
system("pause");
return 0;
}
void checkout(linkedListU p){
int key = -10;
puItem * searchU=nullptr;
int counter = 0;
double total = 0;
double amount;
cout << "Enter the plu for the item you want or enter 0 to exit: ";
cin >> key;
while (key < 0)
{
cout << "\nInvalid input please re enter: ";
cin >> k
searchU = p.pluLookup(key);
}
while (key)
{
When it gets to the plu lookup it throws the error and I cant seem to find out why.
I know that that is error is for deleting something twice but I couldnt find any instance of that in this code.
There are a lot of issues with your code, where most of them are due to your classes not being safely copyable (they lack a user-defined copy constructor and assignment operator, and destructor). Please see the rule of 3:
What is The Rule of Three?
Your checkout function has the following prototype:
void checkout(linkedListU p){
This means that you are passing linkedListU by value. Since linkedListU failed to follow the rule of 3, when you pass this type by value, you will invoke the compiler-defined copy constructor which only makes shallow copies, thus causing undefined behavior.
Your linked list class has members that are pointers to dynamically allocated memory, and they need to be properly handled by following the Rule of 3 at the link above. Since you failed to do that, passing by value cannot be done safely.
To address this issue, you can pass the linked list by reference, not by value:
void checkout(linkedListU& p){
This will stop the copying to occur, but it really doesn't address the underlying issue of the rule of 3 not being used in any of your classes.
For example, your puItem is being returned by value in the puItem::getFruit function, and also passed by value in the puItem::setFruit function. Calling these functions without any changes also invokes undefined behavior due to these classes not being safely copyable (also due to you using members that point to dynamically allocated memory).
To address this issue, the first thing you can do is change the base class item to use std::string name; instead of char *name;. This makes item now a copyable class without having to write user-defined copy operations or to have a destructor that needs to delete name;. The reason is that once std::string is used, all of your members in item can be copied without user intervention. The compiler default version would suffice.
class item
{
int plu;
std::string name;
double price;
double inv;
public:
void setPLU(int g) { plu = g; }
void setName(const char * p) { name = p; }
void setPrice(double g) { price = g; }
void setInventory(double g) { inv = g; }
int getPlu() { return plu; }
std::string getName() { return name; }
double getPrice() { return price; }
double getInventory() { return inv; }
};
Note that there is no need for a destructor. Now, when puItem is derived from this class, puItem is also now safely copyable, and you can pass and return puItem by value:
class puItem : public item
{
bool type;
public:
void setType(bool g) { type = g; }
bool getType() { return type; }
};
Making these changes totally eliminates usage of these classes from causing heap errors, double deletion errors, or memory leaks. Any further errors concerning memory issues are now focused on your linked list class (which uses dynamically allocated memory). So the least, the problem is narrowed down by a huge amount and is now focused.

binary search string 2d arrays

My question is to find the string in 2d array and if it match display binary no.
Pience of my cide
string inst[37][3]={{"ld","00001","C2"},{"st","00011","C2"},{"la","00101","C2"},{"ldr","00010","C1"},
{"lar","00110","C1"},{"str","00100","C1"},{"add","01100"," "},{"addi","01101","C2"},
{"sub","01110"," "},{"neg","01111"," "},{"or","10110"," "},{"ori","10111","C2"},
{"and","10100"," "},{"andi","10101","C2"},{"not","11000"," "},{"shr","11010","C3"},
{"shra","11011","C3"},{"shl","11100","C3"},{"shc","11101","C3"},{"br","01000","C3"},
{"brl","01001","C3"},{"brlnv","01001"," "},{"brzr","01000"," "},{"brlzr","01001"," "},
{"not","11000"," "},{"brnz","01000"," "},{"brlnz","01001"," "},{"brpl","01000"," "},
{"brmi","01000"," "},{"brlmi","01001"," "},{"nop","00000"," "},{"stop","11111"," "},
{"een","01010"," "},{"edi","01011"," "},{"rfi","11110"," "},{"svi","10000"," "},
{"ri","10001"," "}};
int last=36, initial=0 , mid, index;
for(int i = 0; i < icount-1; i++)
{
//display arrays
for(int j = 0; j < 4;j++)
{
cout << input[i][j] << " ";
// this is for check first column that consist inst and then convert to binary code
if(j==0)
{
while(last>=initial)
{
mid=(last+initial)/2;
if(input[i][0]==inst[mid][0])
{ index=mid;
}
else if(input[i][0]>inst[mid][0])
{ initial=mid+1;
}
else
last=mid-1;
}
cout<<" "<<inst[index][1]<<" ";
}
}
it's like output not display the correct binary code. Any kind of help I'm really appreciated.
Thanks you.
* I don't want to use return mid and create another function
Your search would be soooo much simpler if you reorganized your data:
struct Data_Record
{
string command;
string value;
string other;
// Here's what makes the search work better:
bool operator==(const Data_Record& dr)
{
bool is_equal = false;
if (command == dr.command)
{
if (value == dr.value)
{
if (other == dr.other)
{
is_equal = true;
}
}
}
}
bool operator<(const Data_Record& dr)
{
return command < dr.command;
}
};
const Data_Record inst[37] = { /* ... */};
Data_Record const * p_item_found = NULL;
Data_Record key = {"and", "", ""};
p_item_found = std::binary_search(&inst[0], &inst[38], key);
if (p_item != &instr[38])
{
cout << "Found it\n";
}
else
{
cout << "Item not found.\n";
}
You can do other cool stuff like overloading operator<< and operator>> for custom output and input.
Edit 1: OOP hierarchy
Many instruction sets have groups that share commonality. For example, jump or branch instructions all have a destination address. Math instructions may have the same operands.
I recommend having a hierarchy of classes (or structures). Research "C++ Factory Design Pattern".
class Instruction
{
public:
virtual void Print_Annotated(std::ostream& output) = 0;
virtual void Instruction_Counter Execute(void) = 0;
protected:
std::string opcode;
std::string instruction_value;
};
class Jump_Instr_Category : public Instruction
{
protected:
unsigned int destination_address;
};
class Math_Instr_Category : public Instruction
{
protected:
std::string parameter1;
std::string parameter2;
};
You use the Factory Pattern to return a pointer to the Instruction base class.
The User's program would be a simple as:
std::vector<Instruction *> program;

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 << ", ";
}