Anzeige

Caesar-Verschlüsselung


#1
Hallo,

hab folgenden Programmcode:

C:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main (void)
{

char c;
while( (c = getchar()) != '\n')
{   
    putchar(c);
}
putchar ('\n');

return EXIT_SUCCESS;

}
Im Moment lest er eingegebene Zeichen ein und gibt diese wieder aus.
Ich soll ihn so umschreiben, dass er eingelesene Wörter/Sätze verschlüsselt und dann wieder ausgibt. Die Schlüsselvariable soll fix definiert sein und muss nicht vom Benutzen eingegeben werden.

Bsp.: Schlüssel: 2 ; eingegebenes Wort: Guten Tag --> ausgegebenes Wort: Iwvgp Vci

Die eingegeben Wörter sollten immer in Kleinbuchstaben ausgegeben werden und Leerzeichen dürfen nicht verschlüsselt werden.

Mein Code:

C:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main (void)
{

int key = 3;
int letter = 0;
int letter2 = 0;

char c;
while( (c = getchar()) != '\n')
{
    letter = (int)c;
    if((letter + key) > 122)
    {
        letter2 = (letter = 96+key);
    }

/*if (letter == 32)
    {
        letter2 = letter;
    }*/
    
    else   
    {
        letter2 = letter + key;
    }

    c = (char)letter2;
    putchar(c);
}

putchar ('\n');

return EXIT_SUCCESS;

}
Bis jetzt verschlüsselt das Programm eingegebene Kleinbuchstaben, aber hab noch das Problem, dass Leerzeichen mit verschlüsselt werden und Großbuchstaben noch nicht richtig verschlüsselt werden.

Jemand einen Tipp, wie ich das Problem lösen könnte?
 

cwriter

Erfahrenes Mitglied
#2
Jemand einen Tipp, wie ich das Problem lösen könnte?
Hm, wenn du weisst, wie Buchstaben in Computern funktionieren, dürfte das eigentlich nicht zu schwer sein.
Da die Grossbuchstaben ja auch automatisch klein werden sollen, kannst du sie direkt als Kleinbuchstaben behandeln (tolower()). Und auf ein Leerzeichen kannst du mittels "c == ' '" prüfen.

Deine Frage tönt ein bisschen wie "macht mir den Rest". Sicherlich meinst du das nicht so, aber vielleicht kannst du deine Fragen in Zukunft etwas spezifischer formulieren. Etwas "wie kann ich aus Grossbuchstaben Kleinbuchstaben machen" oder "Wie erkenne ich ein Leerzeichen". Ansonsten kannst du auch einen Code schreiben und hier posten, wenn du einen Fehler nicht findest (gerne mit Eingabe und Ausgabe, und wo das Resultat von den Erwartungen abweicht).

Gruss
cwriter
 
#3
Hm, wenn du weisst, wie Buchstaben in Computern funktionieren, dürfte das eigentlich nicht zu schwer sein.
Da die Grossbuchstaben ja auch automatisch klein werden sollen, kannst du sie direkt als Kleinbuchstaben behandeln (tolower()). Und auf ein Leerzeichen kannst du mittels "c == ' '" prüfen.

Deine Frage tönt ein bisschen wie "macht mir den Rest". Sicherlich meinst du das nicht so, aber vielleicht kannst du deine Fragen in Zukunft etwas spezifischer formulieren. Etwas "wie kann ich aus Grossbuchstaben Kleinbuchstaben machen" oder "Wie erkenne ich ein Leerzeichen". Ansonsten kannst du auch einen Code schreiben und hier posten, wenn du einen Fehler nicht findest (gerne mit Eingabe und Ausgabe, und wo das Resultat von den Erwartungen abweicht).

Gruss
cwriter
Das mit der Leertaste hätte ich mir so irgendwie gedacht:

C:
if (letter == 32)
    {
        letter2 = (letter = 32);  // 32 steht in der ASCII-Tabelle für das Leerezeichen
    }
So bleibt das Leerzeichen zwar ein Leerzeichen, aber wenn der key z.B. 3 ist und "z" verschlüsselt werden sollten, stimmt es nicht mehr. Die Verschlüsselung von bspw. "a" klappt noch.

