How to insert pair<string, CUSTOM_CLASS> into multimap C++ - c++

How can I insert pair<string, CUSTOM_CLASS> into multimap? pair() function is answering "no instance of constructor..."
What am I doing wrong?
MY code:
using namespace std;
class CUSTOM_CLASS{
public:
string state;
multimap<string, CUSTOM_CLASS> relation;
bool isStart = false;
bool isEnd = false;
}
CUSTOM_CLASS findNext(string s) {
for (int i = 0; i < automat.size(); i++) {
if (automat.at(i).stav == s) {
return automat.at(i);
}
}
}
void assignRelation(string f, string i, string w) {
multimap<string, CUSTOM_CLASS> tmp;
CUSTOM_CLASS where;
for (int i = 0; i < automat.size(); i++) {
if (automat.at(i).stav == f) {
where = findNext(w);
tmp.insert(pair<string, CUSTOM_CLASS>(i, where));
}
}
}
And this gives me error.

Related

How can I print a Dictionary in c++ ? This is the code that im running, and I cant get to work the printDicionary method

This is the code that im running, and I cant get to work the printDicionary method.
Im not sure how to use the vector i created and i want to know how could I print all of the elements in this way:
[0]:
[1]: (1501, “adiós”), (301, “nuevo”)
[2]:
[3]: (23, “perro”)
…
[5]: (15, “hola”)
…
[9]: (9, “gato”)
#include <iostream>
#include <vector>
using namespace std;
template <class K, class V>
class KeyPair{
public:
K key;
V value;
KeyPair(){
key=NULL;
value=NULL;
}
KeyPair(K key, V val){
this->key=key;
this->value=val;
}
};
template <class K, class V>
class Dictionary{
public:
vector<KeyPair<K,V> > *dict;
int positions;
Dictionary(){
positions=10;
dict=new vector<KeyPair<K,V> >[positions];
}
Dictionary(int pos){
positions=pos;
dict=new vector<KeyPair<K,V> >[positions];
}
void insert(K key, V value){
KeyPair<K,V> kp(key, value);
int hash=key%positions;
for(int i=0; i<dict[hash].size(); i++){
if(dict[hash][i].key==key){
cout<<"llave ya existente"<<endl;
return;
}
}
dict[hash].push_back(kp);
//dict//arreglo de vectores keypair
//dict[hash]//vector de keypair
}
V checkAtKey(K key){
int hash=key%positions;
for(int i=0; i<dict[hash].size(); i++){
if(dict[hash][i].key==key){
return dict[hash][i].value;
}
}
return NULL;
}
void printDictionary(){
This is where i created the method
for(int i=0; i<dict[i].size(); i++){
cout << dict.key <<endl;
Im not sure if this is the way i should call the dict
cout << dict.value <<endl;
return;
}
}
};
int main(){
Dictionary<int, string> a;
a.insert(5, "perro");
a.insert(4, "gato");
Dictionary<int, string> b;
b.insert(15, "lombriz");
b.printDictionary();
}
there are a lot of mistakes in your code, man.
the "kp" member of Dictionary is a pointer (it has that "*" star), so you must use "->" to access its members, such as ".at(i)", which is the same as [i], or ".push_back(i)" to add an element at the end of the vector.
i have put your original code in comments and replaced it with the right code so you can see what changes i made. ask me if you wanna know more about what i changed, bro. good luck!
#include <iostream>
#include <vector>
using namespace std;
template<class K, class V> class KeyPair
{
public:
K key;
V value;
KeyPair()
{
key = NULL;
value = NULL;
}
KeyPair(K key, V val)
{
this->key = key;
this->value = val;
}
};
template<class K, class V> class Dictionary
{
public:
vector<KeyPair<K,V>> * dict;
int positions;
Dictionary()
{
positions = 10;
dict = new vector<KeyPair<K, V>>[positions];
}
Dictionary(int pos)
{
positions = pos;
dict = new vector<KeyPair<K, V>>[positions];
}
void insert(K key, V value)
{
KeyPair<K, V> kp(key, value);
//int hash = key % positions;
//for (int i = 0; i < dict[hash].size(); i++)
for (int i = 0; i < dict->size(); i++)
{
//if (dict[hash][i].key == key)
if (dict->at(i).key == key)
{
cout << "llave ya existente" << endl;
return;
}
}
//dict[hash].push_back(kp);
dict->push_back(kp);
}
V checkAtKey(K key)
{
//int hash = key % positions;
//for (int i = 0; i < dict[hash].size(); i++)
for (int i = 0; i < dict->size(); i++)
{
//if (dict[hash][i].key == key)
if (dict->at(i).key == key)
{
//return dict[hash][i].value;
return dict->at(i).value;
}
}
return NULL;
}
void printDictionary()
{
//for (int i = 0; i < dict[i].size(); i++){
for (int i = 0; i < dict->size(); i++)
{
// cout << dict.value << endl;
KeyPair<K, V> curr_key = dict->at(i);
printf("%d - %s\n", curr_key.key, curr_key.value.c_str());
// or you can do this
// std::cout << curr_key.key << " - " << curr_key.value.c_str();
}
}
};
int main()
{
Dictionary<int, string> a;
a.insert(5, "perro");
a.insert(4, "gato");
Dictionary<int, string> b;
b.insert(15, "lombriz");
b.printDictionary();
return 0;
}

