2016-01-21 107 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的對象的副本存儲在地圖中而不是它的地址。字符數組的情況不同。它是存儲爲鍵的數組名稱的第一個字符的地址。退出該函數後,該數組不存在。所以程序有未定義的行爲。 –