Umlautkonverter mit CStrings funktioniert nicht



  • Moin,

    ich soll ein Programm erstellen, das mit CStrings arbeitet. Der Benutzer soll einen Satz eingeben und darauf sollen alle Umlaute und das "ß" in "ae,oe,ue,ss" konvertiert werden.

    Momentan funktioniert das Programm nicht. Wo liegt der Fehler?

    #include <iostream>
    #include <conio.h>
    
    using namespace std;
    
    int main()
    {
        char s1[200], s2[400];
        int x=0;
    
        cout<<"Satz eingeben: ";
        cin.getline(s1, 200);
    
        for (int i=0; i<strlen(s1); i++)
        {
            if (s1[i]=='ä') //ä
            {
                s2[x]='a';
                s2[x+1]='e';
            } else
            if (s1[i]=='ö') //ö
            {
                s2[x]='o';
                s2[x+1]='e';
            } else
            if (s1[i]=='ü') //ü
            {
                s2[x]='u';
                s2[x+1]='e';
            } else
            if (s1[i]=='Ä') //Ä
            {
                s2[x]='A';
                s2[x+1]='E';
            } else
            if (s1[i]=='Ö') //Ö
            {
                s2[x]='O';
                s2[x+1]='E';
            } else
            if (s1[i]=='Ü') //Ü
            {
                s2[x]='U';
                s2[x+1]='E';
            } else
            if (s1[i]=='ß')
            {
                s2[x]='s';
                s2[x+1]='s';
            } else
            {
                s2[i]=s1[x];
            }
            if (s2[i]!=s1[x])
                x++;
    
            x++;
        }
    
        cout<<'\n';
    
        for (int i=0; i<strlen(s2); i++)
            cout<<s2[i];
    
        getch();
    }
    


  • Phisherman schrieb:

    Momentan funktioniert das Programm nicht. Wo liegt der Fehler?

    Das ist nicht gerade das, was man eine Fehlerbeschreibung nennt... Also die Gegenfrage: was genau funktioniert denn nicht?

    EDIT: Übrigens solltest du sowas besser in eine switch-Anweisung packen (char ist ein integraler Typ und darf mit switch verwendet werden). Bei dieser endlosen Verschachtelung blickt ja keiner mehr durch... 😉



    1. versuchs mal mit
    System::String^ s;
    s=System::Console::ReadLine();
    

    aber nur mit Common-Runtime-Langue Unterstützung !

    cin() ließt z.B. statt "ß" "à" ein. (?)

    s2[i]='u';
    s2[i+1]='e';
    

    Was soll den DAS ?? Damit überschreibst du das nächste Zeichen !
    "Straße" --> "Strass" Und mit Umlaut am Ende gibt's nen Buffer Overflow 🙄



  • Guck dir mal die Funktion "OemToChar" an. Die sollte dein Problem lösen.

    EDIT: Übrigens brauchst du einen Zähler für den Zielstring. Der ist schließlich tendenziell länger, da kannste nicht einfach an Position i schreiben, so wie du an Position i von s1 liest...



  • a) Es gibt keine Umlaute im normalen character-Zeichensatz. Damit ist auch nicht definiert, was 'ä', 'ö', 'ü' und 'ß' eigentlich darstellt. Benutze wchar_t um Zeichen zu verarbeiten die über den ASCII-Zeichensatz hinausgehen.
    b) Es gibt keine Umlaute im C++ Befehlszeichensatz. Damit bist du von der Grutmütigkeit des Compilers abhängig, ob er diese Zeichen im Quelltext überhaupt akzeptiert oder gleich aussteigt. Was er dann damit macht ist im Standard nicht definiert und Glückssache. Um solche Zeichen in den wstrings etc. zu haben sollte man auf die Unicode-Umschreibungen zurückgreifen.



  • Dein if-else-Chaos könnte man ersetzen und gleich noch das Navigieren in den Strings vereinfachen (bzw. überhaupt mal richtig machen). Hier mal beispielhaft nur für ä=>ae:

    void UmlauteUmwandeln(char *in,char *out) {
    	while(*in) {
    		switch(*in) {
    			case 'ä':
    				*out='a';
    				*++out='e';
    				break;
    			default:
    				*out=*in;
    		}
    		++in;
    		++out;
    	}
    }
    
    int main()
    {
    	char rgne[]="haha ä ää ä haha";
    	char rgne2[1024]={0};
    	UmlauteUmwandeln(rgne,rgne2);
    }
    

    (ggf. halt noch vorher mit OemToChar umwandeln, wenn du von der Konsole einliest...)



  • @darkshadow: Ich habe doch unten in der Schleife i um 1 erhöht. 😕
    ---

    Geht es auch anders? Alle genannten Methoden habe ich noch nicht kennengelernt und soll bzw. darf sie nicht benutzen.



  • Phisherman schrieb:

    @darkshadow: Ich habe doch unten in der Schleife i um 1 erhöht. 😕

    darkshadow hat deinen Code nicht ganz verstanden. Du überschreibst keine Zeichen, wie er behauptet, sondern schreibst korrekterweise für jedes 'ß' im Quellstring zwei 's' in den Zielstring. Das ist schon richtig. Dein Problem ist nur, dass du am Anfang eines Schleifendurchlaufs für beide Strings mit dem gleichen Index (i) ansetzt. Sobald ein Umlaut vorgekommen ist, ist der Zielstring länger als der Quellstring. Es leuchtet dir sicher ein, dass du für das nächste Zeichen s1[i] nicht einfach an der Stelle s2[i] schreiben darfst (denn da steht ja z.B. das 'e' vom zuletzt geschriebenen "ae"). Du musst also einen eigenen Zähler für den Zielstring mitlaufen lassen, der mit jedem geschriebenen Zeichen (pro Durchlauf also 1-2 Zeichen) um eins erhöht wird.

    Dein zweites Problem ist der Zeichensatz, wie schon gesagt wurde. OemToChar wäre eine Möglichkeit...

    Ich würde dir Folgendes empfehlen: arbeite erstmal nicht mit einem vom Benutzer eingelesenen String, sondern mit einem fest kodierten (so wie in meinem Beispiel). Dann sorgst du erst dafür, dass deine Schleife vom Ablauf her funktioniert, und im Anschluss kannst du dir dann über das Zeichensatz-Problem Gedanken machen.

    Phisherman schrieb:

    Geht es auch anders? Alle genannten Methoden habe ich noch nicht kennengelernt und soll bzw. darf sie nicht benutzen.

    Was genau meinst du denn bei meinem Beispiel? Die switch-Anweisung?? Das ist nur eine bequemere Schreibweise für mehrfach verschachtelte if-else-Anweisungen. Du kannst es natürlich ruhig so halten wie bisher, kein Problem. Wichtiger ist ja, was bei eingetretener Bedingung passiert, nicht wie diese genau abgefragt wird (bwz. wie die Abfrage syntaktisch formuliert wird).
    Falls du OemToChar meinst: du findest hier im Forum Alternativen die zeigen, wie man das händisch macht. Einfach mal die Suchfunktion nutzen.



  • Danke, die Zählvariable habe ich nun in den ersten Post eingebaut.



  • Phisherman schrieb:

    Danke, die Zählvariable habe ich nun in den ersten Post eingebaut.

    Aha, und funktioniert's denn jetzt auch?



  • Das Umstellen funktioniert besser, aber Umlaute, wie hier angesprochen wurde, werden in der Bedingung nicht erkannt.



  • Ich kann nur nochmal auf meinen Post von oben verweisen. Umlaute sind im C++ Zeichensatz nicht enthalten, das was du da geschrieben hast ist nicht spezifiziert.



  • Setz doch einfach mal einen Breakpoint hinter die Benutzereingabe und sieh dir im Debugger an, was wirklich im String steht, wenn du Umlaute eingibst. Dann verstehst du vielleicht eher, was wir mit der Zeichensatz-Geschichte meinen und warum dein Code nicht funktionieren kann.



  • Jetzt funktioniert es einwandfrei! 😃
    Ich habe nun diese If-Else Kaskade entfernt und eine Switch-Case Anweisung dafür integriert. Das mit den Umlauten habe ich ganz einfach gelöst, wie ihr sehen könnt. Ich glaube, dass das Programm aber nur auf Windows System funktioniert, da die Werte der Sonderzeichen von der Codepage 850 sind.

    #include <iostream>
    #include <conio.h>
    
    using namespace std;
    
    int main()
    {
        char s1[200], s2[400];
        int x=0;
    
        cout<<"Satz eingeben: ";
        cin.getline(s1, 200);
    
        for (int i=0; i<strlen(s1); i++)
        {
            switch (int(s1[i]))
            {
                   case 132:           //ae
                   {
                        s2[x]='a';
                        s2[++x]='e';
                        break;
                   }
                   case 148:           //oe
                   {
                        s2[x]='o';
                        s2[++x]='e';
                        break;
                   }
                   case 129:           //ue
                   {
                        s2[x]='u';
                        s2[++x]='e';
                        break;
                   }
                   case 142:           //AE
                   {
                        s2[x]='A';
                        s2[++x]='E';
                        break;
                   }
                   case 153:           //OE
                   {
                        s2[x]='O';
                        s2[++x]='E';
                        break;
                   }
                   case 154:           //UE
                   {
                        s2[x]='U';
                        s2[++x]='E';
                        break;
                   }
                   case 225:           //ss
                   {
                        s2[x]='s';
                        s2[++x]='s';
                        break;
                   }
                   default:
                        s2[x]=s1[i];
            }
            x++;
        }
    
        s2[x]='\0';
    
        cout<<'\n';
    
        for (int i=0; i<strlen(s2); i++)
            cout<<s2[i];
    
        getch();
    }
    

Anmelden zum Antworten