2013-05-16 116 views
0

我嘗試讀取一個字典文件,其中每行包含由空格分隔的word-id,word和frequency。問題是用於存儲單詞的地圖具有相同的值。如果你能幫助我,我非常感激。帶指針值的C++映射

typedef struct{ 
    int id; 
    int count; 
    char* word; 
} WORD; 

//read file 
std::map<int, WORD*> readWordMap(char* file_name) 
{ 
    std::ifstream infile(file_name, std::ifstream::in); 
    std::cout<<"word map read file:"<<file_name<<std::endl; 
    if (! infile) { 
     std::cerr<<"oops! unable to open file "<<file_name<<std::endl; 
     exit(-1); 
    } 
    std::map<int, WORD*> map; 
    std::vector<std::string> tokens; 
    std::string line; 
    char word[100]; 
    int size; 
    while (std::getline(infile, line)) { 
     size = (int)split(line, tokens, ' '); 
     WORD* entry = (WORD*) malloc(sizeof(WORD*)); 
     entry->id = atoi(tokens[0].c_str()); 
     entry->count = atoi(tokens[2].c_str()); 
     strcpy(word, tokens[1].c_str()); 
     entry->word = word; 

     map[entry->id] = entry; 
     std::cout<< entry->id<<" "<<entry->word<<" "<<entry->count<<std::endl; 

     } 
     infile.close(); 
     std::cout<<map.size()<<std::endl; 
     std::map<int, WORD*>::const_iterator it; 
     for (it = map.begin(); it != map.end(); it++) { 
      std::cout<<(it->first)<<" "<<(it->second->word)<<std::endl; 

     } 

     return map; 
} 

//split string by a delimiter 
size_t split(const std::string &txt, std::vector<std::string> &strs, char ch) 
{ 
    size_t pos = txt.find(ch); 
    size_t initialPos = 0; 
    strs.clear(); 

    while(pos != std::string::npos) { 
     strs.push_back(txt.substr(initialPos, pos - initialPos + 1)); 
     initialPos = pos + 1; 

     pos = txt.find(ch, initialPos); 
    } 

    strs.push_back(txt.substr(initialPos, std::min(pos, txt.size()) - initialPos + 1  )); 

    return strs.size(); 
} 

數據文件:

2 I 1 
3 gave 1 
4 him 1 
5 the 3 
6 book 3 
7 . 3 
8 He 2 
9 read 1 
10 loved 1 

結果:

2 I 1 
3 gave 1 
4 him 1 
5 the 3 
6 book 3 
7 . 3 
8 He 2 
9 read 1 
10 loved 1 
map size:9 
2 loved 
3 loved 
4 loved 
5 loved 
6 loved 
7 loved 
8 loved 
9 loved 
10 loved 
+2

我強烈建議你殺的指針,只是用'的std :: string'在'char *'和'std :: map '代替'std :: map '。 – chris

+1

還有''WORD * entry =(WORD *)malloc(sizeof(WORD *));''是錯誤的。應該是'WORD * entry =(WORD *)malloc(sizeof(WORD));'而不是 – Xaqq

+0

@chris非常感謝你,我用'WORD std :: string'分別替換了'WORD *和char *'。 –

回答

1
WORD* entry = (WORD*) malloc(sizeof(WORD*)); 

分配WORD pointer而不是整個WORD結構。

編譯器不斷分配項目放置它不initalized任何東西它們都指向這甚而不屬於你的程序可能。一些隨機地址),你該指針添加到地圖反覆。所以,你的地圖的所有第一個指向相同的位置(巧合)。它應該是

WORD* entry = new WORD; 

這是做的更清潔的方式,

struct WORD{ 
    int id; 
    int count; 
    std::string word; 
}; 

while (std::getline(infile, line)) { 
    WORD* entry = new WORD; 
    std::istringstream iss(line); 

    iss >> entry->id >> entry->word >> entry->count; 
    map[entry->id] = entry; 
    std::cout<< entry->id<<" "<<entry->word<<" "<<entry->count<<std::endl; 
    } 
+0

非常感謝。有用。但是我嘗試打印指向不同位置的'WORD *'的分配地址。 '0x100100ae0 0x100100ab0 0x100100c20 0x100100c90 0x100100d00 0x100100d70 0x100100de0 0x100100e50 0x100100ec0' –

+0

@ user2293003你的意思是你想打印出來在你原來的代碼?或在我的版本? – stardust

+0

@ user2293003不要在C++中使用'malloc'。使用'new'。儘可能使用'stingstreams'。儘可能避免生成指針。 – stardust

1

你忘了strcpy之前WORD::word分配內存。並且您將char word[100]的地址分配給所有地圖的所有項目。

 

而且最好使用std::string代替C風格的字符串。另外,您可以使用std::stoi將字符串轉換爲整數。試試這個:

struct WORD{ 
    int id; 
    int count; 
    std::string word; 
}; 

std::map<int, WORD> readWordMap(const std::string &file_name) 
{ 
    ... 
    std::map<int, WORD> map; 
    ... 

    while (std::getline(infile, line)) { 
     ... 

     WORD entry; 
     entry.id = std::stoi(tokens[0]); 
     entry.count = std::stoi(tokens[2]); 
     entry.word = tokens[1]; 

     map[entry.id] = entry; 

     ... 
     } 
     infile.close(); 
     ... 
} 
+0

非常感謝你,它的工作原理。 –