Switch-Anweisung mit String-Datentyp
-
Hallo,
ich würde gerne wissen, wie man switch auf einen String
anwenden kann.Folgende Anweisung klappt nicht:
string sTest = "Hallo"; switch (sTest) { case "Tag": cout << "Fall Tag " << endl; break; case "Hallo": cout << "Fall Hallo " << endl; break; default: cout << "Unbekannte Anrede " << endl; break; }Ich möchte die switch-Anweisung auf folgenden Code anwenden:
#include <iostream> #include <string> using namespace std; template<typename T> void foo(T a) { //Check data type string sCheckTypeName = typeid(T).name(); if (sCheckTypeName == "int") { cout << "a = " << a << " int with " << sizeof(a) << "\t bytes. Call a int function" << endl; } else if (sCheckTypeName == "double") { cout << "a = " << a << " double with " << sizeof(a) << "\t bytes. Call a double function" << endl; } else { cout << "Not a provided data type: " << sCheckTypeName << endl; } } int main() { int nNumber = 10; double dNumber = 10.5; char* sName = "James"; __int64 i64Number = 20; foo(nNumber); foo(dNumber); foo(sName); foo(i64Number); cin.get(); return 0; }Vielen Dank
Thomas
-
Das wird nicht gehen, weil man bei case nur ganzzahlige Werte angeben kann, also z.B. int und char:
http://tutorial.schornboeck.net/switch.htm
Darauf sollte dich eigentlich dein Compiler aufmerksam gemacht haben.
-
Man kann switch auf Strings anwenden.
Undzwar kannst du einfach die Strings in Integer umwandeln.
Dafür kann man zum Beispiel den crc32-Alghoritmus verwenden.
Aber du kannst auch einfach selbst eine Funktion schreiben die irgendwie aus einem String eine mehr oder weniger einzigartige Zahl berechnet. Die Genauigkeit muss dabei ja nicht sooo hoch sein, da es relativ unwahrscheinlich ist, dass zwei Strings in einer einfachen Aufzählung exakt die gleichen Werte erreichen.Also mal angenommen du hast eine entsprechende Funktion namens crc32() zur Verfügung:
#include <iostream> #include "crc32.h" using namespace std; #define Z(str) crc32(str) int main( void ) { char* str = "Yes"; switch( Z(str) ) { case Z("Yes"): cout << "Yes" << endl; break; case Z("No"): cout << "No" << endl; break; default: break; } return 0; }Das Problem ist nur, dass Funktionsaufrufe als Argument für case ungültig sind.
Das heißt, der Alghoritmus müsste komplett im Makro definiert sein?
Hm, klingt kompliziert.
Die einzig andere Lösung die mir einfällt wäre das Schreiben einer eigenen String-Klasse und das Überladen des int()-Operators. Allerdings weiß ich nicht ob dies bei case gültig wäre oder nicht. Das müsste man ausprobieren.
-
@MAG
Deine Lösung wird nicht funktionieren. Die Argumente für case müssen Compiletime Konstanten sein. Und das will ich sehen, wie du aus String Literalen mittels crc32 ganzzahlige Compiletime Konstanten machst.
Theoretisch ist das zwar möglich, leider bietet C++ für sowas noch keine Möglichkeiten. Zudem ist das keine stabile Lösung, also nicht wirklich empfehlenswert. Wahrscheinlichkeit hin oder her.IdR ersetzt man das switch für Strings durch ein if/else Konstrukt.
string foo = ...; if (foo == "int") //... else if (foo == "double") //... else //...@Johnny2005
Für dein Problem gibt es in C++ allerdings eine ganz andere Lösung. Dafür schaust du dir am besten mal das Strategy Pattern an.template <class T> void strategy(T a); template <> void strategy(int a) { cout << "a = " << a << " int with " << sizeof(a) << "\t bytes. Call a int function" << endl; } template <> void strategy(double a) { cout << "a = " << a << " double with " << sizeof(a) << "\t bytes. Call a double function" << endl; } template <class T> void strategy(T a) { cout << "Not a provided data type: " << typeid(T).name() << endl; } template<typename T> void foo(T a) { //Check data type strategy<T>(a); }