2015-01-02 7 views
-1

먼저 첫 번째 요소에 덮어 쓰기를 발생, 나는 다음과 같은 코드를 가지고,

map<char*, char*> records; 

// id, value are buffer variables to store the text that returns from `strcpy()` 
char *id = (char*)malloc(sizeof(char*) * 20); 
char *value = (char*)malloc(sizeof(char*) * 20); 

sql->open(dbFile); 
sql->query("SELECT * FROM categories"); 
while(sql->fetch() != SQLITE_DONE){ 

    // copy the text that returns from `sql->getValue`, then convert that text from `const unsigned char*` to `const char*` 
    strcpy(id, reinterpret_cast<const char*>(sql->getValue(0))); 
    strcpy(value, reinterpret_cast<const char*>(sql->getValue(1))); 

    // insert the values that in `id`,`value` as new item 
    records.insert(pair<char*, char*>(id, value));   
} 
free(id); 
free(value); 

이전 코드의 아이디어는 사용하여이 방법 sql->getValue(0)를 반환하는 텍스트를 복사입니다 strcopy()을 입력 한 다음 해당 텍스트를 const unsigned char*에서 const char*으로 변환 한 다음이 텍스트를 id, value 변수에 저장 한 다음 id, value을 새 항목으로 삽입하십시오. 이전 단계는 데이터베이스에서 가져 오는 각 데이터에서 발생합니다.

는 생각이 더 명확히 : 예를 들어
, 데이터베이스에서 가져온 세 개의 행 ( fruits, vegetables, sweets가) 있습니다. 지도 용기 내에 세 가지 데이터를 삽입 할 때
물론, 항목 수는 컨테이너 즉 세 가지 항목 ( fruits) ( vegetables) ( sweets) 일 것이다.

제 경우에는 항목 수를 확인할 때 하나의 항목 만 있고 항목은 sweets입니다.

이제 나머지 항목은 어디에 있습니까?

+1

'std :: map'에 사용하는 키는 ** id가 아닌 ** id이며,'id'의'char *'입니다. std :: string을 사용하여 메모리 누수가 있다고 생각하는 것이 좋습니다. – Galik

+0

마지막 질문에서'char *'의지도가 나쁜 디자인이라고 들었습니다. 할 수는 있지만이 코드와 마찬가지로 메모리 관리가 엉망이됩니다. – Blastfurnace

+0

@ 갈릭 : 고마워, 정확히, 나는 알고 있었지만 문자열 유형을 사용하지 않고 문제를 해결하는 방법을 알지 못했다. –

답변

1

동일한 메모리 슬래브를 세 번 덮어 쓰고 포인터를 슬래브에 세 번 저장하는 중입니다. 포인터가 변경되지 않기 때문에 맵과 관련하여 매번 동일한 값입니다.

정말 원하는 것은 포인터가 아닌 문자열 맵을 사용하는 것입니다. 이것은 또한 시도 - 캐치 블록하지 않고 코드 예외 안전 (적어도 문자열을) 만드는 장점이있다

#include <string> 

... 

map<string, string> records; 

string id, value; // size of allocation will be handled by the string class. 

sql->open(dbFile); 
sql->query("SELECT * FROM categories"); 
while(sql->fetch() != SQLITE_DONE){ 
    // string has an assignment operator from C-style strings 
    id = reinterpret_cast<const char*>(sql->getValue(0)); 
    value = reinterpret_cast<const char*>(sql->getValue(1)); 

    // more readable way of writing the insert. id, value will be copied into 
    // the map. 
    records[id] = value; 
} 

// freeing unnecessary; string class handles it when id, value go out of scope. 

을 : 당신이 std::string를 사용하는 경우이 훨씬 쉬울 것입니다. std::string의 소멸자는 범위 유지 방법에 관계없이 정리를 처리합니다.

+0

고맙겠지 만 문자열 유형을 사용하는 것을 제외하고는 어떤 방법이 있습니까? –

+0

@LionKing :'std :: map'에 삽입 한 __every__ 문자열에 메모리를 할당 할 수 있으며 적절한 시간에 한 번만 수동으로 메모리를 수동으로 해제해야합니다. 아니면'std :: string'이 당신을 위해 그 자원을 올바르게 관리하게 할 수 있습니다 ... – Blastfurnace

+0

당신이 그것을 사용하고 싶지는 않지만 있습니다. 진지하게, 그것은 암보다 나쁜 것입니다. 루프 내부에 새로운 C- 문자열을위한 새로운 메모리를 할당하고, 값을 복사 한 다음 맵에 저장해야합니다. 모든 C 스타일 문자열을 수동으로 정리해야합니다. 이러한 모든 할당에 대해 오류 처리를 수행해야합니다. 지도를 정렬 된 상태로 유지하려면 C 스타일 문자열로 작동하는 비교 functor를지도에 제공해야합니다. 당신은 그런 종류의 일을 정말로하고 싶지 않습니다. 저와 다른 모든 사람들을 신뢰하십시오. – Wintermute

관련 문제