在c ++中添加字符串值以映射

时间:2016-01-21 10:55:32

标签: c++ dictionary containers

我正在尝试将char数组值添加到地图中,但是在显示char数组的值时,不会显示整数值。 即ii.first未显示,但ii.second正确显示。

以下是我正在运行的完整代码,

#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();
}

运行代码时获得的输出:

Enter the employee name
farhan
Enter the employee id
909
Map size: 1
the first=: 909

这里的first = farhan:909应该是正确的输出,任何人都可以让我明白我在哪里做错了吗?

3 个答案:

答案 0 :(得分:2)

其他提到的问题是char *。同样在你的情况下,char *变得悬空而你实际上指向垃圾,其背后的原因是,当名称超出范围时释放内存,并且您仍然指向该内存,实际上您需要复制数据在地图上。

这个有效

// 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();
}

只是一个快速修复,可能需要更多努力才能做得更好。但只是为了给你一个想法。

如果你需要使用char *,那么你可能需要自己批量分配内存,每次你去询问你在数据结构中复制它的名称并检索指向它的指针。要正确处理你使数据结构的方式在结果的清洁方面发生了很大变化,但核心要点是,你需要管理你的内存,复制到一个会持久存在但不会丢失的地方,然后存储一个指向该内存的指针,而不是指当你离开set_value()时释放的内存区域。

答案 1 :(得分:1)

这一行

this->p.insert(map<char *,int>::value_type(name,empid));  

向地图添加char*指针,而不是字符串本身。如果指针 指向堆栈(name []在堆栈上)然后它将是潜在的 每次迭代都使用相同的地址。

使用std :: string

e.g。

typedef std::map<std::string, int> ptype;
...
p.insert(std::make_pair(name,empid))

或手动分配动态内存并跟踪字符串

char* nameStorage = new char[strlen(name)+1];
strcpy(nameStorage,name);
p.insert(std::make_pair(nameStorage,empid));

答案 2 :(得分:1)

您定义了地图的键,如char *

typedef map <char*, int, cmp_str> ptype;
             ^^^^^

所以在成员函数set_value

void set_value() {
    char name[20];
    int empid;

    //...

    this->p.insert(map<char *,int>::value_type(name,empid));
}

为密钥分配了本地可变的name的地址(更准确地说是数组name的第一个字符的地址),它将在退出函数后被销毁。

之后,密钥将被取消,因为它将指向一个不存在的字符数组。

此外,密钥应该是可复制的,但是数组没有复制赋值操作符。

您可以使用标准类std::array<char, 20>作为键类型。例如

typedef map <std::array<char, 20>, int, cmp_str> ptype;

在这种情况下,您还必须更改它将接受此类对象的cmp_str

另一种方法是使用标准类std::string而不是数组。 Foir示例

typedef map <std::string, int> ptype;