2009-08-21 7 views
1

if Anweisung sieht zu peinlich, weil ich eine Möglichkeit brauche, die Anzahl der Konstaanten zu erhöhen. Entschuldigung dafür, dass ich dich durch diese "Konstante" in die Irre führe, anstatt, was ich meinte.Was ist der beste Weg, eine String-Variable mit einer Reihe von String-Konstanten zu vergleichen?

+3

Möchten Sie wirklich eine ** Konstante ** mit einer Reihe von ** Konstanten ** vergleichen? Das Ergebnis dieses Tests ist statisch bekannt, oder? –

+0

Er könnte einen nicht konstanten Zeiger auf eine konstante Zeichenkette bedeuten: 'const char * blah =" foo "; if (isRiemannHypothesisTrue()) blah = "bar"; '. Dann überprüfe, ob Blah im Set ist. –

+0

zu onebyone - ich denke, ich habe eine Frage gestellt, bevor ich denke =) Ich muss eine Zeichenfolge analysieren, wenn die Funktion also ein Schlüsselwort sieht, sollte es durch einen anderen Zeichenfolgenwert ersetzt werden. – mknight

Antwort

2

Setzen Sie die zu vergleichenden Strings in einen statischen Vektor oder Satz und verwenden Sie dann den std :: find-Algorithmus.

+4

Verwenden Sie nicht std :: find auf Sätzen oder Karten. Die Suche nach Mitgliedsfunktionen ist für diese Typen viel effizienter – Glen

+0

Ja, Sie haben Recht. – Naveen

9

alle Konstanten zu einem std hinzufügen :: set, dann können Sie prüfen, ob der Satz mit

Zeichenfolge enthält
std::set<std::string> myLookup; 
//populate the set with your strings here 

set<std::string>::size_type i; 

i = myLookup.count(searchTerm); 
if(i) 
    std::cout << "Found"; 
else 
    std::cout << "Not found"; 
+1

Scott Meyers würde vorschlagen, dass Sie hier "zählen" anstatt "finden" verwenden. Es ist auch weniger Code. –

+0

Und er hätte recht gehabt. Ich habe nur vergessen, zählen, ich habe nicht lange verwendet.Ich werde meine Antwort aktualisieren – Glen

+0

Denken Sie daran, dass das Set sollte statisch und gefüllt sein, nur wenn es leer ist oder nur sicherstellen, dass es für Sie verfügbar ist aber nur einmal gefüllt, wenn Sie es effizient arbeiten möchten;) – RnR

0
const char * values[]= { "foo", "bar", ..., 0 }; 

bool IsValue(const std::string & s) { 
    int i = 0; 
    while(values[i]) { 
     if (s == values[i]) { 
     return true; 
     } 
     i++; 
    } 
    return false; 
} 

Oder eine std :: set.

3

Hängt davon ab, ob Ihnen die Leistung wichtig ist.

Wenn nicht, dann ist der einfachste Code wahrscheinlich die verschiedenen Strings in ein Array (oder Vektor, wenn Sie wollen, dass Sie die Anzahl der Konstanten zur Laufzeit erhöhen wollen). Dies wird auch für eine kleine Anzahl von Saiten ziemlich schnell sein:

static const char *const strings[] = { "fee", "fie", "fo", "fum" }; 
static const int num_strings = sizeof(strings)/sizeof(char*); 

dann entweder:

int main() { 
    const char *search = "foe"; 
    bool match = false; 
    for (int i = 0; i < num_strings; ++i) { 
     if (std::strcmp(search, strings[i]) == 0) match = true; 
    } 
} 

Oder:

struct stringequal { 
    const char *const lhs; 
    stringequal(const char *l) : lhs(l) {} 
    bool operator()(const char *rhs) { 
     return std::strcmp(lhs, rhs) == 0; 
    } 
}; 

int main() { 
    const char *search = "foe"; 
    std::find_if(strings, strings+num_strings, stringequal(search)); 
} 

[Warnung: Ich habe nicht den obigen Code getestet , und ich habe die Signaturen schon mehrmals falsch ...]

Wenn Sie sich um Leistung kümmern, und es gibt eine Reas onable Anzahl der Strings, dann wäre eine schnelle Option so etwas wie ein Trie. Aber das ist eine Menge Aufwand, da es in der C++ - Standardbibliothek keinen gibt. Sie können viel von dem Vorteil erhalten entweder ein sortiertes Array/Vektor verwendet, suchten mit std::binary_search:

// These strings MUST be in ASCII-alphabetical order. Don't add "foo" to the end! 
static const char *const strings[] = { "fee", "fie", "fo", "fum" }; 
static const int num_strings = sizeof(strings)/sizeof(char*); 

bool stringcompare(const char *lhs, const char *rhs) { 
    return std::strcmp(lhs, rhs) < 0; 
} 

std::binary_search(strings, strings+num_strings, "foe", stringcompare); 

... oder std::set verwenden. Aber solange Sie die Menge der Zeichenketten zur Laufzeit nicht ändern, hat die Verwendung einer Menge über ein sortiertes Array mit binärer Suche keinen Vorteil, und eine Menge (oder ein Vektor) muss mit Code gefüllt werden, während ein Array statisch initialisiert werden kann . Ich denke C++ 0x wird Dinge verbessern, mit Initialisierungslisten für Sammlungen.

+0

+1 für die Nennung von sortierten 'Vektor 'mit' binary_search'. – avakar

1

Die technisch beste Lösung ist: Erstellen Sie eine 'perfekte Hash-Funktion', die auf Ihre Menge von String-Konstanten zugeschnitten ist, damit später beim Hashing keine Kollisionen auftreten.

+0

Ich mag das Denken, aber das Problem ist - nicht nur konstant sollte nicht kollidieren, aber die mögliche Eingabe Zeichenfolge auch. –

Verwandte Themen