string in switch case Anweisung



  • Hallo,

    ich habe in einer Klasse eine static const Variable vom Datentyp string deklariert.
    Nun wollte ich in einer switch case Anweisung einen String auswerten, aber irgendwie meckert mein Compiler das der case Ausdruck keine Konstante ist.

    Bsp.:

    class A
    {
          ...
       private:
          static const string HALLO_A;
    
          void print( void ) const
          {
             string a = "A";
    
             switch( a.c_str()[0] )
             {
                case HALLO_A:
                    cout << "HALLO_A" << endl;
                    break;
             }
          }
          ...
    }
    
    const string A::HALLO_A = "A";
    

    Dies ist jetzt nur ein Sinnlosbeispiel spiegelt aber sehr gut mein Anliegen wieder.

    Auch wenn ich die static const Variable als char deklariere geht dies nicht.
    Gibt es eine Möglichkeit dennoch mein Vorhaben umzusetzen?

    mfg rendner



  • std::map



  • Hallo,

    Hm deine Frage ist etwas wirsch gestellt, meinst du sowas ?

    BTW: Habs mal als Funktion geschrieben, ging schneller 😉

    inline void Output(char chCheck)
    {
        const char  chA = 'A',
                    chB = 'B';
    
    	switch(chCheck)
    	{
    		case chA: cout << "HALLO_A" << endl; break;
    		case chB: cout << "HALLO_B" << endl; break;
    		default: cout << "FEHLER" << endl; break;
    	}
    }
    // UNICODE-Ready ist das nat. nicht!
    

    tja ich weiß zwar nicht was du damit bezwecken willst, oder ob es das ist was du meinst...aber bitte schonmal 😃



  • @ we:
    Wäre ne alternative halte ich aber fast für meinen Fall zu umständlich.

    @ CodeFinder:
    Aufgrund deines funktionierenden Beispieles habe ich auch noch einmal schnell ne Kleine Klasse gebaut in der alles funktioniert.

    #ifndef _A_H
    #define _A_H
    
    #include <iostream>
    using namespace std;
    
    class A
    {
    
    	public:
    
    		A( string str ): m_str( str )
    		{
    			m_str += A::PRINT_END;
    		};
    		~A( void ){};
    
    		void print( void ) const{ printString( &m_str ); };
    
    	private:
    
    		void printString( const string *str ) const;
    		string m_str;
    
    		static const char PRINT_HALLO;
    		static const char PRINT_HELLO;
    		static const char PRINT_END;
    
    };
    #endif
    
    const char A::PRINT_HALLO = 'x';
    const char A::PRINT_HELLO = 'y';
    const char A::PRINT_END   = '_';
    
    void A::printString( const string *str ) const
    {
    
    	for( unsigned int i = 0; i < str->size(); i++ )
    	{
    		switch( str->c_str()[i] )
    		{
    			case A::PRINT_HALLO:
    				cout << "A::PRINT_HALLO" << endl;
    				break;
    
    			case A::PRINT_HELLO:
    				cout << "A::PRINT_HELLO" << endl;
    				break;
    
    			default:
    				cout << "..." << endl;
    		}
    	}
    }
    

    Und in diesem Beispiel funktioniert alles tadelos.

    In meiner grösseren Klasse ist eigentlich alles genauso bis auf den Aufruf aber er meckert ja erst beim case.
    Hier ist der relevante Teil mal zu sehen:

    class B
    {
    	//...
    
    	private: 
    		static const char PRINT_PATH_1;
    
    		void printPath( const string *path ) const
    		{
    			uint i = 0;
    			uint l = path->size();
    
    			while( i < l )
    			{
    				switch( path->c_str()[i] )
    				{
    					case PRINT_PATH_1:
    						cout << "Path_1" << endl;
    						break;
    
    					default: cout << "gibts nich! " << endl;
    
    				}
    				++i;
    			}
    		}
    
    		void print( void ) const
    		{
    			// m_path ist vom Datentyp std::list<string>
    			printPath( &m_path.front() );
    		}
    
    	//...
    }:
    
    const char B::PRINT_PATH_1 = '1';
    


  • rendner schrieb:

    aber er meckert ja erst beim case

    d.h. genau ?

    ahso dann:

    void printPath( const string *path ) const
            {
                uint i = 0;
                uint l = path->size();
    
                while( i < l )
                {
                    switch( path->c_str()[i] )
                    {
                        case PRINT_PATH_1:
                            cout << "Path_1" << endl;
                            break;
    
                        default: cout << "gibts nich! " << endl;
    
                    }
                    ++i;
                }
            }
    

    soooo sauber is der Code nicht...du solltest 'path' auf Gültigkeit prüfen!
    wg. Speicherverletzungen! ⚠



  • Dein Code ist doch der gleiche wie meiner, oder sollte das keine Lösung meines Problemes sein, oder funktioniert das bei dir?

    rendner schrieb: aber er meckert ja erst beim case

    CodeFinder antwortete: d.h. genau ?

    Der Compiler meint das der case Ausdruck keine Konstante ist.
    Aber nur in dem etwas Komplexerem Beispiel ( class B ) in dem einfachem geht es ja und ich würde jetzt zu gerne Wissen wieso es bei mir in dem Komplexerem nicht klappen sollte.

    Ach ja das uint ist ein unsigned int.

    du solltest 'path' auf Gültigkeit prüfen!
    wg. Speicherverletzungen!

    Und wie müsste das eventuell aussehen?
    ( reicht sicherlich wenn du es nur mal grob erklärst )

    mfg rendner



  • AFAIK kann man keine Strings über ein die switch-Anweisung vergleichen. Nimm halt if ... else if ... usw.
    Den Grund weiss ich nicht mehr, aber es stand hier im Forum. Suche hat grad nicht geholfen.



  • @ don_basto:
    Ich vergleiche ja auch keine strings sondern nur ein einzelnes Zeichen und das geht!

    Ich will halt nur den Unterschied wissen ( oder zumindest meinen Fehler finden ) warum es bei der einen Variante geht und bei der anderen nicht damit ich das beheben kann.


  • Mod

    rendner schrieb:

    @ don_basto:
    Ich vergleiche ja auch keine strings sondern nur ein einzelnes Zeichen und das geht!

    Ich will halt nur den Unterschied wissen ( oder zumindest meinen Fehler finden ) warum es bei der einen Variante geht und bei der anderen nicht damit ich das beheben kann.

    es genügt für ein case-label nicht, konstant zu sein, es muss auch ein konstanter ausdruck sein. das bedeutet, dass const variablen in diesem ausdruck auch initialisiert werden müssen - ein konstanter ausdruck kann nur entstehen, wenn der exakte wert bereits an dieser stelle berechenbar ist. das ist in deinem zweiten beispiel nicht der fall. es gibt also zwei alternativen:
    - definition der variablen vor der funktionsdefinition (die dann nicht mehr direkt in der klassendefinition erfolgen kann)
    - initialisierung der statischen konstante direkt in der klassendefinition, das ist für integrale typen ausdrücklich vorgesehen (in diesem falle kannst du i.d.R. auch auf die definition verzichten, denn eine solche konstante wird nur selten in einem kontext gebraucht, der ein lvalue benötigt)



  • es genügt für ein case-label nicht, konstant zu sein, es muss auch ein konstanter ausdruck sein. das bedeutet, dass const variablen in diesem ausdruck auch initialisiert werden müssen - ein konstanter ausdruck kann nur entstehen, wenn der exakte wert bereits an dieser stelle berechenbar ist. das ist in deinem zweiten beispiel nicht der fall.

    Ahh, jetzt verstehe ich warum, mensch da wär ich nie drauf gekommen aber eigentlich logisch.

    Danke!
    ( habe mich für die erste Version entschieden )

    mfg rendner



  • Hallo nochmal...
    also wg. der Lösung hat dich camper ja perfekt aufgeklärt...dann noch:

    rendner schrieb:

    CodeFinder schrieb:

    du solltest 'path' auf Gültigkeit prüfen!
    wg. Speicherverletzungen!

    Und wie müsste das eventuell aussehen?
    ( reicht sicherlich wenn du es nur mal grob erklärst )

    naja wenn einer bei der Methode:

    void printPath( const string *path ) const
            {
                uint i = 0;
                uint l = path->size();
    
                while( i < l )
                {
                    switch( path->c_str()[i] )
                    {
                        case PRINT_PATH_1:
                            cout << "Path_1" << endl;
                            break;
    
                        default: cout << "gibts nich! " << endl;
    
                    }
                    ++i;
                }
            }
    

    als Parameter NULL übergibt, wird das compiliert (fehlerfrei), jedoch schickste damit dein Programm ins Nirvana... ⚠ denn das "path->size();" kann ja dann nich funktionieren 💡

    Also besser so:

    void printPath( const string *path ) const
            {
                if(path == NULL)
                    return;
                /* 
                  // oder:
                  assert(path != NULL);
                  // ...mag ich persönlich aber nicht^^
                */
    
                uint i = 0;
                uint l = path->size();
    
                while( i < l )
                {
                    switch( path->c_str()[i] )
                    {
                        case PRINT_PATH_1:
                            cout << "Path_1" << endl;
                            break;
    
                        default: cout << "gibts nich! " << endl;
    
                    }
                    ++i;
                }
            }
    

  • Mod

    andereseits ist kein guter grund erkennbar, warum printPath einen zeiger statt einer referenz erhalten sollte. gerade bei einem wald-und-wiesen-argument wie einem string, kann eine referenz doch eigentlich nur von vorteil sein.



  • camper schrieb:

    wald-und-wiesen-argument

    lol jo :p

    jo ne Referenz ist sinnvoll 👍


Anmelden zum Antworten