I am trying to add a char array value into a map, but on displaying the value of char array is not coming, however the integer value is displayed. That is ii.first is not displayed, however ii.second is displayed correctly.
Here is the complete code which I am running,
#include <iostream>
#include <cstring>
#include <map>
#include <utility>
using namespace std;
class map_demo {
public:
class cmp_str {
public:
bool operator() (char const *a, char const *b) {
return std::strcmp(a, b) <0;
}
};
private:
typedef map <char*, int, cmp_str> ptype;
ptype p;
public:
void set_value() {
char name[20];
int empid;
cout<<"Enter the employee name\n";
cin.getline(name,20);
// cout<<"name entered=:"<<name;
cout<<"Enter the employee id\n";
cin>>empid;
this->p.insert(map<char *,int>::value_type(name,empid));
}
void get_value() {
cout << "Map size: " << p.size() << endl;
for(ptype::iterator ii=p.begin(); ii!=p.end(); ++ii) {
cout <<"the first="<< (*ii).first << ": " << (*ii).second << endl;
}
}
};
//=====================================================================
int main() {
map_demo mp1;
mp1.set_value();
mp1.get_value();
}
The output obtained on running the code:
Enter the employee name
farhan
Enter the employee id
909
Map size: 1
the first=: 909
Here the first = farhan:909, should be the correct output, can anyone make me understand where I am making it wrong??
The problem there as other mentioned is the char *. Also in you case the char * becomes dangling and you are actually pointing to garbage, the reason behind that is that when name goes out of scope that memory is freed, and you are still pointing to that memory, you actually need to copy the data in the map.
this one works
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <map>
#include <utility>
using namespace std;
class map_demo
{
public:
class cmp_str
{
public:
bool operator() (char const *a, char const *b)
{
return std::strcmp(a, b) <0;
}
};
private:
typedef map <string, int> ptype;
ptype p;
public:
void set_value()
{
char name[20];
std::string inval;
int empid;
cout << "Enter the employee name\n";
cin.getline(name, 20);
inval = name;
//cout<<"name entered=:"<<name;
cout << "Enter the employee id\n";
cin >> empid;
//this->p.insert(map<char *, int>::value_type(name, empid));
this->p.insert(std::pair<string , int>(inval,empid));
}
void get_value()
{
cout << "Map size: " << p.size() << endl;
for (auto ii = p.begin(); ii != p.end(); ++ii)
{
std::string mysf(ii->first);
//std::cout << mysf << std::endl;
cout << "the first=" << mysf << ": " << (*ii).second << endl;
}
}
};
int main()
{
map_demo mp1;
mp1.set_value();
mp1.get_value();
}
Is just a quick fix, probably with a bit more effort can be made better. But just to give you an idea.
If you need to do it with char *, then you probably need to allocate memory yourself in bulk, each time you go and ask for a name you copy that in your data struct and retrieve a pointer to it. To properly handle that the way you make your data struct changes a lot in how clean your result will be, but the core point is, you need to manage your memory, copy in a place which will persist and not get lost, and store a pointer to that memory, not to a region of memory freed when you get out of set_value().
This line
this->p.insert(map<char *,int>::value_type(name,empid));
adds a char* pointer to the map, not the string itself. If the pointer
points to the stack (name[] is on the stack) then it will be the potentially
the same address in each iteration.
Either use a std::string
e.g.
typedef std::map<std::string, int> ptype;
...
p.insert(std::make_pair(name,empid))
or allocate dynamic memory manually and keep track of the string
char* nameStorage = new char[strlen(name)+1];
strcpy(nameStorage,name);
p.insert(std::make_pair(nameStorage,empid));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With