Printing from Trie

I have built a trie in C++ designed to hold words of sentences. Each sentence will have a weight which determines the order in which they should be output. I have several recursive functions that call other recursive functions, and the dilemma I am facing is that I want to print my list only once.
Basically my get function calls the printFromNode function which creates the vector of pairs p that I want to sort and print. If someone could point me in the right direction in how to do that it would be much appreciated.
Code:
Trie.cpp:
//#include "Trie.h"
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <sstream>
#include <stack>
using namespace std;
class Node
{
private:
string word = "";
bool endOfSentence = false;
int weight = -1;
public:
vector<Node> children = {};
Node() {
this->setWord("");
}
Node(string s){
this->setWord(s);
}
string getWord(){
return this->word;
}
void setWord(string s) {
this->word = s;
}
void setEOS(){
this->endOfSentence = true;
}
void setWeight(int weight){
this->weight = weight;
}
int getWeight() {
return this->weight;
}
};
class Trie
{
public:
Node root;
void add(vector<string> phrase, int weight, Node* n){
Node* current = n;
int w = weight;
int found = -1;
for (int i = 0; i < current->children.size(); i++) {
if (phrase[0] == current->children[i].getWord()) {
found = i;
}
}
if (found > -1) {
current = &current->children[found];
phrase.erase(phrase.begin());
add(phrase, w, current);
}
else {
addPhrase(phrase, w, current);
}
}
void addPhrase(vector<string> phrase, int weight, Node* n) {
Node* current = n;
for (int i = 0; i < phrase.size(); i++) {
Node temp = *new Node(phrase[i]);
current->children.push_back(temp);
current = &current->children.back();
if (i == phrase.size() - 1) {
current->setEOS();
current->setWeight(weight);
}
}
}
void get(vector<string> search) {
Node* current = &this->root;
get(search, current);
}
void get(vector<string> search, Node* n) {
Node* current = n;
int found = -1;
//test search size
if (search.size() == 0) {
cout << "Please enter a valid search" << endl;
}
for (int i = 0; i < current->children.size(); i++) {
if (search[0] == current->children[i].getWord()) {
found = i;
}
}
if (found > -1 && search.size() == 1) {
current = &current->children[found];
printFromNode(*current);
maxNode(*current);
}
else if (found > -1 && search.size() != 1) {
current = &current->children[found];
search.erase(search.begin());
get(search, current);
}
else {
cout << "Not Found" << endl;
}
}
void printOutput(vector<pair<int,string>> p){
sort(p.begin(), p.end());
cout << p.size() << endl;
for (int i = 0; i < p.size(); i++) {
cout << p[i].second << " " << endl;
}
}
void printFromNode(Node n) {
vector<string> phrase = {};
vector <pair < int, string>> final = {};
printFromNode(n,phrase,final);
}
void printFromNode(Node n, vector<string> &v, vector<pair<int,string>> &p) {
string output;
if (n.getWord() == "") {
return;
}
for (int i = 0; i < n.children.size(); i++) {
if (n.children[i].getWeight() > 0) {
for (int i = 0; i < v.size(); i++)
{
output.append(v[i] + " ");
}
output.append(n.children[i].getWord());
p.push_back(make_pair(n.children[i].getWeight(), output));
}
v.push_back(n.children[i].getWord());
printFromNode(n.children[i], v, p);
v.pop_back();
sort(p.begin(), p.end());
}
return;
}
void maxNode(Node n) {
int max = 0;
int index = 0;
int temp = 0;
for (int i = 0; i < n.children.size(); i++) {
temp = n.children[i].children.size();
if (temp > max) {
max = temp;
index = i;
}
}
cout << n.children[index].getWord() << " " << max << endl;
}
};
Main.cpp:
#include "Trie.cpp"
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int main(int argc, char* argv[]) {
// Initialize trie up here
Trie myTrie = *new Trie();
// parse input lines until I find newline
for(string line; getline(cin, line) && line.compare(""); ) {
stringstream ss(line);
string string_weight;
ss >> string_weight;
int weight = stoi(string_weight);
// I am just going to put these words into a vector
// you probably want to put them in your trie
vector<string> phrase = {};
for(string word; ss >> word;) {
phrase.push_back(word);
}
myTrie.add(phrase, weight, &myTrie.root);
vector<string> ans = {};
}
// parse query line
string query;
getline(cin, query);
stringstream ss(query);
vector<string> search = {};
for (string query; ss >> query;) {
search.push_back(query);
}
myTrie.get(search);
return 0;
}
You can remove recursive methods, and doing something like the following:
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <set>
class Node
{
public:
bool endOfSentence = false;
std::set<int> weights;
std::map<std::string, Node> children;
Node() = default;
const Node* get(const std::string& word) const
{
auto it = children.find(word);
if (it == children.end()) {
return nullptr;
}
return &it->second;
}
auto find_by_weight(int weight) const
{
return std::find_if(children.begin(),
children.end(),
[=](const auto& p){ return p.second.weights.count(weight);});
}
};
class Trie
{
Node root;
public:
void add(int weight, const std::vector<std::string>& phrase)
{
Node* node = &root;
for (const auto& word : phrase) {
node->weights.insert(weight);
node = &node->children[word];
}
node->weights.insert(weight);
node->endOfSentence = true;
}
bool contains(const std::vector<std::string>& phrase) const
{
const Node* node = &root;
for (const auto& word : phrase) {
node = node->get(word);
if (node == nullptr) {
return false;
}
}
return node->endOfSentence;
}
void print(int weight) const
{
const Node* node = &root;
const char* sep = "";
while (node) {
const auto it = node->find_by_weight(weight);
if (it == node->children.end()) {
break;
}
std::cout << sep << it->first;
sep = " ";
node = &it->second;
}
std::cout << std::endl;
}
void print_all() const
{
for (int i : root.weights) {
print(i);
}
}
};
And usage/Test:
int main(int argc, char* argv[]) {
const std::vector<std::vector<std::string>> sentences = {
{"My", "name", "is", "John"},
{"My", "house", "is", "small"},
{"Hello", "world"},
{"Hello", "world", "!"}
};
Trie trie;
int i = 0;
for (const auto& sentence : sentences) {
trie.add(i, sentence);
++i;
}
const std::vector<std::vector<std::string>> queries = {
{"My", "name", "is", "John"},
{"My", "house"},
{"Hello", "world"}
};
for (const auto& query : queries) {
std::cout << trie.contains(query) << std::endl;
}
trie.print_all();
}
Demo

