Rot-n Algorithmus

Gast #3197013
Lesenswert?

Hallo Leute,

ich bin auf der Suche nach einem Quellcode für einen Rot-n Algorithmus 
ausgelegt für die Asciizeichen im Bereich 33 bis 126.

Meine bisherige Lösung implementiert lediglich Rot47. Aktuell mache ich 
damit eine Text unlesbar. Nun würde ich jedoch gerne die Funktion 
dahingehend erweitern, dass wenn an einer bestimmten Stelle eine Zahl 
zwischen 1 und 47 auftaucht, der Text um die besagte Zahl verschoben 
wird.

Aktuelle programmiere ich in Visual Basic aber wenn ihr zufällig nen 
passenden Codesnippet rumfliegen habt würde ich mich sehr über den Code 
freuen, unabhängig von der Sprache (jedenfalls was die geläufigsten 
angeht ;)).

Schönen Sonntag noch,
J.L.
#3197028
Lesenswert?

Du meinst sich die "rotate by n" oder Caesar-Verschlüsselung.

Du addierst einfach n auf deinen Asciiwert und beim Überschreiten der 
Bereichsgrenzen fügst du eine Sonderbehandlung ein. Dafür kannst du den 
Modulo-Operator nutzen.

Notiere dir mal die Rahmenbedingungen auf einen Zettel und du wirst 
schnell zu einer Lösung gelangen.

Grüsse
Gast #3197082
Lesenswert?

Ich bin nur etwas verwirrt wegen der Grenzen und dem Modulo.

Mein Bisheriger Code sieht folgerndermaßen aus und klappt auch ohne 
dergleichen:
1
    Public Function encode(strInput As String, n As Integer)
2
        Dim i As Integer
3
        Dim strOutput As String
4
        For i = 1 To Len(strInput)
5
            strOutput = strOutput & Chr((Asc(Mid(strInput, i, 1)) + n))
6
        Next i
7
        encode = strOutput
8
    End Function
9

10
    Public Function decode(strInput As String, n As Integer)
11
        Dim i As Integer
12
        Dim strOutput As String
13
        For i = 1 To Len(strInput)
14
            strOutput = strOutput & Chr((Asc(Mid(strInput, i, 1)) - n))
15
        Next i
16
        decode = strOutput
17
    End Function
#3197111
Lesenswert?

Dein Bereich liegt zwischen 33 und 126 bzw. '!' und '~'.

Bei der Verschlüsselung wird der Wert > 126, dass musst du behandeln.

Bei der Entschlüsselung wird der Wert < 33, dass musst Du ebenfalls 
behandeln.

Warum verwendest Du '&'? Ist dieses den kein logischer Operator? Den 
Zusammenhang verstehe ich hier nicht.

Grüsse
Gast #3197121
Lesenswert?

Markus M. schrieb:
> Warum verwendest Du '&'? Ist dieses den kein logischer Operator? Den
> Zusammenhang verstehe ich hier nicht.
Das ist in Basic der Zeichenketten-Verkettungsoperator.

Wenn ich mich recht entsinne, darf in Visual Basic die Mid()-Funktion 
als Mid-Anweisung auch als l-value stehen, sodass man direkt zuweisen 
kann.
1
Mid(s$, i, 1) = Chr(Asc(Mid(s$, i, 1)) + n)
Gast #3197141
Lesenswert?

Die Frage zu dem &-Opertaor wurde ja bereits erklärt daher
habe ich jetzt mal versucht den Code anzupassen aber es will noch nicht.

Ich möchte im Bereich von 1  bis 47 verschieben, daher komme ich 
zwischen 'p' über die '~' möglicherweise über die grenzen und 
sicherstellen das er beim Verschlüsseln ein Zeichen >32 daraus macht.
Mein Code sieht jetzt wie folgt aus.
1
    Public Function encode(strInput As String, n As Integer)
2
        Dim i, asciidec As Integer
3
        Dim strOutput As String
4
        For i = 1 To Len(strInput)
5
            asciidec = Asc(Mid(strInput, i, 1))
6
            'strOutput = strOutput & Chr(asciidec + n))
7
            If asciidec >= 80 And asciidec <= 126 Then
8
                strOutput = strOutput & Chr(32 + ((asciidec + n) Mod 126))
9
            Else
10
                strOutput = strOutput & Chr(asciidec + n)
11
            End If
12
        Next i
13
        encode = strOutput
14
    End Function
15

16
    Public Function decode(strInput As String, n As Integer)
17
        Dim i, asciidec As Integer
18
        Dim strOutput As String
19
        For i = 1 To Len(strInput)
20
            asciidec = Asc(Mid(strInput, i, 1))
21
            'strOutput = strOutput & Chr(asciidec - n))
22
            If asciidec >= 80 And asciidec <= 126 Then
23
                strOutput = strOutput & Chr(32 + ((asciidec + n) Mod 126))
24
            Else
25
                strOutput = strOutput & Chr(asciidec + n)
26
            End If
27
        Next i
28
        decode = strOutput
29
    End Function

Aber wenn ich die Rotation-n verändere hab ich wieder Chaos.
#3197148
Lesenswert?

Ist doch klar, dass es Chaos gibt Du gibt die Grenzen mit 80 und 126 
vor. Gehst aber davon aus, das dein "Alphabet" bei 32 beginnt.

Was kommt heraus, wenn Du 32 durch 80 ersetzt oder äquivalent 80 durch 
32?

Ausserdem sollte der Inputwert immer innerhalb der Grenzen liegen. Das 
brauchst Du nicht zu prüfen. Denn umgekehrten Fall musst Du prüfen.

