2016-01-21 76 views
3

我想一个字符数组值添加到地图中,但上显示字符数组的值不打算来,但显示的整数值。 即ii.first未显示,但ii.second正确显示。添加字符串值映射在C++

这里是我运行的完整代码,

#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

使用'std :: string',而不是'const char *'作为键。 –

+0

@RichardHodges,你好先生....我曾尝试过使用字符串,我可以知道使用char *时出现了什么错误。 此外,提及使用的关键是char *而不是const char * ...请验证一次...谢谢... –

+1

@FarhanPatel char *'是用于传统的C代码。 'std :: string'的优点很多(类型安全,自动内存管理,没有缓冲区溢出,为它重载的操作符等等) – bolov

回答

2

那里提到的问题是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()时释放的内存区域。

+0

@Marco ... thnx为概念.....但是纠正我,如果我错了,不是字符串inval也是本地函数你创建的set_value(),然后如何将该局部变量添加到地图中。? –

+0

std :: string提供拷贝构造函数,在我的映射中我没有传递指针或引用,而是对象本身,这意味着编译器会调用拷贝构造函数。如果我使用的是指针或ref,你将会遇到同样的问题。 在C++数组中,注意到更多的是带有一些语法糖的指针,当你将一个数组传递给一个函数时,你可以通过一个指针而不是通过值来访问值。 std :: string,为你管理内存,分配,移动,复制等。 –

+0

thnx @marco ...先生你以为我一次有这么多的概念.... thnx很多.. –

1

此行

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

增加了char*指向地图,而不是字符串本身。如果指针 指向堆栈(名称[]位于堆栈上),那么它将是每次迭代中相同的地址。

可以使用std :: string

例如,

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)); 
+0

先生我同意这个概念,因为你提到char *变得悬而未决,因为它是本地的功能,但empid也是然而,它是正确分配....为什么这样?请澄清? –

+1

这两个指针(地址数组开始)和整数复制值,在整数情况下,这就是你想要复制和存储 –

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

的键被分配与本地valriable 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; 
+0

我们的empid是一个局部变量在函数中,甚至是工作......所以它是如何,因为empid是一个整数?请澄清这一点以及....或者它是错误的插入本地empid ..... –

+1

@FarhanPatel它是empid的对象的副本存储在地图中而不是它的地址。字符数组的情况不同。它是存储为键的数组名称的第一个字符的地址。退出该函数后,该数组不存在。所以程序有未定义的行为。 –