Zum Inhalt springen
View in the app

A better way to browse. Learn more.

Fachinformatiker.de

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Pizzacorgie28

User
  • Registriert

  • Letzter Besuch

Reputationsaktivität

  1. Danke
    Kleine Randnotiz: Du darfst gerne in der Code-Box unten rechts die Sprache für das Syntax Highlighting wählen @Pizzacorgie28
  2. Like
    Wie soll auch das funktionieren, wenn dein Text länger ist als dein Key?
    output[i] = eingabe[i]^key[i]; //XOR verschlüsselung Dein Key muss zwangsläufig genauso lang sein, wie dein zu verschlüsselnder Text.
    In anderen Sprachen würdest du eine "Index out of Range"-Exception bekommen. C hat aber keine Bereichsüberprüfung und er greift nun mit key[i] auf einen ungeschützten Bereich, wenn der Text länger ist, als der Schlüssel.
     
  3. Positiv
    Ein Zeiger ist eine Variable, die statt den konkreten Wert die Speicheradresse zu diesem Wert besitzt. Eine Speicheradresse kann man sich vorstellen, wie eine Hausnummer, nur dass anstatt wir hier häuser Bytes haben. Die Adresse 0x1 (Hexadezimalschreibweise) ist das erste Byte im Speicher.
    int i1 = 3; // i1 hat den Wert 3 int* i2 = &i; // i2 hat als Wert die Speicheradresse von i1 Das &-Zeichen ist der sog. Adressoperator. Mit dem können wir die Adresse einer Variable abrufen. Darum geben wir bei scanf() die Adresse an, wohin der Wert geschrieben werden soll.
    Ich persönlich finde die Schreibweise von Zeigern, die man häufig in C-Beispielen findet, nicht so schöb, weil der Stern etwas tückisch ist. Der wird nämlich für zweierlei Dinge verwendet. Einmal für die Kennzeichnung eines Zeigers und einmal den konkreten Wert eines Zeigers zu ermitteln. Daher schreibe ich eher
    int* i2 = &i1; anstatt
    int *i2 = &i1; So wird es für mich deutlicher, dass es sich um einen Int-Zeiger handelt und der Stern nicht zum Variablennamen dazugehört.
    int main() { int i1 = 3; // i1 hat den Wert 3 int* i2 = &i1; // i2 hat als Wert die Speicheradresse von i1 printf("Wert i1: %d\n", i1); printf("Adresse i1: %p\n", &i1); printf("Wert i2: %p\n", i2); printf("Adresse i2: %p\n", &i2); printf("Inhalt i2: %d\n", *i2); return 0; } Da kommt jetzt z.B. sowas raus:
    Wert i1: 3 Adresse i1: 0x7ffd27627e44 Wert i2: 0x7ffd27627e44 Adresse i2: 0x7ffd27627e48 Inhalt i2: 3 i2 hat jetzt nun als Wert die Speicheradresse von i1. Liegt aber in einem anderen Speicherbereich und der konkrete Inhalt ist die Zahl 3.
    Ein String wird in C als Array von Characters dargestellt. Ein Array ist wiederum eine Sonderform eines Zeigers. Die Variable zeigt auf das erste Element des Arrays.
    int main() { char text[] = "Hallo Welt"; printf("Inhalt text: %c\n", *text); printf("Wert text: %p\n", text); return 0; } Da kommt z.B. das dabei raus.
    Inhalt text: H Wert text: 0x7fff5582eead Der Inhalt ist einfach 'H' und als Wert die Adresse.
    Die Eckigen Klammern, z.B. bei text[2] ist ein indexierter Zugriff. Wir haben es dann hier mit einer Zeiger-Aritmethik zu tun und zwar wird der Zeiger um zwei Stellen verschoben. Da er weiß, dass es sich hier um ein Char-Array handelt und ein Char ein Byte groß ist, weg er nun von der Speicheradresse zwei Bytes weiter. In unserem Beispiel wäre dies das Zeichen 'l'.
  4. Like
    Wieso ist in xorencrypt() key ein Zeiger auf ein Integer?
    Was erwartest du denn in, was bei key[i % keylen] rauskommen soll?
  5. Like
    Nein, denn genau das ist der Witz: Es ist ein Ring.
    Wenn ich ein Zeichen um 12 Stellen verschiebe, um wie viele Stellen muss ich es weiterschieben, um wieder auf den Ursprung zu kommen?
  6. Like
    Beim Verschlüsseln erhöhst du den Wert des chars, checkst dann ob sein Wert zu hoch ist und wenn ja ziehst du die Zeichensatzlänge (26) ab um wieder im gültigen Bereich zu landen.
    Beim Entschlüsseln verringerst du (in deiner ersten Code-Version) den Wert des chars, checkst dann aber nicht ob der Wert zu niedrig ist, sondern (sinnloserweise) wie beim Verschlüsseln ob der Wert zu hoch ist.
    Aus der -12 eine +14 zu machen ist eine möglich Korrektur des Problems, dabei solltest du dir aber im Klaren sein, warum es funktioniert. (Zeichensatzlänge (26) - entschlüsselungsweite(12) = +14)
  7. Like
    Überprüfe doch einmal deine "Überlaufkorrektur" beim Entschlüsseln. Bei Verschlüsseln funktioniert diese korrekt, beim Entschlüsseln leider nicht.
  8. Haha
    Damit behebt man das Problem aber nur bedingt. scanf() scant solange den stdin, bis ein newline gefunden wird. Bei "%c" würde man also jedes Zeichen einzeln zurückgeben. Deswegen erscheit auch der Text zwei Mal, weil im Gegensatz zu Unix Windows ein anderes Vorgehen für new line hat. Wenn man nämlich '1' + Enter eingibt, werden drei Zeichen übertragen: '1', carriage return und new line. Also gibt scanf() zurück '1' zurück und dann carriage return. In deinem Beispiel würde er zwar carriage return ignorieren aber das Problem bestünde weiterhin, wenn der Benutzer z.B. "12" eingibt. Dann wird die Schleife wieder zwei Mal ausgeführt und dementsprechend wird der Text auch zwei Mal ausgewiesen.
    Wenn man das Problem in den Griff bekommen möchte, muss man etwas weiter ausholen, denn mit einem scanf() alleine kommt man hier nicht weit. scanf() ist auch nicht unbedingt dafür gedacht, Benutzereingaben entgegenzunehmen, sondern ist fürs Parsing von stdin gedacht. Das Parsing setzt aber schon voraus, dass die Daten in einer Strukturierten Form vorliegen. Das ist aber bei Benutzereingaben nicht der Fall. Die sind sehr willkürlich.
    Man könnte jetzt auf die Idee kommen, einfach per scanf() einen string einzulesen anstatt ein einzelnes Zeichen:
    char s[1]; scanf("%s", s); printf("%s", s); Dies ist aber nicht vor Speicherüberläufen geschützt. Wenn man jetzt "123" eingibt, würde "123" auch rauskommen, obwohl der String nur ein Zeichen belegt und die anderen beiden außerhalb des Bereiches liegen und somit vollkommen ungeschützt.
    Der ideale Weg wäre mit fgets() die stdin in einem Puffer zu lesen und diesen dann zu parsen. fgets() ist nämlich sicher vor Speicherüberläufen. Er stoppt, wenn der Puffer gefüllt ist, new line oder end of file erreicht ist. Jenachdem, was zu erst eintritt.
    Hier mal eine Funktion, die sicherstellt, dass der Benutzer auch wirklich nur ein Zeichen eingegeben hat:
    int readChar(char *c) { char puffer[10]; char temp[10]; fgets(puffer, sizeof(puffer), stdin); sscanf(puffer, "%s", temp); int length = strlen(temp); if(length == 1) { *c = temp[0]; return 0; } if(length == 0) return -1; if(length > 1) return 1; } Der Rückgabewert ist ein für C typisches Pattern um Fehlermeldungen darzustellen, da es ja keine Exceptions gibt. Bei 0 ist alles in Ordnung. Bei -1 hat der Benutzer nur die Enter-Taste gedrückt und bei 1 wurden zu viele Zeichen eingeben.
    Und nein, das hat alles nichts mit irgendwelchen Eigenheiten von C zu tun, sondern C ist eine ist zwar eine Hochsprache aber in einem sehr niedrigen Level und das was man mit anderen Sprachen mit einer Zeile machen kann, muss man hier schon selber schreiben.

  9. Haha
    bitte gestatte mir den Hinweis dass die Schwachstelle dieser Verschlüsselung die verbleibende Häufigkeit einzelner Zeichen ist ...
    Ein so verschlüsselter Text ist in kurzer Zeit wieder lesbar
  10. Like
    Da muss ich mich mal kurz selber korrigieren: Da wurde zwar char b deklariert, allerdings falsch initialisiert. Du initialisierst die Variable da mit sich selbst, ich schätze das ist undefined behaviour. Da willst du auf jeden Fall char b = 'b' schreiben.
  11. Like
    Wie @blaargh schon schreibt liegt das daran, dass du auch eine Variable hast, die so heißt. Du solltest das Coding aber einheitlich gestalten. Also entweder fragst du direkt nach Charactern ab, dann muss das bei allen in Anführungszeichen oder aber du fragst auf den Wert der Variablen/Konstanten ab, dann müsstest du aber bei den anderen Abfragen statt '1','2' und '3' mit ceaser, vigenere und symmetrische vergleichen. Durch diese Vermischung ist es (gerade auch für dich selber, wenn ich deine Antwort lese) schwer nachvollziehbar, was das Coding jetzt genau machen soll. 🙂
    @blaargh falsch initiiert ist sie nicht, da der Variable b der Integerwert 98 zugewiesen wird, der 'b' entspricht. Nichtsdestotrotz ist es so nicht gerade übersichtlich und man sollte sich vielleicht über die Benennung der Variablen mehr Gedanken machen (gerade wenn es später um wesentlich komplexere Programme geht :D)
  12. Like
    Das ist nicht nur bei C so, sondern bei sehr vielen Programmiersprachen. Liegt einfach daran, dass darunter nun einmal eine Maschine arbeitet, die konkrete Daten braucht und wenig Raum für Interpretation bietet. D.h. du als Entwickler musst dafür sorgen, dass die möglichen Fehler von Benutzern korrekt abgehandelt werden. (Ich selber entwickle in ABAP und da ist es sogar problematisch, wenn du bei gewissen Klammern kein Leerzeichen setzt ^^')
    Daher auch mein Vorschlag statt mit If mit Switch-Case zu arbeiten, da du dort direkt einen Zweig (default) hast, der allen anderen Eingaben als den gewünschten (1,2,3,b) abhandeln kann.
    Die Abfrage solltest du meines Wissens nach trotzdem eher
    while (auswahl != 'b') lauten. Oder ist C da nicht so penibel?
  13. Like
    Korrekt, das würde so nicht compilen. Der Vergleich mit b impliziert, dass es eine Variable mit dem Namen b gibt, anstatt mit dem char 'b' zu vergleichen. Allerdings hat er ja recht weit oben die Variable char b; deklariert, deswegen ist das kein Problem.
  14. Like
    Das hängt mit der scanf() Methode und dem Zeilenumbruch von "\n" zusammen. Um das zu umgehen, kannst du einfach ein Leerzeichen vor das %c in der folgenden Zeile hinzufügen:
    scanf("%c", &auswahl) ; scanf(" %c", &auswahl) ;  
  15. Like
    Wozu willst du das Zeichen '1' noch in eine 1 umwandeln? Ich sehe hier keinen Bedarf für.
     
  16. Like
    Stimmt. Ich hab hier etwas zu umständlich gedacht. ceaser, vigenere und symmetrische müssen ja nicht zwangsweise Zahlen sein.
  17. Like
    Ist vielleicht schon zu viel aber man könnte daraus auch Konstante, mittels der #define Direktive machen.
     
     
  18. Like
    Genau das! Zumal man diese Variablen doch sowieso nicht braucht, oder?
    @Pizzacorgie28 In der If-Abfrage musst du dann nicht nach Integerwerten fragen sondern kannst direkt nach Char-Werten fragen, indem du den "eigentlichen" Wert in Hochkommata setzt. Eine Wertzuweisung macht für mich am Anfang auch keinen Sinn, außer du würdest dann direkt Abfragen "if ( auswahl == ceaser )" etc. D.h. eigentlich kannst du die drei Variablen auch weglassen und dann jeweils einfach nur fragen "if (auswahl == '1')" usw.
    Müsste die Bedingung von der While-Schleife nicht auch in Hochkommata oder aber als Zahlenwert dort stehen?
    Übrigens könntest du statt 4 If-Abfragen auch mit Switch Case arbeiten und dort dann auch, wie ich oben schon geschrieben habe, die Eingabe direkt mit den Variablen, denen du einen Wert zugewiesen hast, vergleichen. Dabei sollten die Variablen aber eher Konstanten sein, da sich der Wert ja nicht ändern soll.
  19. Like
    Ein char ist intern auch nur ein Zahlenwert, der exakt ein Byte groß ist. Komischer Zufall, wa? Historisch betrachtet ist ein Byte die Menge an Bits, die benötigt werden, um ein Zeichen darzustellen.  Mit Hilfe der ASCII-Tabelle weiß die Grafikkarte nun, wie das Zeichen mit dem Wert 98 aussieht. Es ist nämlich ein b. Der Weg geht auch andersrum. Man kann ein Zeichen in Hochkommata setzen und der Compiler wandelt es zurück in eine Zahl.  Du kannst dann also z.B.
    while (auswahl != 'b') { schreiben und der Compiler macht aus 'b' eine 98. Dasselbe gilt auch für deine if-Abfragen.
    Du kannst ja mal folgenden Code testen:
    printf("%d", 'b'); Du siehst, als Ergebnis kommt 98 raus.
  20. Like
    Das sieht schon nicht schlecht aus, die Aufgabenstellung erfüllt das Programm ja. Aber wie du bereits angemerkt hast, kann man den Code noch etwas leserlicher gestalten. Gestern hattest du in einem Code Ausschnitt noch folgende Zeile:
    printf("Bitte eine der oben genannten zeichen eingeben\n"); Die würde ich wieder mit in das Programm aufnehmen, damit der spätere Benutzer des Programms weiß, das seine letzte Eingabe nicht gültig war.
    Da würde ich dir recht geben, schauen wir uns mal den Fall für 1 an:
    if (auswahl == 49) //49 steht für 1 49 steht zwar korrekterweise für das Zeichen '1', aber ohne den Kommentar daneben wäre das für einen anderen Programmierer der deinen Code liest nicht ersichtlich wo die magische 49 herkommt (Außer er hat die ASCII Tabelle auswendig gelernt, aber davon würde ich nicht ausgehen).
    Das könnte man dann zwar so lösen:
    int ceaser=49; if (auswahl == ceaser) ... Trotzdem ist die 49 noch etwas magisch, da in der Aufgabenstellung steht, das eine 1 erwartet wird. Du könntest jetzt zwar deine eigene Methode schreiben, die chars in den entsprechenden int Wert umwandelt, aber glücklicherweise ist das nicht das erste mal, das jemand so eine Umwandlung vor hat und man muss das Rad nicht neu erfinden. Nachdem ich char to int Umwandlung in einer Suchmaschine eingegeben hab, wurde mir die atoi() Methode vorgeschlagen.
  21. Like
    %i ist aber auch nicht richtig. Ist b eine Zahl?
    Was hindert dich, die Eingabe zu machen, diese Eingabe auszuwerten, deine Ausgabe zu machen und dann wieder von vorne anzufangen?
  22. Like
    Gibt ja noch mehr als nur Vergleichsoperatoren.
    Aber überlege mal, wie grafische Oberflächen funktionieren. Grafische Oberflächen laufen in einer Endlosschleife. Man könnte auch hier das gleiche Prinzip anwenden. Es wird immer wieder die Eingabe eingelesen, verarbeitet und etwas wird ausgegeben. Wie sieht also eine endlosschleife aus und wie müsstest du deinen Code umstrukturieren?
    Schaue auch mal dein scanf() an. Vorallem welches Format deine Eingabe haben muss und welche du erlauben möchtest.
  23. Like
    Genau %c ist der korrekte Format specifier für Character Datentypen. In der Dokumentation von der scanf() Methode ist das auch noch mal etwas ausführlicher beschrieben. Die Methode erwartet als Parameter einen const char*. (Wobei die Dokumentation von scanf() zugegebenerweise nicht gerade die intuitivste ist, besonders am Anfang.)
    scanf("%d",&auswahl); Wäre hier also nicht korrekt, weil die Variable auswahl mit dem Datentypen int deklariert wurde. Der Mursk enstand, weil die Daten an der Adresse, die der scanf() Aufruf als ersten Parameter zurück gibt, als char formatiert sind.
    int 1; ist beispielsweise die Zahl 1.
    char '1'; hingegen ist nur das Zeichen '1' nicht aber der Wert. Intern steht jetzt beispielsweise für '1' der Wert 49 im Speicher das ist der ASCII Wert für das Zeichen '1'. Und da man vorher definiert hat, dass es sich um einen char handelt, weiß die Anwendung das sie es als '1' interpretieren soll.
    Praktischerweise hast du aber bereits die char Variable b angelegt, die kann hier übergeben werden.
    Jetzt sollte auch wieder lesbarer Inhalt in der Variable stehen.
    Wenn du den Inhalt der char Variable nun in einen int kopieren möchtest musst du diesen zunächst umwandeln/casten. Zum Beispiel mit einem direkten cast wie folgender:
    auswahl = (int)b; so wird aber nur der Inhalt von b nach auswahl kopiert, um bei dem Beispiel mit der '1' zu bleiben, steht dann in auswahl die Zahl 49, was aber nicht korrekt ist. Du benötigst also eine andere Lösung, um einen char in einen int umzuwandeln.
    Würde funktionieren, wenn es nicht noch den 'b' Fall und Zahlen kleiner als 0 gäbe, hier brauchst du also eine andere Unterscheidung, ob die letzte Eingabe nun valide war oder nicht. Um nicht zu viel vorwegzunehmen, nur noch folgender Satz:
    Wenn in der Fallunterscheidung in einen der Blöcke gesprungen wird, war die Eingabe valide.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.