2010-11-27 14 views
14

¿Cómo se tiene una inserción insensible a mayúsculas y minúsculas o se busca una cadena en std :: set?std insensible a mayúsculas y minúsculas :: conjunto de cadenas

por ejemplo-

std::set<std::string> s; 
s.insert("Hello"); 
s.insert("HELLO"); //not allowed, string already exists. 
+1

Puede aclarar un poco lo que se entiende por 'caso inserción sensible'? – Jon

Respuesta

31

Es necesario definir un comparador personalizado:

struct InsensitiveCompare { 
    bool operator() (const std::string& a, const std::string& b) const { 
     return stricmp(a.c_str(), b.c_str()) < 0; 
    } 
}; 

std::set<std::string, InsensitiveCompare> s; 
+11

Cuando leo InsensitiveCompare no pude evitar pensar en mi suegra. +1. – Fozi

+0

Este enfoque no funcionará correctamente si hay caracteres NUL en una cadena. Ver [esta pregunta] (https://stackoverflow.com/questions/11635/case-insensitive-string-comparison-in-c). – Sauron

2

std :: conjunto ofrece la posibilidad de proporcionar su propio comparador (al igual que la mayoría de envases std). A continuación, puede realizar cualquier tipo de comparación que desee. Ejemplo completo está disponible here

0

De lo que he leído esto es más portátil que stricmp() porque stricmp() no es, de hecho, parte de la biblioteca std , pero solo implementado por la mayoría de los proveedores de compiladores. Como resultado a continuación, mi solución es simplemente la suya.

#include <string> 
#include <cctype> 
#include <iostream> 
#include <set> 

struct caseInsensitiveLess 
{ 
    bool operator()(const std::string& x, const std::string& y) 
    { 
    unsigned int xs (x.size()); 
    unsigned int ys (y.size()); 
    unsigned int bound (0); 

    if (xs < ys) 
     bound = xs; 
    else 
     bound = ys; 

    { 
     unsigned int i = 0; 
     for (auto it1 = x.begin(), it2 = y.begin(); i < bound; ++i, ++it1, ++it2) 
     { 
     if (tolower(*it1) < tolower(*it2)) 
      return true; 

     if (tolower(*it2) < tolower(*it1)) 
      return false; 
     } 
    } 
    return false; 
    } 
}; 

int main() 
{ 
    std::set<std::string, caseInsensitiveLess> ss1; 
    std::set<std::string> ss2; 

    ss1.insert("This is the first string"); 
    ss1.insert("THIS IS THE FIRST STRING"); 
    ss1.insert("THIS IS THE SECOND STRING"); 
    ss1.insert("This IS THE SECOND STRING"); 
    ss1.insert("This IS THE Third"); 

    ss2.insert("this is the first string"); 
    ss2.insert("this is the first string"); 
    ss2.insert("this is the second string"); 
    ss2.insert("this is the second string"); 
    ss2.insert("this is the third"); 

    for (auto& i: ss1) 
    std::cout << i << std::endl; 

    std::cout << std::endl; 

    for (auto& i: ss2) 
    std::cout << i << std::endl; 

} 

de salida con el caso insensible conjunto y conjunto regular que muestra la misma pedido:

This is the first string 
THIS IS THE SECOND STRING 
This IS THE Third 

this is the first string 
this is the second string 
this is the third 
+0

Una pequeña observación: si está trabajando con, por ejemplo, Texto en griego, esto no funcionará porque, en general, no es posible implementar una comparación de mayúsculas y minúsculas con 'tolower' solo. El ejemplo de libro de texto para esta imposibilidad es ΌΣΟΣ que no distingue entre mayúsculas y minúsculas, lo mismo que όσος (que en griego significa "tantos como"). –

Cuestiones relacionadas