2012-10-02 29 views
2

我想創建索引的C風格的字符串多重映射,如下面的代碼段:多重映射C風格的字符串鍵未能插入項

#include <cstring> 
    #include <map> 
    #include <iostream> 

    using namespace std; 

    int main(void) 
    { 
     int i, j; 
     int (*fn_pt)(const char *, const char *) = strcmp; 
     multimap<char *, char *, int (*)(const char *, const char *)>a(fn_pt); 

     for (i = 0; i < 2; i++) 
     { 
      char key[2]; 
      sprintf(key, "%d", i); 
      for (j = 0; j< 5; j++) 
      { 
       char value[2]; 
       sprintf(value, "%d", j); 
       a.insert(pair<char *, char *>(key, value)); 
      } 
     } 

     for (i = 0; i < 2; i++) 
     { 
      char key[2]; 
      sprintf(key, "%d", i); 
      multimap<char *, char *>::iterator it = a.find(key); 
      while (it != a.end()) 
      { 
       cout << it->first << "\t" << it->second <<endl; 
       it++; 
      } 
     } 
    } 

簡單地改變的關鍵上面的程序到整數給我預期的結果。但是,對一個字符串索引multimap會給我一些意想不到的結果(只有1和4的行按空格分隔),而不是顯示每個使用的鍵值的每個值。

我在哪裏錯了?

感謝

+1

爲什麼不使用'std :: string'?很難在標準的C++容器中正確使用'const char *'鍵和值。 – kennytm

+0

@KennyTM我會嘗試使用std :: string並查看它是否有效。但我認爲C風格的字符串應該也能工作,特別是因爲我已經明確地給出了比較器 – Arani

回答

4

strcmp是一個錯誤的謂語multimap使用。 謂詞應滿足下列關係:

表達排版(A,B),其中comp爲這一比較類和的目的a和b是鍵值,如果要被放置在將返回真在嚴格的弱排序操作中比b更早的位置。

strcmp違反了,因爲它返回一個非零值,如果字符串是不相等的,無論是一個< B或A> B。

你應該定義你自己的謂詞,它返回true當且僅當第一個字符串小於第二個。

+1

也稱爲「嚴格弱排序」。 – Xeo

+0

是的,我現在認識到了這個問題。 – Arani

3
multimap<char *, char *, int (*)(const char *, const char *)>a(fn_pt); 

    for (i = 0; i < 2; i++) 
    { 
     char key[2]; 
     sprintf(key, "%d", i); 
     for (j = 0; j< 5; j++) 
     { 
      char value[2]; 
      sprintf(value, "%d", j); 
      a.insert(pair<char *, char *>(key, value)); 
     } 
    } 

你存儲兩個指針在一個容器中,然後你消滅的對象(keyvalue)這些指針指向,當他們走出去的範圍。這使容器保留了現在沒有意義的信息。

1

在超出範圍之後很長時間內,您正在使用內存keyvalue。實際上,你所有的指針都指向同一塊棧內存,而且當你真正看它時,這塊指針就可以被重用了。

要做你想做的事情,你需要使用strdup()創建你的char *數據的永久副本。當然,那麼你需要擔心以後再釋放它。

+0

另外,當然,strcmp也是錯誤的。 – Arkadiy