In C gibt es ein switch
Konstrukt, das es einem ermöglicht, verschiedene bedingte Codezweige basierend auf einem ganzzahligen Testwert auszuführen, z.
int a;
/* Read the value of "a" from some source, e.g. user input */
switch ( a ) {
case 100:
// Code
break;
case 200:
// Code
break;
default:
// Code
break;
}
Wie ist es möglich, dasselbe Verhalten (dh vermeiden Sie die sogenannte " if
- else
Leiter") für einen Zeichenfolgenwert, dh a, zu erhalten char *
?
c
switch-statement
Niklas
quelle
quelle
Antworten:
Wenn Sie meinen, wie man etwas Ähnliches schreibt:
Dann besteht die kanonische Lösung in C darin, eine If-else-Leiter zu verwenden:
quelle
switch (something) { case A: /*...*/ break; case B: /*...*/ break; }
.Wenn Sie viele Fälle haben und nicht viele
strcmp()
Anrufe schreiben möchten , können Sie Folgendes tun:Sie müssen nur sicherstellen, dass Ihre Hash-Funktion keine Kollisionen innerhalb der Menge möglicher Werte für die Zeichenfolge aufweist.
quelle
[a-zA-Z0-9_]
? Irgendein Beispiel?uint
s, deren Bits als 8 1-Byte- ASCIIs behandelt werdenchar
. Ich habe dies vor einiger Zeit für Schlüsselvergleiche innerhalb einer Hash-Tabelle in C implementiert. Sie eliminieren somit die Notwendigkeit von Hashing oder Buckets. Das Problem tritt dort auf, wo Sie 64 Bit überschreiten müssen. Sie zahlen dann die Kosten für Bedingungen, während Sie jeden Satz von 8char
s in der vollständigen Zeichenfolge durchlaufen. Es sei denn, Sie rollen die Schleife ab, wenn Sie die maximale Größe der Schlüssel kennen. Es ist ein feiner Balanceakt.In C gibt es keine Möglichkeit, dies zu tun. Es gibt viele verschiedene Ansätze. In der Regel ist es am einfachsten, eine Reihe von Konstanten zu definieren, die Ihre Zeichenfolgen darstellen, und nach Zeichenfolgen zu suchen, um die Konstante zu erhalten:
Es gibt natürlich effizientere Möglichkeiten, dies zu tun. Wenn Sie Ihre Schlüssel sortiert halten, können Sie eine binäre Suche verwenden. Sie können auch eine Hashtabelle verwenden. Diese Dinge verändern Ihre Leistung auf Kosten der Wartung.
quelle
Meine bevorzugte Methode hierfür ist eine Hash-Funktion (von hier ausgeliehen ). Auf diese Weise können Sie die Effizienz einer switch-Anweisung auch dann nutzen, wenn Sie mit char * arbeiten:
Dieser Ansatz erfordert natürlich, dass die Hash-Werte für alle möglichen akzeptierten Zeichen im Voraus berechnet werden. Ich denke nicht, dass dies ein zu großes Problem ist. da die switch-Anweisung jedoch unabhängig davon mit festen Werten arbeitet. Ein einfaches Programm kann erstellt werden, um Zeichen durch die Hash-Funktion zu leiten und ihre Ergebnisse auszugeben. Diese Ergebnisse können dann wie oben beschrieben über Makros definiert werden.
quelle
Ich denke, der beste Weg, dies zu tun, besteht darin, die "Erkennung" von der Funktionalität zu trennen:
quelle
Es gibt eine Möglichkeit, die Zeichenfolgensuche schneller durchzuführen. Annahmen: Da es sich um eine switch-Anweisung handelt, kann ich davon ausgehen, dass sich die Werte zur Laufzeit nicht ändern.
Die Idee ist, qsort und bsearch der C stdlib zu verwenden.
Ich werde an xtofls Code arbeiten.
quelle
Um die obige Antwort von Phimueme zu ergänzen: Wenn Ihre Zeichenfolge immer aus zwei Zeichen besteht, können Sie aus den beiden 8-Bit-Zeichen ein 16-Bit-Int erstellen - und dieses aktivieren (um verschachtelte switch / case-Anweisungen zu vermeiden).
quelle
To add to Phimueme's answer above
können Sie die Kommentarfunktion verwenden. :)Ich habe eine Header-Datei veröffentlicht , um das Umschalten der Zeichenfolgen in C durchzuführen. Sie enthält eine Reihe von Makros, die den Aufruf von strcmp () (oder ähnlichem) verbergen, um ein switch-ähnliches Verhalten nachzuahmen. Ich habe es nur mit GCC unter Linux getestet, bin mir aber ziemlich sicher, dass es zur Unterstützung anderer Umgebungen angepasst werden kann.
BEARBEITEN: Fügen Sie den Code hier wie gewünscht hinzu
Dies ist die Header-Datei, die Sie einschließen sollten:
Und so benutzt du es:
quelle
Wir können der if-else-Leiter nicht entkommen, um eine Zeichenfolge mit anderen zu vergleichen. Selbst ein normaler Switch-Case ist intern auch eine If-else-Leiter (für ganze Zahlen). Wir möchten möglicherweise nur das Switch-Case für String simulieren, können aber niemals die if-else-Leiter ersetzen. Die besten Algorithmen für den Zeichenfolgenvergleich können sich der Verwendung der Funktion strcmp nicht entziehen. Bedeutet, Zeichen für Zeichen zu vergleichen, bis eine Nichtübereinstimmung gefunden wird. Die Verwendung von if-else-Leiter und strcmp ist daher unvermeidlich.
DEMO
Und hier sind die einfachsten Makros, um den Schaltfall für Zeichenfolgen zu simulieren.
Und Sie können sie als verwenden
Ausgabe:
Unten ist die Verwendung von verschachtelten SWITCHs aufgeführt:
Ausgabe:
Hier ist die umgekehrte Zeichenfolge SWITCH, in der Sie eine Variable (anstelle einer Konstante) in der CASE-Klausel verwenden können:
Ausgabe:
quelle
So mache ich das im Allgemeinen.
quelle
case 'B'<<8+'1':
würde dies klarer machen, denke ich, als 0x4231.#define twochar(a) (((uint16_t)a[1]<<8)|a[0])
Das ist wie man es macht. Nein nicht wirklich.
quelle
Wenn es sich um eine 2-Byte-Zeichenfolge handelt, können Sie so etwas wie in diesem konkreten Beispiel tun, in dem ich ISO639-2-Sprachcodes einschalte.
LANIDX_ * sind konstante Ganzzahlen, die zum Indizieren in Arrays verwendet werden.
quelle
Unter der Annahme einer geringen Endianness und Größe von (char) == 1 könnten Sie dies tun (so etwas wurde von MikeBrom vorgeschlagen).
Es könnte für den BE-Fall verallgemeinert werden.
quelle
Funktionszeiger sind eine gute Möglichkeit, dies zu tun, z
result = switchFunction(someStringKey); //result is an optional return value
... ruft eine Funktion auf, die Sie mit der Zeichenfolgentaste festgelegt haben (eine Funktion pro Fall):
Verwenden Sie eine bereits vorhandene Implementierung von Hashmap / Tabelle / Wörterbuch wie khash, geben Sie diesen Zeiger auf eine Funktion innerhalb von zurück
switchFunction()
und führen Sie sie aus (oder geben Sie sie einfach von zurückswitchFunction()
und führen Sie sie selbst aus). Wenn die Map-Implementierung dies nicht speichert, verwenden Sieuint64_t
stattdessen ein, das Sie entsprechend in einen Zeiger umwandeln.quelle
Hallo, das ist der einfache und schnelle Weg, wenn Sie diesen Fall haben:
[Schneller Modus]
[ERKLÄRTER Modus]
Zum Beispiel: Ich habe viele Menüs, jede Auswahl im 1. Menü führt Sie zum 2. Menü, dasselbe mit dem 2. Menü und dem 3. Menü. Aber die Optionen sind unterschiedlich, so dass Sie wissen, dass der Benutzer endgültig gewählt hat. Beispiel:
Menü 1: 1 ==> Menü 2: 4 ==> Menü 3: 2 (...) Die Auswahl ist 142. Andere Fälle: 111,141,131,122 ...
Sollution: Speichern Sie die erste 1. in a, 2. in b, 3. auf c. a = 1, b = 4, c = 2
quelle