Wie lange Schaltanweisungen vermieden werden können? C ++

8

Ich arbeite an einem "Wörterbuch" für meine Klasse. Ich habe ein int-Array namens NumOfWordsInFile[] , wobei NumOfWordsInFile[0] der Anzahl der Wörter in A.txt entspricht und NumOfWordsInFile[25] entspricht Z.txt

Wie es jetzt ist, habe ich einen großen Schalter für die 26 verschiedenen Buchstabenkonditionen. Ich habe eine Funktion namens AddWord(string word) . AddWord ruft den ersten Buchstaben des Wortes ab und fügt es in die entsprechende .txt-Datei ein. Jetzt ist hier das Problem. Jedes Mal, wenn ein Wort zu A.txt hinzugefügt wird, muss NumOfWordsInFile[0] um 1 erhöht werden. Die einzige Möglichkeit, dies zu tun, ist mit diesen riesigen Schaltern. Ich habe auch eine Funktion deleteWord, die umgekehrt NumOfWordsInFile[] dekrementiert, wenn das Wort gelöscht wird. Jetzt möchte ich nicht zwei 26 Case Switches haben, aber das Problem ist, ich weiß nicht, wie ich es sonst tun soll. Jetzt könnte ich das gleiche für die Löschfunktion tun, aber ich möchte wirklich nicht Hunderte weitere Codezeilen durchgehen lassen. Gibt es einen besseren Weg, dies zu tun?

Beispiel des Schalters in der Funktion AddWord :

%Vor%

Löschfunktion.

%Vor%     
Tyler Pfaff 03.04.2011, 23:13
quelle

8 Antworten

3

Zeichen sind im Grunde Zahlen. "a" ist 97, "b" ist 98 und so weiter. Der einfachste Weg besteht darin, einfach alle numOfWordsInFile[n] durch numOfWordsInFile[current_char - 'a'] zu ersetzen und der gesamte Code, der für jeden Fall wiederholt wird, kann in einer Funktion wie dieser liegen:

%Vor%

Für allgemeinere Lösungen lesen Sie über Hash-Maps und Funktionszeiger (wenn Sie beispielsweise für jedes Zeichen eine andere Funktion zuweisen möchten.

    
chemical 03.04.2011, 23:28
quelle
7

Wenn Sie nur einen kurzen Blick darauf werfen, scheint es, als ob Sie die Position des Buchstabens im Alphabet verwenden, um etwas zu tun.

Sie könnten alle Ihre switch-Anweisungen durch eine Anweisung ersetzen, die wie folgt aussieht:

%Vor%

ActualLetter ist etwas wie "a", zum Beispiel.

Wenn Sie in der Zukunft große Switch-Anweisungen haben, sollten Sie in Erwägung ziehen, den Code in Funktionen zu kapseln:

%Vor%

Oder noch besser, Sie können Polymorphie verwenden, um C ++ - Versand an die gewünschte Methode basierend auf der spezifischen abgeleiteten Klasse zu ermöglichen:

%Vor%

Beachten Sie, dass dynamischer Versand einen (leichten) Leistungseinbruch hat und das oben genannte ist ein sehr schlechter Ort, um es tatsächlich zu benutzen. Die Lösung, die ich, RedX und andere gepostet habe, ist viel besser für dein spezifisches Beispiel geeignet.

    
Mike Bailey 03.04.2011 23:17
quelle
6

In den meisten praktischen Zeichenkodierungen, die Sie wahrscheinlich bei der Verwendung von C oder C ++ finden, sind 'a' bis 'z' zusammenhängend, sodass Sie den Array-Index verwenden können, indem Sie einfach (c - 'a') , wo% co_de eingeben % ist die c , die Sie betrachten.

    
Oliver Charlesworth 03.04.2011 23:17
quelle
5
%Vor%

Alternativ:

%Vor%     
Erik 03.04.2011 23:19
quelle
3
%Vor%

Dies funktioniert nur, wenn Sie nur englische Buchstaben in Ihrem Anwendungsfall haben.

    
RedX 03.04.2011 23:17
quelle
2

Einzelne Zeichen in C ++ sind wirklich nur Zahlen, die ihren ASCII-Werten entsprechen. Sie können Buchstaben voneinander subtrahieren, um numerische Werte zu erhalten. Wenn also word[0] den Buchstaben A enthält, dann wird word[0] - 'A' 0 sein.

So können Sie Ihr numOfWordsInFile -Array direkt indizieren, und Sie brauchen überhaupt keinen Schalter: numOfWordsInFiled[word[0] - 'A'] .

Beachten Sie, dass 'A' and 'a' unterschiedliche numerische Werte haben. Sie müssen also etwas mehr arbeiten, wenn Sie Groß- und Kleinschreibung mischen.

    
SoapBox 03.04.2011 23:18
quelle
1

Wenn Ihre Datei A.txt ist, geben Sie an, dass Ihr Array-Index 'A' - 'A' (= 0) ist. Wenn die Datei B.txt ist, geben Sie den Array-Index 'B' - 'A' (= 1) usw. an.

    
jonsca 03.04.2011 23:16
quelle
1

Es hängt davon ab, wie tragbar Sie sein möchten oder wie internationalisiert. Wenn Sie es sich leisten können, die Möglichkeit zu ignorieren dass der erste Buchstabe ein akzentuiertes Zeichen sein könnte, und nehme an dass du nie auf einem Mainframe oder irgendwo laufen wirst Wenn Sie EBCDIC verwenden, können Sie den ersten Buchstaben in einen bestimmten Fall und subtrahieren "a" oder "A" (je nach Fall) daraus den Index zu erhalten. Der C ++ - Standard garantiert nicht dass die Buchstaben jedoch zusammenhängend sind und nicht in EBCDIC, noch in irgendeiner der Kodierungen, die akzentuiert unterstützen Figuren. Zumindest müssen Sie das testen Das erste Zeichen ist natürlich ein Buchstabe.

Das Problem der Internationalisierung ist schwierig, da Es gibt keine allgemein verwendete Codierung, und einige der Kodierungen sind Multibyte. Für die Einzelbyte-Kodierungen ist es ziemlich geradlinig, um eine Mapping-Tabelle zu verwenden; ein Tisch mit 256 Einträge, indiziert durch den ersten Buchstaben (in unsigned umgewandelt char), die den Index in Ihre Tabelle zurückgibt. Für Multibyte Kodierungen, wie UTF-8, das Problem ist komplizierter: Sie können das Anfangszeichen in einer UTF-8-Sequenz in ein int übersetzen, aber Sie können mit Werten um eine Million oder mehr und Ihnen enden Ich möchte keine Tabelle mit einer Million Einträge (die meisten davon sind völlig irrelevant. Eine einfache Lösung könnte sein, hinzuzufügen ein 27. Eintrag für "andere". (Das würde auch "Wörter" wie fangen "2nd".)

Eine sehr portable Möglichkeit wäre:

%Vor%

Vergessen Sie nicht, das Anfangszeichen auf ein Zeichen ohne Vorzeichen zu setzen vor der Indizierung.

    
James Kanze 04.04.2011 08:26
quelle