Buchstabenumwandlung



  • Hallo!

    Wir haben die Aufgabe bekommen, ein C-Programm zu schreiben, indem wir mithilfe der ASCII-Codes großbuchstaben in kleinbuchstaben und umgekehrt verwandeln können. Dies soll allerdings auch bei wörtern, sowie bei gemischten wörtern funktionieren.

    Wir haben jetzt begonnen, schaffen es aber irgendwie nicht, dass die buchstaben umgewandelt werden. Wo liegt hier unser fehler? Ich denke, ich poste einfach mal das programm, ist so glaub ich einfacher zu verstehen:

    #include <stdio.h>
    #define MAXLENGTH 2000
    
    int main (void)
    
    {
    	char wort[MAXLENGTH];
    	int i, laenge;
    
    	printf("Bitte wort eingeben: ");
    	scanf( "%s" , &wort);
    
    	laenge= 0;
    
    	while (wort[laenge] != '\0')		
    		laenge++;
    
    	for (i=0; i < laenge; i++);
    
    		if (i<=97 )
    
    			i = i + 32;
    
    		else
    			i = i - 32;
    
    	printf( "%s\n" , wort);
    
    	return 0;
    }
    


  • Du fragst die Variable i nach ihrem Wert ab. (i <= 97).

    Du willst aber den Buchstaben an der Stelle i abfragen:

    if(wort[i] <= 97) {
    
        //...
    }
    

    /edit:
    Außerdem ist deine for()-Schleife falsch. Du darfst sie nicht mit einem Semikolon beenden, sondern sie muss den Bereich einklammern, der durchlaufen werden soll. Guckst du:

    for(i=0; i<laenge; i++)
    {
        // mache irgendwas
    }
    

    /edit2:

    Uiuiui. Da sind ja noch mehr Fehler. Du darfst dann natürlich auch nicht i = i + 32 schreiben. So veränderst du nur die Zählervariable. Aber wir wollen ja die Buchstaben im Array wort[] ändern.

    for (i=0; i < laenge; i++){
    
            if (wort[i]<=97 )
    
                wort[i] += 32;
    
            else
                wort[i] -= 32;
    }
    

    So ist es syntaktisch richtig. Leider funktioniert es nicht so einfach, wie du dir dass gedacht hast. Musst sicherlich mehr Abfragen einbauen.

    Probier es einfach mal aus, dann siehst du schon, dass es nicht so funktioniert, wie es soll.



  • Außerdem solltest du dir mal die Funktionen man: strlen (zur Längenbestimmung des Strings) und man: toupper ansehen.

    Btw, deine Bereichsabfrage passt nicht wirklich auf den Bereich "Großbuchstaben":

    if(wort[i]>='a'&&wort[i]<='z') wort[i]=wort[i]-'a'+'A';
    


  • CStoll schrieb:

    und man: toupper ansehen.

    Ja, aber sie sollen es ja lernen, wie das mit dem ASCII System funktioniert. Da ist das schon ein guter Lerneffekt, dass mal zu Fuß zu coden. Wenn man dann weiß, wie es läuft kann man später auf die Funktion zurückgreifen.



  • DarthZiu schrieb:

    Ja, aber sie sollen es ja lernen, wie das mit dem ASCII System funktioniert. Da ist das schon ein guter Lerneffekt, dass mal zu Fuß zu coden.

    und dann merkt man auch schnell, dass sich gross/kleinbuchstaben nur am bit 5 unterscheiden

    ...
    i = 0;
    while (wort[i])
    {
       if (wort[i] ist ein buchstabe)
       {
          if (bit 5 ist 0)
             wort[i] |= 0x20;
          else
             wort[i] &= ~0x20; 
       }
       i++;
    }
    ...
    


  • OK, das ist ein Argument, dem ich folgen kann. Trotzdem - wenn man schon Buchstaben umwandeln will, sollte man seine Abfragen auch so anpassen, daß der richtige Bereich getroffen wird (und "wort[i]<=97" erwischt alle Zeichen bis einschließlich 'a' (dazu gehören Großbuchstaben, Ziffern und etliche Sonderzeichen).



  • Sehr schön, wieder was dazu gelernt. 👍



  • Dann kann man Bit 5 ja gleich toggeln und braucht es nicht nochmal abzufragen:

    // für jedes Zeichen
    for (i=0; i < laenge; i++){
    
        // wenn es ein Buchstabe ist
        if (wort[i] >= 'a' && wort[i] <= 'z' || wort[i] >= 'A' && wort[i] <= 'Z')
    	// Bit 5 toggeln
    	wort[i] ^= 0x20;
    }
    


  • Wau, danke für die prompte Hilfe! allerdings kann ich mit dem letzten beitrag relativ wenig anfangen. was sind denn toggeln?

    ok, ich habe das Programm jetzt soweit editiert. Es wandelt alles schön um. Jetzt komme ich dadurch allerdings direkt zum nächsten problem: es wandelt wie gesagt alles um. allerdings sollen sonderzeichen und zahlen stehen bleiben. meine überlegung war jetzt einfach am anfang alles bis auf die Zalenbereiche 65-90 und 97-122 auszuklammern. aber, wie mache ich das am elegantesten?

    *edit*

    mit toupper und tolower hatten wir shcon ein funktionsfähiges programm in einem Lehrbuch gefunden, allerdings durften wir diese funktionen nicht benutzen 😞 😉

    so sieht das programm jetzt aus:

    #include <stdio.h>
    #define MAXLENGTH 2000
    
    int main (void)
    
    {
    	char wort[MAXLENGTH];
    	int laenge;
    	char i;
    
    	printf("Bitte wort eingeben: ");
    	scanf( "%s" , &wort);
    
    	laenge= 0;
    
    	while (wort[laenge] != '\0')		
    		laenge++;
    
    	for (i=0; i < laenge; i++)
    		{
    
    		if (wort[i]<=96 ) // hier würde dann die 'ausklammerung' stattfinden
    
    			wort[i] += 32;
    
    		else
    			wort[i] -= 32;
    		}
    
    	printf( "%s\n\n" , wort);
    	printf( "Die laenge der Zeichenkette ist %i\n", laenge);
    	printf( " i3 liegt bei %i\n", i );
    	printf( " oder %c\n" , i);
    
    	return 0;
    }
    


  • Meine eben geposteter Code erledigt alles, was du machen willst.
    Er wandelt wirklich nur die Buchstaben ineinander um. Keine Sonderzeichen, Zahlen, etc.

    Toggeln:

    Wie net schon geschrieben hat unterscheiden sich Groß- und Kleinbuchstaben nur am 5. Bit:

    a:  0110.0001
    A:  0100.0001
    

    Das bedeutet, wenn du Groß- in Kleinbuchsatben und umgedreht umwandeln willst, brauchst du nur das Bit Nummer 5 "umzuschalten". Also, wenn ne 0 dasteht machste ne 1 draus und andersherum. Das nennt sich toggeln.

    Das wird in ner Programmiersprache mit einer XOR-Verknüpfung erledigt:

    0110.0001   (a)
    XOR   0010.0000   (0x20)
    ------------------------
          0100.0001   (A)
    
    und nun zurück:
    
         0100.0001    (A)
    XOR  0010.0000    (0x20)
    ------------------------
         0110.0001    (a)
    

    Wie du siehst, kannst du mit einer Operation (XOR 0x20) zwischen Groß- und Kleinbuchstaben "umschalten". XOR wird in C mit dem Zeichen '^' dargestellt.



  • "toggeln" bedeutet einfach, daß ein Bit zwischen 0 (aus) und 1 (an) umgeschaltet wird (das macht DathZiu mit der XOR-Konstruktion "wort[i]^=0x20;").

    Ansonsten kannst du mehrere Bedingungen per && (UND) bzw. || (ODER) miteinander verknüpfen, um die "erlaubten" ASCII-Bereiche auszufiltern.



  • @ DarthZiu & CStoll:

    Vielen Danke für die Super erklärung! Allerdings habe ich es selbernochmal versuchen müssen, da wir das Programm vorstellen müssen. da wir toggeln noch nicht behandelt haben könnte das dann auffallen 😉

    So, soweit habe ich das proggi jetzt fertig. macht alles so wie es soll. jetzt habe ich nur noch eine Frage: wie stell ich das an, dass der auch leerzeichen mitnimmt; sprich, dass er einen ganzen Satz umwandelt?

    ich habe mal irgendwas mit getchar und putchar gelesen, aber keine eindeutige erklärung finden können.

    #include <stdio.h>
    #define MAXLENGTH 2000
    
    int main (void)
    
    {
        char wort[MAXLENGTH];
        int laenge;
        char i;
    
        printf("Bitte wort eingeben: ");
        scanf( "%s" , &wort);
    
        laenge= 0;
    
        while (wort[laenge] != '\0')
            laenge++;
    
        for (i=0; i < laenge; i++)
            {
    			if( wort[i]>=65 &&wort[i]<=90 || wort[i]>=97 && wort[i]<=122 )
    
           			if (wort[i]<=90 )
    
                		wort[i] += 32;
    
            		else
                		wort[i] -= 32;
            }
    
        printf( "\nUmwandlung: %s\n\n" , wort);
    
        return 0;
    }
    


  • So, soweit habe ich das proggi jetzt fertig. macht alles so wie es soll. jetzt habe ich nur noch eine Frage: wie stell ich das an, dass der auch leerzeichen mitnimmt; sprich, dass er einen ganzen Satz umwandelt?

    Dazu kannst du fgets() für die Eingabe verwenden (oder auch "scanf("%[^\n]",wort);")

    PS: Wieso machst du eigentlich zwei Schleifen? Das kannst du doch zusammenfassen:

    while(wort[i]!='\0'
    {
      if(...)
      i++;
    }
    

    oder

    for(i=0;wort[i]!='\0';++i)
      ...
    


  • hm, mit der ersten zähle ich, wieviele buchstaben das wort hat und bei der zweiten sage ich: breche ab, wenn du alle buchstaben durchgearbeitet hast. ka, ob man das noch großartig anders schreiben kann, habe erst vor knapp 3 monaten mit c angefangen, deshalb sieht alles noch ein bischen wüst aus 🙂



  • Da ist es doch einfacher zu sagen "arbeite so lange, bis du das Wortende erreicht hast" (siehe die Code-Schnipsel in meinem vorigen Beitrag)



  • campinge schrieb:

    Allerdings habe ich es selbernochmal versuchen müssen, da wir das Programm vorstellen müssen. da wir toggeln noch nicht behandelt haben könnte das dann auffallen 😉

    Das seh ich aber völlig anders: Du kannst doch sagen, dass du im www gefunden hast, dass sich Groß- und Kleinbuchstaben nur an Bitstelle 5 unterscheiden.

    Und dann hast du dich hier http://de.wikipedia.org/wiki/Bitmaske#Bit_umschalten_.28toggle.29 belesen, wie dass mit dem Umschalten funktioniert. Wär ja schlimm, wenn du in der Schule dafür "bestraft" wirst, eigenständig zu denken.



  • hm, ist auch ne gute idee.

    ich habe mal beide Programme fertiggemacht und lasse dann die anderen aus meine mteam entscheiden, ob sie was lernen möchten oder nicht 😉
    Auf jeden fall vielen Dank nochmal für eure fixe Hilfe! ich werd bestimmt noch öfters mal vorbeischaun, lol 🙂


Anmelden zum Antworten