Und wie meintest du das mit den direkten einlesen als Kleinbuchstaben? Den Befehl (tolower()) kenn ich nämlich nicht.
 

cwriter

Erfahrenes Mitglied
#4
Das mit der Leertaste hätte ich mir so irgendwie gedacht:
Wenn du nur dein kommentiertes if wieder ent-kommentierst, sollte es lesbarer sein. Aber ja, so müsste es gehen.

Und wie meintest du das mit den direkten einlesen als Kleinbuchstaben? Den Befehl (tolower()) kenn ich nämlich nicht.
Du liest jeden Buchstaben ganz normal ein und machst dann ein tolower() darauf. Ein bisschen googlen hilft, aber weil ich so nett bin: http://www.cplusplus.com/reference/cctype/tolower/

Gruss
cwriter
 
#5
Wenn du nur dein kommentiertes if wieder ent-kommentierst, sollte es lesbarer sein. Aber ja, so müsste es gehen.


Du liest jeden Buchstaben ganz normal ein und machst dann ein tolower() darauf. Ein bisschen googlen hilft, aber weil ich so nett bin: http://www.cplusplus.com/reference/cctype/tolower/

Gruss
cwriter
So:

C:
while( (c = getchar()) != '\n')
{
    letter = (int)c;
    if((letter + key) > 122)
    {
        letter2 = (letter = 96+key);
    }
    if (letter == 32)
    {
        letter2 = (letter = 32);
    }
    else   
    {
        letter2 = letter + key;
    }

    c = (char)letter2;
    putchar (tolower(c));
}
Das mit dem (tolower()) war einfacher als gedacht :D

Hab jetzt aber immer noch das Problem, dass wenn die Verschlüsselung über "z" hinausläuft und der key z.B. 2 ist, nicht b ausgegeben wird, sondern f. Ganz egal, welche Zahl der key ist, es wird immer f ausgegeben.

Wenn ich aber diesen Codeteil
C:
if (letter == 32)
    {
        letter2 = (letter = 32);
    }
lösche, funktioniert es. Dann wird für z, bei einem key mit dem Wert 2, b ausgegeben. Hab keine Ahnung, wieso das so ist..
 

cwriter

Erfahrenes Mitglied
#6
Das mit dem (tolower()) war einfacher als gedacht :D
Aber falsch. Hast du mal Z als Eingabe probiert?

Statt 32 könntest du ' ' schreiben, statt 97 'a' etc.
C++:
letter2 = (letter = 96+key);
Bitte nicht. Es wird unleserlich und ist nicht, was du haben willst. Warum lässt du letter nicht einfach so, wie's ist?

Wenn ich aber diesen Codeteil lösche
Woran bindet denn dann das else? Zuvor addierst du den Key doppelt...
Generell ist aber sehr viel daneben...
C++:
//c = input
c = tolower(c); // Normalisiere...
if(isspace(c)) {
    out = c;
    return;
}
else if(!isalpha(c)) printf("Kein Buchstabe!"); // Fehler bei falscher Eingabe
char normalized = c - 'a'; // Generiere die Differenz von 'a'
char enc = (normalized + key) % 26;
char out = enc + 'a'; // Wieder zurück auf lesbare Zeichen
Das alles ist noch relativ verbos und kann stark gekürzt werden. Aber dein Code strotzt nur so von falschen Werten und Annahmen, und dein Vorgehen scheint generell ein bisschen Trial & Error zu sein. Versuche doch mal, diesen Code zu verstehen.
Deine Angabe von Ein- und Ausgabe ist übrigens nicht nachzuvollziehen. Du solltest mit einer Eingabe von z d und nicht f erhalten.
(c = 'z' = 122, 122 + 2 > 122 => letter = 96 + 2 = 98 = 'b', letter !=32 => letter2 = 98 + 2 = 100 = 'd').

Gruss
cwriter
 
#7
Aber falsch. Hast du mal Z als Eingabe probiert?
Ja, das ist mir jetzt auch aufgefallen.

Statt 32 könntest du ' ' schreiben, statt 97 'a' etc.
C++:
letter2 = (letter = 96+key);
Bitte nicht. Es wird unleserlich und ist nicht, was du haben willst. Warum lässt du letter nicht einfach so, wie's ist?
Habs jetzt so:
Code:
if((letter + key) > 122)
    {
        letter2 = (letter = 'a'+key);
    }
    if (letter == ' ')
    {
        letter2 = letter;
    }
    else    
    {
        letter2 = letter + key;
    }
Wenn ich jetzt aber z eingebe, bekomme ich g als Ausgabe und nicht d, wie es sein sollte.

Woran bindet denn dann das else? Zuvor addierst du den Key doppelt...
Generell ist aber sehr viel daneben...
Wie meinst du das mit den doppelten Key?
C++:
//c = input
c = tolower(c); // Normalisiere...
if(isspace(c)) {
    out = c;
    return;
}
else if(!isalpha(c)) printf("Kein Buchstabe!"); // Fehler bei falscher Eingabe
char normalized = c - 'a'; // Generiere die Differenz von 'a'
char enc = (normalized + key) % 26;
char out = enc + 'a'; // Wieder zurück auf lesbare Zeichen
Das alles ist noch relativ verbos und kann stark gekürzt werden. Aber dein Code strotzt nur so von falschen Werten und Annahmen, und dein Vorgehen scheint generell ein bisschen Trial & Error zu sein. Versuche doch mal, diesen Code zu verstehen.

Deine Angabe von Ein- und Ausgabe ist übrigens nicht nachzuvollziehen. Du solltest mit einer Eingabe von z d und nicht f erhalten.
(c = 'z' = 122, 122 + 2 > 122 => letter = 96 + 2 = 98 = 'b', letter !=32 => letter2 = 98 + 2 = 100 = 'd').
Ich weiß, dass die Ausgabe nicht richtig ist. Verstehe aber nicht, wie es auf die Ausgabe f bzw. jetzt g kommt.
 

cwriter

Erfahrenes Mitglied
#8
Wenn ich jetzt aber z eingebe, bekomme ich g als Ausgabe und nicht d, wie es sein sollte.
key=4?
Gibt mir doch mal eine Trace dafür (gehe den Code auf einem Blatt Papier durch). Dann siehst du das Problem sehr schnell.
Dein Problem ist u.a., dass wenn letter + key > 122, dann wird letter zu 'a'+key. Also ist letter dann nicht mehr abhängig von der Eingabe. Siehst du da ein Problem?

Wie meinst du das mit den doppelten Key?
Rechne den Code im Kopf / auf Papier durch. Dann siehst du es.

Gruss
cwriter
 
#9
key=4?
Gibt mir doch mal eine Trace dafür (gehe den Code auf einem Blatt Papier durch). Dann siehst du das Problem sehr schnell.
Dein Problem ist u.a., dass wenn letter + key > 122, dann wird letter zu 'a'+key. Also ist letter dann nicht mehr abhängig von der Eingabe. Siehst du da ein Problem?
Hier der ganze Code:

Key = 3, dann sollte ich bei der Eingabe von z, c als Ausgabe bekommen. (Sry, hab mich vorhin verschrieben)

Bei der Eingabe von a, bekomme ich ordnungsgemäß d heraus.

Code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main (void) 
{

int key = 3;
int letter = 0;
int letter2 = 0;

char c;
while( (c = getchar()) != '\n') 
{
    letter = (int)c;
    if((letter + key) > 122)
    {
        letter2 = (letter = 'a'+key);
    }
    if (letter == ' ')
    {
        letter2 = letter;
    }
    else    
    {
        letter2 = letter + key;
    }

    c = (char)letter2;
    putchar (tolower(c));
}

putchar ('\n');

return EXIT_SUCCESS;

}
Rechne den Code im Kopf / auf Papier durch. Dann siehst du es.

Gruss
cwriter[/QUOTE][/code]
 

cwriter

