2009-07-01 14 views
16

Sono sicuro che questo sarebbe stato chiesto prima ma non riuscivo a trovarlo. Esiste un sistema integrato (vale a dire che utilizza i metodi di std :: wstring o gli algoritmi) come un confronto insensibile tra maiuscole e minuscole i due oggetti wstring?Confrontando il wstring con l'ignorare il caso

+6

nota, che i confronti case-insensitive sono dipendente dal luogo. – avakar

+1

vedere http://stackoverflow.com/questions/11635/case-insensitive-string-comparison-in-c, io raccomanderei la soluzione Boost o l'estrazione di c_str e l'uso di wcscasecmp/_wcsicmp – Hasturkun

+0

@Hasturkun: Grazie per il link . Mi sono ricordato vagamente di aver letto questo su SO. – Naveen

risposta

27

Se non ti dispiace essere legato all'implementazione di Microsoft è possibile utilizzare questa funzione definita in <string.h>

int _wcsnicmp(
    const wchar_t *string1, 
    const wchar_t *string2, 
    size_t count 
); 

Ma se si vuole le migliori prestazioni/rapporto di compatibilità/funzionalità probabilmente sarà necessario esaminare la libreria di boost (parte di esso è stl comunque). Semplice esempio (tratto da different answer a diversi domanda):

#include <boost/algorithm/string.hpp> 

std::wstring wstr1 = L"hello, world!"; 
std::wstring wstr2 = L"HELLO, WORLD!"; 

if (boost::iequals(wstr1, wstr2)) 
{ 
    // Strings are identical 
} 
+3

Il prefisso di codifica L manca dalle stringhe letterali – mloskot

2

È possibile utilizzare std :: tolower() per convertire le stringhe in caratteri minuscoli o utilizzare la funzione wcscasecmp per eseguire un confronto senza distinzione tra maiuscole e minuscole nei c_str.

Ecco un funtore confronto è possibile utilizzare direttamente così:

struct ci_less_w 
{ 
    bool operator() (const std::wstring & s1, const std::wstring & s2) const 
    { 
     #ifndef _WIN32 
      return wcscasecmp(s1.c_str(), s2.c_str()) < 0; 
     #else 
      return _wcsicmp(s1.c_str(), s2.c_str()) < 0; 
     #endif 
    } 
}; 
+1

Penso che sia stata richiesta una soluzione di libreria standard. –

6

Utilizzando la libreria standard:

bool comparei(wstring stringA , wstring stringB) 
{ 
    transform(stringA.begin(), stringA.end(), stringA.begin(), toupper); 
    transform(stringB.begin(), stringB.end(), stringB.begin(), toupper); 

    return (stringA == stringB); 
} 

wstring stringA = "foo"; 
wstring stringB = "FOO"; 
if(comparei(stringA , stringB)) 
{ 
    // strings match 
} 
+11

che if (stringA == stringaB) mi costringe a lasciare un commento! :) deve essere restituito (stringA == stringaB) –

+4

Questa soluzione non funzionerà in diverse versioni locali, in alcune lingue quando si converte in maiuscolo e quindi indietro si ottengono stringhe diverse. – Stan

+1

Non hai semplicemente confrontato le stringhe, hai effettivamente fatto entrambe le stringhe MAIUSCOLE indipendentemente dal risultato. Prova a scrivere un metodo con la firma 'bool compare (const wstring stringA, const wstring stringB)', quindi correggi questo algoritmo. – Zak

-1

È possibile utilizzare mancata corrispondenza() o lexicographical_compare(). Ciò è suggerito da Scott Meyers in STL effecitve, voce 35.

+2

Esempio per quelli di noi che non hanno quel libro sarebbe bello. – Stan

+2

Si noti che nessuna di queste funzioni confronterà maiuscole/minuscole per impostazione predefinita. Dovresti comunque scrivere una funzione che confronti i caratteri in modo insensibile e passali a quelle funzioni. – Geerad

2
#include <algorithm> 
#include <string> 
#include <cstdio> 


bool icase_wchar_cmp(wchar_t a, wchar_t b) 
{ 
    return std::toupper(a) == std::toupper(b); 
} 


bool icase_cmp(std::wstring const& s1, std::wstring const& s2) 
{ 
    return (s1.size() == s2.size()) && 
      std::equal(s1.begin(), s1.end(), s2.begin(), 
           icase_wchar_cmp); 
} 



int main(int argc, char** argv) 
{ 
    using namespace std; 

    wstring str1(L"Hello"), str2(L"hello"); 

    wprintf(L"%S and %S are %S\n", str1.c_str(), str2.c_str(), 
       icase_cmp(str1,str2) ? L"equal" : L"not equal"); 

    return 0; 
} 
2

Parlando inglese giusto?! anche se mi piacerebbe andare con la mia bella Boost :)

bool isequal(const std::wstring& first, const std::wstring& second) 
{ 
    if(first.size() != second.size()) 
     return false; 

    for(std::wstring::size_type i = 0; i < first.size(); i++) 
    { 
     if(first[i] != second[i] && first[i] != (second[i]^32)) 
      return false; 
    } 

    return true; 
} 
+3

+1. (secondo [i]^32) è interessante. Non ho mai saputo che fosse così che ascii è stato progettato! – Sahas

+0

Questo prenderà in considerazione '[' per essere uguale a '{', e '*' per essere uguale a una nuova riga, insieme a molte altre imprecisioni. Inoltre, assumere l'inglese quando si ha a che fare con stringhe larghe è quasi certamente sbagliato. – interjay

+0

per ASCII funziona, ma per wchar_t? Forse no? – Nayan

1

Se è necessario che la stringa farà sempre caso comparazione insensitive (quando si utilizza operatori == o =!), quindi una possibile soluzione elegante è di ridefinire char_traits: : confronta il metodo.

Definire la propria struttura. Esempio

struct my_wchar_traits: public std::char_traits< wchar_t> 
{ 
    static int compare(const char_type* op1, const char_type* op2, std::size_t num) 
    { 
     // Implementation here... any of the previous responses might help... 
    } 
}; 

Quindi, definire il proprio caso stringa insensitive:

typedef std::basic_string< wchar_t, my_wchar_traits> my_wstring; 
Problemi correlati