Range: 33 bis 126
if: (input + n) > 126  ->  (input + n + 33 ) - 125  - 1

Grüsse
Gast #3197152
Lesenswert?

Dann kommt auch nur Blödsinn raus. Alles was nicht in den Grenzen ist 
(ausgehend davon das auch nur auch nur Zeichen verschlüsselt werden die 
in dem Bereich 33-126 liegen) wird ja mit dem ELSE-Zweig abgefangen und 
um n erhöht.
Gast #3197196
Lesenswert?

Mein Code sieht jetzt folgendermaßen aus:
1
    Public Function encode(strInput As String, n As Integer)
2
        Dim i, asciidec As Integer
3
        Dim strOutput As String
4

5
        For i = 1 To Len(strInput)
6
            asciidec = Asc(Mid(strInput, i, 1))
7
            asciidec = asciidec + n
8
            If asciidec > 126 Then
9
                asciidec = (asciidec Mod 126) + 32
10
            End If
11
            strOutput = strOutput & Chr(asciidec)
12
        Next i
13
        encode = strOutput
14
    End Function
15

16
    Public Function decode(strInput As String, n As Integer)
17
        Dim i, asciidec As Integer
18
        Dim strOutput As String
19

20
        For i = 1 To Len(strInput)
21
            asciidec = Asc(Mid(strInput, i, 1))
22
            If (asciidec < (126 - n)) Then
23
                asciidec = asciidec - 32
24
                asciidec = asciidec + 126
25
                asciidec = asciidec - n
26
            Else
27
                asciidec = asciidec - n
28
            End If
29
            strOutput = strOutput & Chr(asciidec)
30
        Next i
31
        decode = strOutput
32
    End Function

Die Verschlüsselung für n=47 klappt nur mit der Decodierung hapert es.
Moderator #3197222
Lesenswert?

Johannes Lake schrieb:
>                asciidec = (asciidec Mod 126) + 32

Das 'Mod' kannst du hier auch durch ein '-' ersetzen, also
1
                asciidec = asciidec - 126 + 32

oder gleich
1
                asciidec = asciidec - 94

>            If (asciidec < (126 - n)) Then
>                asciidec = asciidec - 32
>                asciidec = asciidec + 126
>                asciidec = asciidec - n
>            Else
>                asciidec = asciidec - n
>            End If

Statt (126 - n) müsste in der obersten Zeile (33 + n) stehen.

Oder mach's einfach genauso wie bei encode, nur andersherum:
1
            asciidec = asciidec - n
2
            If asciidec < 33 Then
3
                asciidec = asciidec + 94
4
            End If

Gleiche oder sehr ähnliche Code-Abschnitte sind meist schlecht, weil
aufwendiger zu lesen und weniger wartungsfreundlich. Besser und noch
einfacher geht es so:
1
    Public Function decode(strInput As String, n As Integer)
2
        decode = encode(strInput, 94 - n)
Gast #3197251
Lesenswert?

Danke an alle. Hatte es gerade selber ans Laufen gekriegt aber mit den 
Optimierungstipps vom Vorredner ist es nochmal ein Stück sauberer 
geworden.
1
 Public Function encode(strInput As String, n As Integer)
2
        Dim i, asciidec As Integer
3
        Dim strOutput As String
4

5
        For i = 1 To Len(strInput)
6
            asciidec = Asc(Mid(strInput, i, 47))
7
            asciidec = asciidec + n
8
            If asciidec > 126 Then
9
                asciidec = asciidec - 94
10
            End If
11
            strOutput = strOutput & Chr(asciidec)
12
        Next i
13
        encode = strOutput
14
    End Function
15

16
    Public Function decode(strInput As String, n As Integer)
17
        Dim i, asciidec As Integer
18
        Dim strOutput As String
19

20
        For i = 1 To Len(strInput)
21
            asciidec = Asc(Mid(strInput, i, 1))
22
            asciidec = asciidec - n
23
            If asciidec < 33 Then
24
                asciidec = asciidec + 94
25
            End If
26
            strOutput = strOutput & Chr(asciidec)
27
        Next i
28
        decode = strOutput
29
    End Function
#3197256
Lesenswert?

> Das 'Mod' kannst du hier auch durch ein '-' ersetzen, also
Bei Verwendung von Modulo sind beliebige n bei der Verschlüsselung 
gültig. Z.B. Auch n = 555. Wieder eine Abfrage gespart. ;-)

Funktionssicherheit erhöht!

@ Johannes
Wenn Du jetzt noch die Zahlen durch sprechende Konstanten ersetzt, wird 
es nochmal ein Stück sauberer.

Grüsse
Moderator #3197321
Lesenswert?

Markus M. schrieb:
> Dann etwas präziser: für n > 0

Also doch eine Abfrage ;-)

Nee, du hast schon recht. Mod ist sicherer als nur eine Subtraktion, nur
eben noch nicht völlig sicher.

Gerade bei Integer-Divisionen und Modulo-Operationen muss man bei
negativen Operanden höllisch aufpassen, um keine Überraschungen zu
erleben. Zudem werden negative Operanden in verschiedenen Programmier-
sprachen unterschiedlich behandelt, leider meist so, wie man es nicht
erwartet ;-).

Nicht einmal innerhalb von Microsoft kann man sich auf eine einheitliche
Definition der Modulo-Funktion einigen, deswegen liefert das Visual-
Basic-Mod andere Ergebnisse als das Excel-Mod. Das ist für die Anwender
schwer nachvollziehbar, da VBS ja ein Bestandteil von Excel ist:

  http://support.microsoft.com/kb/141178

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren