VisualBasic Chars aus einem String per Referenz ändern

Krafty

Lt. Commander
Registriert
Sep. 2009
Beiträge
1.177
Hallo,

vielleicht wisst ihr einen günstigen und einfachen Weg:

Ich habe geplant über einen String zu iterieren (zweckmäßig per for each Schleife) und dabei die Werte der einzelnen Chars zu ändern, und zwar so, dass der Ausgangs-String diese Änderungen erfährt, ohne ihn komplett neu zu bauen.

Code:
Dim sTest As String = "Test"

        For Each zeichen As Char In sTest
                zeichen = Chr(Asc(zeichen) + 1)
            End While

        Next

Sowas in der Art.

Danke schonmal für die Hilfe.
 
Ja, kannst du schon so machen

Code:
For i = 1 to len(sTest)
  nTestNeu = sTestNeu & Chr(Asc(mid(sTest, i, 1)) + 1)
Next

Oder so :)

Du musst zudem noch an das Modulo denken, denn Z+1 = ?? Vermutlich sollte das dann A sein.

Performanter ist es vermutlich auch wenn du aus dem String einen ByteArray machst, da die Operationen durchführst und dann komplett wieder einen String erstellst.
 
Hallo,

das mit dem Byte/Char Array ist mir auch schon durch den Kopf gegangen.
Allerdings stellte sich mir halt die Frage, ob es sich nicht vermeiden lässt den String jedes mal neu zusammen zu setzen, indem ich irgendwie eine Referenz auf die einzelnen Chars klatsche.
 
Konkatenierug ist auf jeden Fall nicht sehr performant. (Daher verwendet man für so Sachen auch oft einen Stringbuilder)

Mit einem Byte Array bist du wahrscheinlich besser bedient...
Code:
Dim sTest As String = "Test"
Dim b() As Byte

b = StrConv(sTest, vbFromUnicode)
 
Da hast du etwas vor, was technisch mit der Klasse String nicht möglich ist und nie möglich sein wird (Visual Studio 2002 und neuer). Unter Visual Basic kommt der .NET-Datentyp String zum Einsatz. Eine String-Instanz ist unveränderlich, man erhält nie eine Referenz auf die einzelnen Zeichen, sondern immer nur Kopien: MSDN Dokumentation System.String

Verwende gleich die StringBuilder-Klasse, die genau für deinen Zweck da ist: eine veränderliche Zeichenkette. Mit StringBuilder.Chars(index)=neuesZeichen legst du direkt in der Zeichenkette das neue Zeichen fest, ohne dass gleich eine neue Instanz erstellt wird, wie das bei String der Fall wäre: MSDN Dokumentation System.StringBuilder

Als Notlösung kannst du auch ein Char-Array verwenden.

@snow1
Ein byte-Array ist denkbar ungeeignet, weil man nicht weiß, in wie viele Bytes ein Char gemappt wird. Die Kodierung eines Unicodezeichens kann in bis zu 4 Bytes umfassen.
 
Zuletzt bearbeitet: (Bytearray nicht geeignet)
Hallo leimer,

das mit dem StringBuilder sieht sehr vielversprechend aus, danke dafür.

Einziger Wermutstropfen ist, dass man nicht über das Objekt iterieren kann sondern mit einer normalen "for i" Schleife auf den Index zielen muss, aber ich werde es wohl überleben. ;)

Mir ist etwas "seltsames" aufgefallen:

Code:
For i As Integer = 0 To sPWTest.Length
                While Asc(sPWTest(i)) < 122
                    Threading.Thread.Sleep(0)
                    sPWTest.Replace(i, Asc(sPWTest(i)) + 1)
                End While
            Next i

Bei diesem Konstrukt wird bei jedem Replace die Länge des StringBuilder Objects um 1 erhöht. Dadurch wird es zu einer Endlos-Schleife.

Ok, 2 Sachen liefen nicht so, wie sie wollten.
Beim Erzeugen des Stringbuilder Objects hat er einen String mit "Zahlen" in Integer umgewandelt und so nicht als Ausgangs-String genommen sondern als Anfangs-Länge... die Klasse muss ja voller Overloads sein :-/

Außerdem habe ich vergessen bei der Länge 1 abzuziehen und den Ascii wieder in Char umzuwandeln.
Und Replace ist String-Abhängig und nicht Integer... aber das wars erstmal für heute ^^
 
Zuletzt bearbeitet:
Der StingBuilder frisst als Konstruktorparameter einen String oder die Anfangskapazität bzw. beides auf einmal: StringBuilder Member Doku

Möchte garnicht wissen, was dein Code machen soll... ergibt für mich wenig Sinn.
Code:
' Über alle Zeichen des StringBuilders iterieren (richtig wäre: sPWTest.Length-1)
For i As Integer = 0 To sPWTest.Length
    ' Solange das Zeichen in der Unicode-Kodierung kleiner als 122 'z' 
    ' ist (also einschließlich der Zeichen []_ usw.)...
    While Asc(sPWTest(i)) < 122
        Threading.Thread.Sleep(0)
        ' Ersetze in sPWTest alle Zeichen mit Unicode-Kodierung i durch das Zeichen,
        ' dessen Unicode-Kodierung um eins höher ist als die Unicode-Kodierung des
        ' i. Zeichens in sPWTest
        sPWTest.Replace(i, Asc(sPWTest(i)) + 1)
        ' Dein Code ersetzt ALLE Zeichen im StringBuilder mit einem 
        ' bestimmten Code durch etwas anderes! *kopfschüttel*
    End While
Next i

Willst du vielleicht die Kodierung aller Zeichen im Stringbuilder "um Eins nach oben schieben"? Dann ist der folgene Programmcode richtig
Code:
' Über alle Zeichen des StringBuilders iterieren (richtig wäre: sPWTest.Length-1)
For i As Integer = 0 To sPWTest.Length-1
    ' Wenn das Zeichen in der Unicode-Kodierung kleiner als 122 'z' 
    ' ist (also einschließlich der Zeichen []_ usw.)...
    If Asc(sPWTest(i)) < 122
        Threading.Thread.Sleep(0)
        ' Ersetze in sPWTest das Zeichen an der Stell i durch das um eins höhere
        sPWTest(i) = Asc(sPWTest(i)) + 1)
    End If
Next i
 
Hallo,

im großen und ganzen hatte mich einfach ein wenig die Langeweile geplagt und ich mir überlegt unser System per BruteForce zu testen. (Deshalb sollen richtigerweise sehr wohl sämtliche Zeichen nacheinander schön durchprobiert werden)

Hatte ja durch die Edits angemerkt, dass ich die Fehler im Code schon bereinigt hatte und nun mit dem StringBuilder zurecht komme.

Nun kommt aber erst noch der wirklich spannende Teil:

Es muss berechnet werden, wieviele Kombinationsmöglichkeiten es gibt und welchen Zustand der String je nach Länge und verwendeten Zeichen nach X durchläufen hätte, um den Vorgang auf die vorhanden Cores auszulagern und nicht einfach 2-4 mal die selbe Arbeit zu verrichten :D

Jaja, sind Theorie und Formeln nicht das spannendste an der Programmierung? ^^
 
Krafty schrieb:
Hallo,

im großen und ganzen hatte mich einfach ein wenig die Langeweile geplagt und ich mir überlegt unser System per BruteForce zu testen. (Deshalb sollen richtigerweise sehr wohl sämtliche Zeichen nacheinander schön durchprobiert werden)

Zunächst: Bruteforce ist immer den denkbar schlechteste Weg. Oft gibt es deutlich effizientere Wege. Nur wenn es keine andere Möglichkeit gibt, sollte man Bruteforce in Erwägung ziehen.

Aber gerade bei Verschlüsselungen kann der Bruteforce-Ansatz deutlich länger dauern, als das Universum alt ist. Daher solltest du viel Zeit mitbringen ;)

Hatte ja durch die Edits angemerkt, dass ich die Fehler im Code schon bereinigt hatte und nun mit dem StringBuilder zurecht komme.

Krafty schrieb:
Es muss berechnet werden, wieviele Kombinationsmöglichkeiten es gibt und welchen Zustand der String je nach Länge und verwendeten Zeichen nach X durchläufen hätte, um den Vorgang auf die vorhanden Cores auszulagern und nicht einfach 2-4 mal die selbe Arbeit zu verrichten :D

Die Anzahl der Kombinationsmöglichkeiten ist einfach Größe des Alphabets hoch Anzahl der Stellen. 10-Stellen bei Groß-/Kleinschreibung sind dementsprechend 52^10 = 144555105949057024 Kombinationen.

Das Verteilen auf mehrere Cores ist nicht so wild. Grundsätzlich kannst du dir über statische und dynamische Verteilung gedanken machen. Da die Berechnung wohl immer fast gleich lange braucht, genügt hier statisch. Das kannst du entweder ganz klassisch mit Threads oder z.B. mit OpenMP machen...
 
Hallo,

ich habe mich für den BruteForce Ansatz entschieden, weil ich die Kennwörter ja sowieso kenne, Wörterbuch Angriffe keinen Sinn ergeben und ich einfach wissen möchte, wie lange es denn dauert.

Danke für die Bestätigung, etwas in dieser Art ist mir auch noch aus der Kombinatorik hängen geblieben und habe extra nochmal bei Wikipedia nachgeschaut. Auch das Auslagern auf Threads oder BackgroundWorker stellt kein Problem dar.

Muss mir nur noch einen Weg überlegen den Zustand nach x Durchläufen zu berechnen, aber bitte nicht vorsagen, sonst machts ja keinen Spaß mehr ;)

OffTopic:

Habt ihr jemals versucht mit dem Zufallsgenerator vom VisualStudio/.NET zu arbeiten?
Wollte mal das Infinite Monkey Theorem nachstellen und musste erkennen, dass ständig die Selben Zeichenketten generiert werden, egal wann und wo ich randomisiere...
 
Um herauszufinden, wie lange ein Bruteforce-Ansatz dauern würde, ist es wohl eine denkbar schlechte Idee den Bruteforce-Algorithmus durchlaufen zu lassen, da das viele viele Jahre dauern könnte.

Im Endeffekt brauchst du nur ermitteln wie viele Kombinationen du pro Sekunde durchführen kannst und dann kannst du es einfach hochrechnen.

Wenn du eine Verschlüsselung wie AES einsetzt, ist derzeit wohl Bruteforce wohl der einzige Ansatz. Aber wie gesagt, wirst du das Ergebnis wohl nicht mehr erleben.

Einfache Verschlüsselungen (ROT/Caesar, Vigenere, Substitution, ...) sind aber z.B. durch Frequenzanalyse recht schnell geknackt.
Ergänzung ()

Btw, das Infinite Monkey Theorem ist eher theoretischer Natur. Ich glaube nicht, dass es dich in irgend einer Form weiter bringt. Im Gegenteil, denn damit wirst du einige Kombinationen auch mehrfach probieren.
 
Zurück
Oben