Segmentation fault when using map in structure

So, I get a segmentation fault when the program enters the for (where it says "Here") and I can't understand why. Do I need to initialize the map every time I make a new tag* object? How?
struct tag {
map <string, tag*> tg;
map <string, string> at;
};
int main () {
int n, q;
map<string, tag*> tags;
vector<string> current;
string s;
char c;
// Parsing the HRML code
in>>n>>q;
for(int i = 1; i <= n; i++) {
in>>c>>s;
if(s[0] =='/') {
current.pop_back();
} else {
current.push_back(s);
tag *t = tags[current[0]];
for(int i = 1; i < current.size(); i++) {
t = t->tg[current[i]]; // <- Here
}
bool ok = true;
while(ok) {
in>>s;
string S;
in>>S>>c>>S;
if(S[S.size()-1] == '>') {
ok = false;
S.erase(S.size()-1, 1);
} S.erase(S.size()-1, 1);
t->at[s] = S;
}
}
}

Algorithm for graph post dominance?

What algorithm can be used to calculate post dominators in a control flow graph?
Currently I calculate the dominators by using the iterative bit vector algorithm:
#include <iostream>
#include <list>
#include <stack>
#include <vector>
#include <memory>
#include <map>
class BasicBlock
{
public:
BasicBlock(std::string name) : mName(name) { }
void AllocateDominatorsAndSetToTrue(const size_t nBlocks)
{
mDominators.resize(nBlocks);
for (size_t i = 0; i < nBlocks; i++)
{
mDominators[i] = true;
}
}
void SetAllDominatorsTo(bool value)
{
for (size_t i = 0; i < mDominators.size(); i++)
{
mDominators[i] = value;
}
}
std::string mName;
int mId = 0;
// Links to blocks before this one
std::vector<BasicBlock*> mPredecessors;
// Links to blocks after this one
std::vector<BasicBlock*> mSucessors;
std::vector<bool> mDominators;
std::vector<BasicBlock*> mImmediateDominator;
};
class ControlFlowGraph
{
public:
void AddBasicBlock(std::string name)
{
mBasicBlocks.emplace_back(std::make_unique<BasicBlock>(name));
}
void AddSucessor(std::string block, std::string target)
{
FindBlock(block)->mSucessors.emplace_back(FindBlock(target));
}
void AddPredecessor(std::string block, std::string target)
{
FindBlock(block)->mPredecessors.emplace_back(FindBlock(target));
}
BasicBlock* FindBlock(std::string name)
{
for (const auto& block : mBasicBlocks)
{
if (block->mName == name)
{
return block.get();
}
}
return nullptr;
}
void CalculateDominators()
{
const size_t nBlocks = mBasicBlocks.size();
int i = 0;
for (std::unique_ptr<BasicBlock>& block : mBasicBlocks)
{
block->mId = i++;
block->AllocateDominatorsAndSetToTrue(nBlocks);
}
BasicBlock* block = mBasicBlocks[0].get();
block->SetAllDominatorsTo(false);
block->mDominators[block->mId] = true; // block always dominates itself
bool changed = false;
do
{
changed = false;
for (std::unique_ptr<BasicBlock>& b : mBasicBlocks)
{
if (b == mBasicBlocks[0]) // Is it the entry node?
{
continue;
}
for (BasicBlock* pred : b->mPredecessors)
{
auto T = b->mDominators;
for (size_t i = 0; i < nBlocks; i++)
{
if (b->mDominators[i] && pred->mDominators[i])
{
b->mDominators[i] = true;
}
else
{
b->mDominators[i] = false;
}
}
b->mDominators[b->mId] = true; // block always dominates itself
if (b->mDominators != T)
{
changed = true;
}
}
}
}
while (changed);
}
void CalculateImmediateDominators()
{
// ??
}
std::vector<std::unique_ptr<BasicBlock>> mBasicBlocks;
};
int main()
{
ControlFlowGraph graph;
graph.AddBasicBlock("1");
graph.AddBasicBlock("2");
graph.AddBasicBlock("3");
graph.AddBasicBlock("4");
graph.AddBasicBlock("5");
graph.AddBasicBlock("6");
graph.AddSucessor("1", "2");
graph.AddSucessor("2", "3");
graph.AddSucessor("2", "4");
graph.AddSucessor("3", "2");
graph.AddSucessor("4", "5");
graph.AddSucessor("4", "6");
graph.AddSucessor("5", "4");
graph.AddSucessor("6", "2");
graph.AddPredecessor("2", "1");
graph.AddPredecessor("3", "2");
graph.AddPredecessor("4", "2");
graph.AddPredecessor("5", "4");
graph.AddPredecessor("6", "4");
graph.CalculateDominators();
graph.CalculateImmediateDominators();
return 0;
}

Cref postincrementation in Map definition

So I have such definition on map class on vector, it works good except for post-incrementation, which doesn't work as it should. You can see in example that variable a should be equal to 10 (post-incremented after assignment). But it's equal to 11. I have no idea how to fix that.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
template<class T>
class Map {
class Cref {
friend class Map;
Map& m;
string key;
T value;
public:
operator double() {
return m.read(key);
};
Map::Cref & operator=(double num) {
m.write(key, num);
return *this;
};
Map::Cref & operator++(int) {
Cref c(*this);
m.increment(key, value);
return c;
}
Cref(Map& m, string a)
: m(m),
key(a) {};
};
public:
class Unitialized {};
struct Record {
string key;
T value;
};
vector<Record> data;
Map() {}
~Map() {}
bool ifexist(string k) {
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == k)
return 1;
}
return 0;
}
Cref operator[](string key) {
return Map::Cref( * this, key);
}
private:
void increment(string key, T value) {
if (ifexist(key) == 0) {
throw Unitialized();
}
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == key)
data.at(i).value += 1;
}
}
void write(string key, T value) {
if (ifexist(key) == 1) {
cout << "Element already exist" << endl;
return;
}
Record r;
r.key = key;
r.value = value;
data.push_back(r);
}
double read(string key) {
if (ifexist(key) == 0) {
throw Unitialized();
}
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == key)
return data.at(i).value;
}
return 0;
}
};
int main(int argc, char** argv) {
Map<int> m;
m["ala"] = 10;
int a = 0;
a = m["ala"]++;
cout << a << endl;
try {
cout << m["ala"] << endl;
cout << m["ola"] << endl;
} catch (Map<int>::Unitialized&) {
cout << "Unitialized element" << endl;
}
return 0;
}
Yes, I already fixed that, overloading of ++ operator should look like that :
T operator ++(int)
{
T ret = m.read(this->key);
m.increment(key, value);
return ret;
}
This fixes everything.