Objekt zum ändern der Sprache.



  • Ich habe eine Klasse geschrieben, die die Sprache der Strings in meinem Programm auch zur Laufzeit ändern kann. Allerdings ist sie noch starkverbesserungsdürftig.

    #include<iostream>
    
    struct GesamtText
    {
    	std::string Text1; // Punkt A
    	std::string Text2;
    	std::string Text3;
    	GesamtText(const std::string was1,const std::string was2, const std::string was3) :
    	Text1(was1), // Punkt B
    	Text2(was2),
    	Text3(was3)
    	{
    	}
    };
    class vStrings
    {
    	private:
    		const GesamtText Deutsch;
    		const GesamtText English;
    	public:
    		vStrings() : 
    		Deutsch("Hallo!","Ich habe Hunger.","Tschüss!"),
    		English("Hello!","I am hungry.","Bye!")
    		{
    		}
    		const GesamtText * Text;
    		void SetLanguage(char was)
    		{
    			switch(was) // Punkt C
    			{
    				case 0:
    					Text = &Deutsch;
    				break;
    				case 1:
    					Text = &English;
    				break;
    			}
    		}
    };
    
    int main(int argc, char *argv[])
    {
    	vStrings vStrings; // Punkt D
    	vStrings.SetLanguage(0);
    	std::cout << vStrings.Text->Text1 << std::endl << vStrings.Text->Text2 << std::endl << vStrings.Text->Text3 << std::endl;
    	system("PAUSE");
    	vStrings.SetLanguage(1);
    	std::cout << vStrings.Text->Text1 << std::endl << vStrings.Text->Text2 << std::endl << vStrings.Text->Text3 << std::endl;
    	return EXIT_SUCCESS;
    }
    

    Folgende Sachen möchte ich noch ändern:

    1. Bei Punkt A und Punkt B hab ich eine Verdoppelung, was sich vorallem bei vielen strings bemerkbar macht.

    2. Bei Punkt C hab ich ein switch, gefällt mir aber nicht so, weil sich das vorallem bei vielen Sprachen bemerkbar macht. (ist nicht ganz so schlimm)

    3. Punkt D ist auch nicht so wichtig: Weiß jemand einen besseren Namen der genauer auf die Klasse zutrifft?

    4. Eine Frage: Sind die Text Strings jetzt eigentlich konstant? Weil so ganz hab ich das noch nicht verstanden: Verbrauchen die auch RAM? Weil sagen wir 20 strings und 5 Sprachen, das macht dann ne Menge aus.

    Ich hoffe ihr könnt mir weiterhelfen, danke im Voraus.

    mfg.



  • Das ist ganz schlecht.
    Mach dir für jede Sprache einen Header, da steht dann zB. drin:

    namespace msg {
      const char* HELLO = "hi!";
      const char* CIAO = "by!";
    }
    

    Und je nach Sprache, bindest du den entspr. Header ein.

    Wenns die Sprache erst zur Laufzeit entschieden werden soll, musst du den Header selber parsen, da würde sich dann natürlich eine simplere Syntax als C++ anbieten.



  • joomoo == Frickler



  • DrGreenthumb schrieb:

    Wenns die Sprache erst zur Laufzeit entschieden werden soll, musst du den Header selber parsen, da würde sich dann natürlich eine simplere Syntax als C++ anbieten.

    Genau das will ich. Aber weiß heißt das: "parsen"? Und soll ich dann nicht mehr C++ schreiben?

    mfg.



  • definitiv schrieb:

    joomoo == Frickler

    Wasn ein Frickler?

    mfg.



  • genau. was ist ein frickler...
    wenn ihr jetzt sagt ich bin einer ist ein frcikler also ein trikotsammler - gehört zu den ultras bremen - ist schöau - und sieht gut aus. hat ne freundinn und wichst sich 6 mal täglich einen. und wisst ihr auch warum? weil ich es kann:P

    ne würde das aber auch mal gerne wissen



  • du könntest es auch so machen:

    enum Message { HELLO, BY, ..., NMESSAGES };
    
    struct Language {
      const char* _str[NMESSAGES];
      const char* str(Message id) { return _str[id]; }
    };
    
    // hierfür ein Makro
    struct German : public Language {
      German() {
        _str[HELLO] = "hi";
        ...
      }
    };
    

    und je nach Sprache legst du das entsprechende Objekt an:

    Language* lang = new German();
    cout << lang->str(HELLO);
    


  • DrGreenthumb schrieb:

    Wenns die Sprache erst zur Laufzeit entschieden werden soll, musst du den Header selber parsen

    😮
    Ich glaube, ich würde eher sowas wie 'ne Stringtable benutzen.



  • groovemaster schrieb:

    DrGreenthumb schrieb:

    Wenn die Sprache erst zur Laufzeit entschieden werden soll, musst du den Header selber parsen

    😮

    Das er keinene C++-"Header" parsen soll, habe ich dazu geschrieben.
    So eine Textdatei wäre aber natürlich nur nötig, wenn man ohne neu-kompilieren Sprachen ändern will.



  • Ich hab jetzt gearbeitet und die ganze Klasse sieht jetzt so aus:

    #include<iostream>
    #include<fstream>
    #include<string>
    #include<deque>
    
    class LanguageStrings
    {
        private:
            std::deque<std::string> Text;
            std::string Undefined;
        public:
            LanguageStrings(const std::deque<std::string>& c) :
            Text(c),
            Undefined("undef")
            {
            }
            std::string &GetText(unsigned int Nr)
            {
                if(Nr >= Text.size())
                {
                    return Undefined;
                }
                return Text[Nr];
            }
    };
    
    class Language
    {
        private:
            std::deque<LanguageStrings *> pLStrings;
            unsigned int ActiveLanguage;
            void LoadLanguageFiles()
            {
                const int EndeEinlesen = 100;
                for(int DateiNr = 0;DateiNr < EndeEinlesen;DateiNr++)
                {
                    char DateiName[] = "xxx.txt";
                    sprintf(DateiName,"%i.txt",DateiNr);
                    std::ifstream fin(DateiName);
                    if(!fin)
                    {
                        DateiNr = EndeEinlesen;
                    }
                    else
                    {
                        std::deque<std::string> Datei; /* Die einzelnen in der Datei durch \n-\n getrennten Strings in einem Deque von einander getrennt */
                        std::string DateiInhalt; /* Temp String */           
                        char ch_last = 0; /* Der letzte eingelesene Charakter */
                        char ch; /* Aktuell eingelesener Charakter */
                        DateiInhalt.append("\n"); /* Ein Charakter am Anfang und einer am Ende werden immer abgeschnitten, auf grund der Trennung durch "\n-\n" */
                        while(fin.get(ch)) /* Jeden Charakter einzeln einlesen */
                        {
                            if((ch_last = '\n' && ch == '-' && fin.peek() == '\n') || fin.peek() == EOF) /* Wurden die drei Trennzeichen gefunden? Oder Ende der Datei?*/
                            {
                                if(fin.peek() == EOF) /* Verhindert, dass das letzte Zeichen abgeschnitten wird. */
                                {
                                    DateiInhalt.append(&ch);
                                }
                                if(DateiInhalt.size() >= 3) /* Vermeidet Laufzeitfehler */
                                {
                                    Datei.push_back(DateiInhalt.substr(1,DateiInhalt.size()-2)); /* String ohne den ersten und letzten Charakter übergeben an das deque */
                                }
                                DateiInhalt.clear(); /* String leeren */                    
                            }
                            else
                            {
                                DateiInhalt.append(&ch); /* Zeichen hinten drann hängen */
                            }
                        }
                        pLStrings.push_back(new LanguageStrings(Datei));
                    }    
                }
            }
        public:
            Language() : ActiveLanguage(0)
            {
                LoadLanguageFiles();
            }
            void ChangeLanguage()
            {
                ActiveLanguage++;
                if(ActiveLanguage >= pLStrings.size())
                {
                    ActiveLanguage = 0;
                }
            }
            std::string & Text(unsigned int Nr)
            {
                return pLStrings[ActiveLanguage]->GetText(Nr);
            }
    };
    
    int main(int argc, char *argv[])
    {
        Language Language;
        std::cout << Language.Text(0) << std::endl;
        Language.ChangeLanguage();
        std::cout << Language.Text(2) << std::endl;
        Language.ChangeLanguage();
        std::cout << Language.Text(2) << std::endl;
        Language.ChangeLanguage();
        std::cout << Language.Text(1) << std::endl;
        Language.ChangeLanguage();
        std::cout << Language.Text(0) << std::endl;
        std::cin.get();
        return EXIT_SUCCESS;
    }
    

    Die 3 txt Dateien sehen so aus:

    0.txt

    Deutsch
    -
    Hallo!
    

    1.txt

    English
    -
    Hello!
    

    2.txt

    Francais
    -
    Bonjour!
    -
    J'ai faim.
    

    Die Ausgabe, wenn man das Programm ausführ folgender maßen:

    Deutsch
    undef
    J'ai faim.
    Hallo!
    English
    

    Scheint ja alles ganz gut zu klappen. Allerdings habe ich jetzt noch das Problem, dass das ganze wahrscheinlich zu viel RAM verbraucht. (Vor allem wen man lange Texte in unterschiedlichen Sprachen hat) Was kann man dagegen tun?

    mfg.


Anmelden zum Antworten