How to I send the Map values to the class - c++

#include <iostream>
#include <memory>
#include <initializer_list>
#include <cassert>
#include <map>
template <typename T>
class Matrix
{
private:
int i,j;
T value;
std::map<std::array<int, 2>,double> Mat;
public:
Matrix():i(0),j(0)
{
std::cout<<"Empty boi called"<<std::endl;
}
Matrix(int row, int column)
{
std::cout<<"Main boi called"<<std::endl;
}
// I'm not really sure where to plug this code in
// In the main function, this code works but not really in class
for (std::map<std::array<int, 2>,int>::iterator it=Mat.begin(); it!=Mat.end(); ++it)
{
i = it->first[0];
j = it->first[1];
value = it->second;
std::cout << "["<< it->first[0] <<","<<it->first[1]<<"]"<< " => " << it->second << '\n';
}
};
int main()
{
std::map<std::array<int, 2>,int> Mat;
Mat[{1,5}]=20;
Mat[{2,6}]=30;
for (std::map<std::array<int, 2>,int>::iterator it=Mat.begin(); it!=Mat.end(); ++it)
std::cout << "["<< it->first[0] <<","<<it->first[1]<<"]"<< " => " << it->second << '\n';
// The same code done in main function is what I want to do in the class
Matrix<double> M(10,10);
M{[1,1]} = 3.14; // This returns an error
return 0;
}
As seen, the mapping is possible when its directly in the main function, but I want to send multiple positions of M to the class and have it initialised. But completely unable to do so. Tried looking in a lot of places to no avail.

Related

Why copy constructor changed previous object pointer member

#include <iostream>
#include <string.h>
#include "Date.h"
#include "Employee.h"
using std::cout;
using std::endl;
using std::to_string;
class TestOps {
public:
int sex = 1;
string toString() {
return " sex:" + to_string(sex) ;
}
};
class Test {
public:
TestOps* testOps;
Test(const Test& t) :Test{} {
this->testOps = new TestOps{ *(t.testOps) };
};
Test() {
TestOps ops;
//this->testOps = new TestOps{}; // it will be ok with this way
this->testOps = &ops;
}
};
int main() {
// code not understand
Test t1;
cout <<"first testOps:" << t1.testOps->toString() << endl; // sex: 1
Test t2{ t1 };
cout << "first testOps:" << t1.testOps->toString() << endl; // sex: -858893460 ???? why?
cout << "second testOps:" << t2.testOps->toString() << endl; // sex: -858893460 ???? why?
return 0;
}
As you can see, why the first log is as expected while the later logs are not?
Also, t1.testOps address is different from t2.testOps which is as expected.
I have done some research but didn't find the answer. Maybe because I'm pretty new to cpp.

Data placed into array correctly but is not there when array is printed