Erfahrenes Mitglied
#10
Hier der ganze Code:
Key = 3, dann sollte ich bei der Eingabe von z, c als Ausgabe bekommen. (Sry, hab mich vorhin verschrieben)
Bei der Eingabe von a, bekomme ich ordnungsgemäß d heraus.
Drücke ich mich eigentlich so undeutlich aus?
1. Sind das keine Traces. Du solltest Computer spielen und den Code für mehrere Buchstaben durchgehen. Ein gutes Testset als Eingabe wäre "abc mno xyz" mit keys={0, 1, 13, 25, 26, 27}. Warum? abc sind gute Tests, weil sie die "Edgecases" des Anfangs sind. mno ist gut, weil es allgemeine "mittlere" Werte sind, und xyz sind die Edgecases am Ende des Alphabets. Ähnlich mit den Keys: {0, 1} ist keine Verschlüsselung und ein Shift by 1, was einfach zu prüfen ist. 13 ist ein genereller, allgemeiner Wert und 25, 26, 27 sind Edgecases für Wrap-Arounds. Natürlich musst du nicht alle diese Testsets durchspielen. Aber lasse den Computer sie rechnen und falls das Ergebnis abweicht, dann kannst du es von Hand durchgehen. Gerne auch hier posten, falls du das Problem dann immer noch nicht siehst.
C++:
letter2 = (letter = 96+key);
Bitte nicht. Es wird unleserlich und ist nicht, was du haben willst. Warum lässt du letter nicht einfach so, wie's ist?
Du hast immer noch diese (ohnehin falsche) Zuweisung drin. Es macht keinen Sinn, letter hier zu verändern.

Dein Problem ist u.a., dass wenn letter + key > 122, dann wird letter zu 'a'+key. Also ist letter dann nicht mehr abhängig von der Eingabe. Siehst du da ein Problem?
Ehrlich gesagt werde ich nicht so richtig schlau aus dir - du ignorierst geflissentlich mindestens 1 Hinweis pro Beitrag, den ich schreibe. Selbst in deinem letzten Post fehlt jetzt, was du bei z tatsächlich bekommst. Stattdessen haust du einen Code rein, der kaum von deinem ursprünglichen Code abweicht, den du schon vor 2-3 Tagen hattest.
Aber wenn ich einen klareren, saubereren Code angebe, der eigentlich schon viel zu viel Hilfe ist, ignorierst du den auch und machst mit dem alten weiter... Also willst du deinen existierenden Code verbessern, was an sich ja lobenswert wäre - nur, warum folgst du dann nicht den Hinweisen? Ich gebe dir wirklich ungern den gefixten Code. Die Idee dieses Forums ist ja, nicht nur einen Code hinzuschmeissen, sondern die Herangehensweisen zu vermitteln und trainieren. Aber ich habe mittlerweile schon so viel Zeit hineingesteckt, da kann ich dir auch gleich einen gefixten Code geben. (Es ist übrigens sehr viel schwieriger, Hinweise zu geben als direkt den Code zu fixen - da du das aber ohnehin nicht zu schätzen wissen scheinst, verschwende ich keine Zeit mehr damit) Es ist dann deine Verantwortung, ob du den einfach abschreibst oder nicht.

C++:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main (void)
{

    int key = 3;
    int letter = 0;
    int letter2 = 0;

    key = key % 26; // Wir haben nur 26 verschiedene keys

    char c;
    while( (c = getchar()) != '\n')
    {
        c = tolower(c);
        letter = (int)c;
     
        if (letter == ' ')
        {
            letter2 = letter;
        }
        else if((letter + key) > 'z')
        {
            letter2 = letter + key - ('z' - 'a' + 1); //'z'-'a'+1 == 26 => kein Overflow mehr möglich, da key < 26
        }
        else 
        {
             letter2 = letter + key;
        }
        c = (char)letter2;
        putchar (c);
    }
    putchar ('\n');
    return EXIT_SUCCESS;
}

Es steht dir nun frei, diesen oder den (wesentlich besseren) Code oben zu nehmen. Alternativ kannst du den Code auch ignorieren und die Hinweise befolgen und selbst darauf kommen und weitere Fragen stellen. Aber ich werde keine Fragen mehr beantworten, sofern nicht auf alle vorherigen Hinweise Bezug genommen wird.

Gruss
cwriter
 
Zuletzt bearbeitet:
Anzeige

Neue Beiträge

Anzeige