2013-09-30 7 views
11

Jestem nowy w Stl's. Oto mój poniżej program.jak zrobić stl :: map kluczowych nieuwzględniających wielkości liter

typedef pair<string, int> p; 
int main(int argc, char *argv[]) 
{ 
    map<string,int> st; 
    st.insert(p("hello",1)); //Inserted "hello" as key to map. 
    st.insert(p("HELLO",1)); //Inserted "HELLO" as key to map. 
    cout<<"size="<<st.size()<<endl; //Output is 2 because two records found "hello" and "HELLO" 
    return 0; 
} 

Nie chcę uwzględniać powtarzających się zmian wielkości liter (wielkimi i małymi lub odwrotnie). Tutaj "st.insert (p (" HELLO ", 1));" powinien zawieść, stąd nie. rekordów powinno wynosić "1" zamiast "2". Czy jest jakaś flaga ustawiona lub podobna?

Nie mogłem znaleźć powiązanych pytań, dlatego wysłałem to pytanie.

Każda pomoc jest wdzięczna.

+3

Najprostszym sposobem jest zamienić je na małe litery przed dodaniem do mapy. – zch

Odpowiedz

26

użyć niestandardowego komparatora:

struct comp { 
    bool operator() (const std::string& lhs, const std::string& rhs) const { 
     return stricmp(lhs.c_str(), rhs.c_str()) < 0; 
    } 
}; 

std::map<std::string, int, comp> st; 

Edit: Jeśli nie jesteś w stanie wykorzystać stricmp lub strcasecmp użytku:

#include<algorithm> 
//... 
string tolower(string s) { 
    std::transform(s.begin(), s.end(), s.begin(), ::tolower); 
    return s; 
} 
struct comp { 
    bool operator() (const std::string& lhs, const std::string& rhs) const { 
     return tolower(lhs) < tolower(rhs); 
    } 
}; 

std::map<std::string, int, comp> st; 
+6

Nie polecam drugiej opcji (z funkcją 'tolower'), ponieważ tworzy ona nowy ciąg znaków. Co oznacza kilka "nowych" i "usuwania" na operatora porównania. Które GREATLY spowalniają cię. Zwraca również porównanie z 'O (1)' średnio (większość łańcuchów różni się w pierwszym znaku) do 'O (s)' gdzie s jest średnim rozmiarem ciągu. Zamiast pojedynczego porównania znaków otrzymujesz 2 'nowe', 2' usuń', 2xs 'tolower' ... nie. – rabensky

+0

Czy możesz wyjaśnić, dlaczego powrót jest <0, a nie == 0? Myślałem, że z funkcjami str *** cmp, mniej niż zero wskazuje, że lewa strona jest podłańcuchem prawej ręki, gdzie równe dopasowanie wynosi 0. –

+1

@TechnikEmpire Mapa jest oparta na porównaniu "mniej niż": Domyślny komparator jest predykatem 'std :: less'. To samo zachowanie osiąga się tutaj, sprawdzając, czy 'stricmp (lhs, rhs)' jest mniejsze niż 0. –

2

Istnieją dwa sposoby, aby to zrobić

Po pierwsze - zmień funkcję "porównania", aby ignorować przypadek

Po drugie - za każdym razem, gdy użyjesz ciągu znaków do wprowadzenia lub uzyskania wartości z mapy, zawiń ją funkcją, która zamienia ją na małe litery.

Na pierwszym wszystko, co trzeba zrobić, to stworzyć „klasę funkcji” (klasa wraz z obsługą operatorską()), który otrzymuje dwa ciągi i zwrotów czy lewica jest „mniejsza” niż po prawej stronie:

struct my_comparitor{ 
    bool operator()(const std::string &a, const std::string &b){ 
    // return iwhether a<b 
    } 
}; 

std::map<std::string,DATA_TYPE,my_comparitor> my_map; 

na drugi prostu to zrobić:

std::map<std::string,DATA_TYPE> my_map; 
my_map.insert(std::make_pair(TO_LOWERCASE("hello"),1)); 
iter=my_map.find(TO_LOWERCASE(key)); 
cout << my_map[TO_LOWERCASE(name)]; 
// etc. 

nie jestem pewien, czy to funkcja, która zamienia na małe litery jest już częścią STL - ale tak czy inaczej jest to łatwe do napisania.