I'm implementing my own hash table and I am running into the following problem: when I insert my node(s) into the table, they are not printed out when I loop through the array. I am using an array of arrays as the underlying data structure and the logic is as follows:
I pass my node to an insert function. This function, based on the
type of data in my node, calls the appropriate hash function provided
by the C++ STL.
Then, I mod the hash value returned by the size of
my hash table and use that to determine which array to place the
node.
I also have an array of arrays of booleans (the same size as my
hash table) that I use to check whether a specific spot in my hash
table already has data in it.
If it does, I simply keep looping till
an empty spot is found.
Like I said before, the problem is that the data is inputed correctly into the array (I've checked that with print statements), but when I print the array, nothing is outputted. I have also checked if my object is being constructed correctly (again, with print statements), but everything is looking fine. I've included the full code below. Any help would be greatly appreciated!
///////START OF NODE.H///////////
#ifndef NODE_H
#define NODE_H
#include <iostream>
template <typename T>
class HashTable;
template <typename T>
class Node
{
friend class HashTable<T>;
private:
T data;
public:
Node(T Data): data(Data)
{
std::cout << "In the node constructor" << std::endl;
}
Node()
{
decltype(data) {};
}
T getData() const
{
return data;
}
};
#endif
//////////////////////END OF NODE.H////////////////////
/////START OF HASHTABLE.H///////
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include "Node.h"
#include <iostream>
#include <array>
#include <functional>
#include <typeinfo>
#include <string>
const int TABLE_SIZE=5;
template <typename T>
class HashTable
{
private:
std::array<std::array<Node<T>, TABLE_SIZE>, TABLE_SIZE> hashTable;
std::array<std::array<bool, TABLE_SIZE>, TABLE_SIZE> spots;
public:
HashTable()
{
for(int index=0;index<spots.size();++index)
{
for(int position=0;position<spots.at(index).size();++position)
{
spots.at(index).at(position)=false;
}
}
}
int hashFunction(Node<T> Node)
{
auto key=Node.getData();
std::hash<decltype(Node.getData())> hash_function {};
int hash=hash_function(key);
if(hash < 0)
{
hash*=-1;
}
//std::cout << "The hash value return by the STL hash function for the key " << key << " is " << hash << std::endl;
if(hash > TABLE_SIZE)
{
hash%=TABLE_SIZE;
}
std::cout << "The hash value for the key " << key << " is " << hash << std::endl;
return hash;
}
void insert(Node<T> Node)
{
int hashValue=hashFunction(Node);
auto location=hashTable.at(hashValue);
std::cout << "Going to insert " << Node.getData() << std::endl;
for(int index=0;index<location.size();++index)
{
if(spots.at(hashValue).at(index)==false)
{
std::cout << "Found a spot that is not taken!" << std::endl;
std::cout << "The size of the data at the spot in the array before we insert is: " << location.at(index).getData().size() << std::endl;
location.at(index)=Node;
std::cout << "The size of the data at the spot in the array after we insert is: " << location.at(index).getData().size() << std::endl;
std::cout << "The data that is in the spot in the array: " << location.at(index).getData() << std::endl;
std::cout << std::endl;
spots.at(hashValue).at(index)=true;
break;
}
}
}
bool contains(Node<T> Node)
{
int hashValue=hashFunction(Node);
auto location=hashTable.at(hashValue);
auto result=find_if(begin(location), end(location), [Node] (const auto & element) {return element.getData()==Node.getData();});
if(result!=end(location))
{
return true;
}
return false;
}
int getSize() const
{
int size {};
for(int index=0;index<hashTable.size();++index)
{
size+=hashTable.at(index).size();
}
return size;
}
void print()
{
std::cout << "In the print function" << std::endl;
for(int index=0;index<hashTable.size();++index)
{
//std::cout << hashTable.at(index).size() << std::endl;
for(int position=0;position<hashTable.at(index).size();++position)
{
std::cout << hashTable.at(index).at(position).getData().size() << std::endl;
}
}
/*
for(int index=0;index<spots.size();++index)
{
for(int position=0;position<spots.at(index).size();++position)
{
if(spots.at(index).at(position)==true)
{
std::cout << "There should be some data here" << std::endl;
}
}
}
*/
}
};
#endif
////////////END OF HASHTABLE.H//////////
////////////START OF MAIN.CPP///////////
#include "HashTable.h"
#include <cstdlib>
#include <random>
#include <algorithm>
using namespace std;
int main()
{
HashTable<string> hash_table;
hash_table.insert(Node<string>("Java"));
hash_table.insert(Node<string>("C++"));
hash_table.insert(Node<string>("C#"));
hash_table.insert(Node<string>("Latex"));
hash_table.insert(Node<string>("Python"));
}
/////////////END OF MAIN.CPP/////////////
One error is in your insert(Node<T> Node) function on these line:
auto location=hashTable.at(hashValue);
//...
location.at(index) = Node;
The location should be a reference not a copy. What is happening is that you're making changes to a local location, and not the actual location that the hash table uses. Thus none of your changes "stick".
The line above should be this:
auto& location=hashTable.at(hashValue); // <-- note that auto is a reference
//...
location.at(index) = Node;
Now you are assigning the returned reference to a reference.
Also, I highly recommend you use a debugger, as this error could have been easily diagnosed if you stepped through your code to see what was being done.
in HashTable::insert this line:
auto location = hashTable.at(hashValue);
makes a copy of a Node. You then operate on and store in the copy, not the node in hashTable. Taking a reference to the node
auto & location = hashTable.at(hashValue);
should fix it.

How to use lambda in for_each?

I am trying to use for_each instead of the normal for loop. However, since I am new to C++11, I am kind of stuck. My intent here is to use for_each and lambda expression together. Any ideas ? I am using visual studio 2010.
Regards,
Atul
Here is the code.
#include "stdafx.h"
#include <algorithm>
#include <memory>
#include <vector>
#include <iostream>
using namespace std;
struct Point
{
union
{
double pt[3];
struct {double X,Y,Z;};
struct {double x,y,z;};
};
Point(double x_,double y_,double z_)
:x(x_),y(y_),z(z_)
{}
Point()
:x(0.0),y(0.0),z(0.0)
{}
void operator()()
{
cout << "X coordinate = " << x << endl;
cout << "Y coordinate = " << y << endl;
cout << "Z coordinate = " << z << endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<Point> PtList(100);
//! the normal for loop
for(int i = 0; i < 100; i++)
{
// Works well
PtList[i]();
}
//! for_each using lambda, not working
int i = 0;
for_each(PtList.begin(),PtList.end(),[&](int i)
{
// Should call the () operator as shown previously
PtList[i]();
});
//! for_each using lambda, not working
Point CurPt;
for_each(PtList.begin(),PtList.end(),[&CurPt](int i)
{
cout << "I = " << i << endl;
// should call the() operator of Point
CurPt();
});
return 0;
}
The third parameter of for_each is a function to apply to each element, not to each index. Otherwise, what would be the point of using that over a traditional loop?
So, instead of an int parameter, it takes a Point parameter. And now there's no reason to capture anything, because a reference to PtList is unnecessary.
// Should make operator() const as it doesn't modify anything
for_each(PtList.begin(),PtList.end(),[](Point const& p)
{
p();
});
Your std::for_each is obviously wrong. The type of the argument to the lamba should be Point, or Point const& depending on what you want to do, and what you're allowed to do.
It should be this:
int count = 0;
for_each(PtList.begin(),PtList.end(), [&](Point const & p)
{
cout <<"No. " << ++count << endl;
p();
});
Make your operator() a const member function.

Sort std::vector<myclass> in one line using sort function from STL

Question is about sorting std::vector<myclass> using function sort from STL's algorithms class.
Standard way is : sort(v.begin(), v.end(), &myfunct)
where myfunct is:
bool myfunct( myclass first, myclass second ) {
if (first.value < second.value)
return true;
else return false;
}
Approach above takes more than one line. I am curious how to do it in one line. Is it possible define function that compares myclass objects inside sort function? May be somehow use this (a < b) ? a : b. I remember that there is something like this in C#, but I forgot how is it called. Is it possible to do in C++.
First, you can just return first.value < second.value but this doesn't get rid of the function. In C++2011 you can use a lambda function:
std::sort(begin, end, [](myclass const& f, myclass const& s){ return f.value < s.value; });
Without C++2011 I think you'll need a function object because there isn't anything which projects your class to the value you actually want to compare.
BTW, you definitely want to pass everything but the most trivial objects by reference to your comparison function.
You could use boost::lambda and boost::lambda::bind (with boost lambda placeholders)
std::sort(vec.begin(), vec.end(),
boost::lambda::bind(&A::a, boost::lambda::_1)
<
boost::lambda::bind(&A::a, boost::lambda::_2));
sort passes 2 values to the comparison function so you need to compare those 2 values. The bind part of code just selects variable a from the struct A from each structures being compared (referenced by _1 and _2).
Example code:
#include <iostream>
#include <algorithm>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/array.hpp>
struct A
{
A() : a(0), b(0) {}
int a;
int b;
};
std::ostream & operator<<(std::ostream & os, A & a)
{ return os << a.a << ":" << a.b; }
int main()
{
boost::array<A,5> vec;
std::fill(vec.begin(),vec.end(),A());
vec[0].a = 1;
vec[1].a = 3;
vec[2].a = 4;
vec[3].a = 0;
vec[4].a = 2;
std::for_each(vec.begin(),vec.end(), std::cout << boost::lambda::_1 << ' ');
std::cout << std::endl;
std::sort(vec.begin(), vec.end(),
boost::lambda::bind(&A::a, boost::lambda::_1)
<
boost::lambda::bind(&A::a, boost::lambda::_2));
std::for_each(vec.begin(),vec.end(), std::cout << boost::lambda::_1 << ' ');
std::cout << std::endl;
}
Output:
1:0 3:0 4:0 0:0 2:0
0:0 1:0 2:0 3:0 4:0
why not copy the vector into a set:
std::copy(v.begin(),v.end(),std::inserter(s,s.end()));
Now the elements in the set are sorted in ascending order and use set now.
A one liner call to sort() : sort(my_vector_of_class_object.begin(),my_vector_of_class_object.end(),compare);
Code of a working demo of a "sort vector of class objects" is provided below:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
class my_Class
{
public:
my_Class(int r,int n, int s):rollno(r),name(n),status(s) { }
int getRollno() const { return rollno;}
int getName() const { return name;}
int getStatus() const { return status;}
private:
int rollno;
int name;
int status;
};
bool compare(const my_Class& x, const my_Class& y) {
return x.getRollno() < y.getRollno();
}
int main()
{
vector<my_Class> my_vector_of_class_object;
vector<my_Class>::const_iterator iter;
my_Class s1(10,20,30);
my_Class s2(40,50,60);
my_Class s3(25,85,9);
my_Class s4(1,50,2);
my_Class s5(90,70,90);
my_Class s6(85,85,3);
my_Class s7(20,6,89);
my_Class s8(70,54,22);
my_Class s9(65,22,77);
my_vector_of_class_object.push_back(s1);
my_vector_of_class_object.push_back(s2);
my_vector_of_class_object.push_back(s3);
my_vector_of_class_object.push_back(s4);
my_vector_of_class_object.push_back(s5);
my_vector_of_class_object.push_back(s6);
my_vector_of_class_object.push_back(s7);
my_vector_of_class_object.push_back(s8);
my_vector_of_class_object.push_back(s9);
cout <<"Before vector sort \n";
for(iter=my_vector_of_class_object.begin(); iter!=my_vector_of_class_object.end();++iter)
std::cout << (*iter).getRollno() << '\t' << (*iter).getName() << '\t' << (*iter).getStatus() << '\n';
cout <<" \n\n";
sort(my_vector_of_class_object.begin(),my_vector_of_class_object.end(),compare);
cout <<"After vector sort \n";
for(iter=my_vector_of_class_object.begin(); iter!=my_vector_of_class_object.end();++iter)
std::cout << (*iter).getRollno() << '\t' << (*iter).getName() << '\t' << (*iter).getStatus() << '\n';
cout <<" \n\n";
return 0;
}

std::map<string, class> print the value of the key

My program is written in C++.
#include <iostream>
#include <string>
#include <map>
using namespace std;
class Details
{
int x;
int y;
};
typedef std::map<string, Details> Det;
Det det;
Details::Details(int p, int c) {
x = p;
y = c;
}
int main(){
det.clear();
insertNew("test", 1, 2);
cout << det["test"] << endl;
return 0;
}
I want to print the value of a key with the simplest way. Eg det["test"] fails to compile.
How to I print values (1,2) for (x,y) that correspond to key "test"?
My best guess is that you have no default or copy constructor in your Obj (you don't have any in the code you posted, but I assume you have one that takes two integers). You've also got a typo in the catalog.insert() line. Here is what worked for me, using your code:
class Obj {
public:
Obj() {}
Obj(int x, int y) : x(x), y(y) {}
int x;
int y;
};
int main (int argc, char ** argv) {
std::map<std::string, Obj> catalog;
catalog.insert(std::map<std::string, Obj>::value_type("test", Obj(1,2)));
std::cout << catalog["test"].x << " " << catalog["test"].y << std::endl;
return 0;
}
Create an operator<< for your class Obj and then you can do something like std::cout << catalog["test"]; (I'm assuming that the missing parens in the insert call are just a copy-paste-o).
I've changed a bit your code.
#include <map>
#include <iostream>
#include <string>
using namespace std;
class Obj {
public:
Obj( int in_x, int in_y ) : x( in_x ), y( in_y )
{};
int x;
int y;
};
int main()
{
std::map< string, Obj* > catalog;
catalog[ "test" ] = new Obj(1,2);
for( std::map<string, Obj*>::iterator i=catalog.begin(); i != catalog.end(); ++i )
{
cout << "x:" << i->second->x << " y:" << i->second->y << endl;
}
}
Given these types:
class Obj {
int x;
int y; };
std::map<string, Obj> catalog;
Given a populated catalog object:
for(auto ob = catalog.begin(); ob != catalog.end(); ++ob)
{
cout << ob->first << " " << ob->second.x << " " << ob->second.y;
}