Index eines Strings festlegen

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Xylon.

    Index eines Strings festlegen

    Hallo, ich hab mal wieder eine kurze Frage. Kann man einen String auch suchen, indem man den Index festlegt bei dem der Wert in einer rtb ist?
    (z.B. ein 4tes "Hallo" in einer rtb mit insgesamt 10 "Hallo"s) Wenn ja wie legt man das fest? Alleine mit IndexOf und LastIndexOf gehts ja nicht. Hab schon folgendes versucht:


    VB.NET-Quellcode

    1. Dim lastFindIndex As Integer = 0
    2. Dim stringToFind As String = TextBox5.Text
    3. Dim currentNumberOfMatches = 0
    4. Dim matchToStopAt As Integer = CInt(TextBox4.Text)
    5. While lastFindIndex > -1
    6. currentNumberOfMatches += 1
    7. If matchToStopAt = currentNumberOfMatches Then
    8. Exit While
    9. End If
    10. lastFindIndex = RichTextBox2.Text.Text.IndexOf(stringToFind, lastFindIndex)
    11. End While


    Dann mit Regular Expressions:

    VB.NET-Quellcode

    1. Public Function SearchForGivenString(text As String, pattern As String, Optional position As Integer = 1) As Match
    2. Dim found As MatchCollection = Regex.Matches(text, "\b" & pattern & "\b")
    3. Dim returnMe As Match
    4. If found.Count = 0 Then
    5. Return returnMe
    6. ElseIf position > found.Count Then
    7. Return found(found.Count - 1)
    8. Else
    9. Return found(position - 1)
    10. End If
    11. End Function


    mit

    VB.NET-Quellcode

    1. Dim testString As String = RichTextBox2.Text
    2. Dim returnMatch As Match = SearchForGivenString(testString, TextBox5.Text, TextBox4.Text)
    3. If Not IsNothing(returnMatch) Then
    4. MsgBox(WriteLine(returnMatch.Value & " " & returnMatch.Index)
    5. End If


    Leider funktionierte das nicht richtig. Hat jemand vielleicht andere Vorschläge?
    @Kevin Hombre: So wie ich das verstanden habe:
    In der RTB:

    Quellcode

    1. Asdf Hallo Bla das ist Hallo ein Test Hallo und viele Hallo sind enthalten Hallo

    Er möchte jetzt vermutlich das hier:

    VB.NET-Quellcode

    1. Dim Result = Foo(RTB.Text, "Hallo", 2)

    Dass hier also das "Hallo" mit dem Index 2 gefunden wird (nachfolgend fett markiert)
    Asdf Hallo Bla das ist Hallo ein Test Hallo und viele Hallo sind enthalten Hallo

    Also müsste 38 zurückgegeben werden (wenn ich mich nicht verzählt habe), weil das dritte "Hallo" (Index 2) an dieser Stelle im String beginnt.

    Soweit ich weiß, gibt's da keine vorgefertigte Funktion.
    Die musst Du selber zusammenstückeln. Ist aber recht einfach.

    Die Signatur sieht so aus:

    VB.NET-Quellcode

    1. Function IndexOfNthContent(Target As String, Content As String, N As Integer) As Integer


    Erstelle eine List(Of Integer). In dieser Liste werden die Indices aller Vorkommen gespeichert (also beim Beispiel oben sind dann 5 Elemente enthalten, die alle einen Index von einem "Hallo"-Vorkommen angeben).

    Du gehst alle Zeichen des Target-Strings durch. Das musst Du mit einer For-Schleife und nicht mit einer For-Each-Schleife machen, weil Du den Index brauchst. Als Zählvariable nehmen wir iT ("i" für die gute alte Zählervariable und "T" für "Target").

    Erstelle eine lokale Variable in dieser Schleife vom Typ Boolean. "SequenceValid" würde mir als Name einfallen. Initialisiere sie mit True.

    In der Schleife gehst (ebenfalls mit einer For-Schleife) Du alle Zeichen des Content-Strings durch (Zählvariable iC).

    Jetzt folgendes: In der inneren Schleife wird folgendes überprüft:

    VB.NET-Quellcode

    1. Target(iT + iC) = Content(iC)

    Mir fällt das etwas schwer zu erklären, deshalb eine Grafik dazu. Graue Kästchen sind noch unbewertet, grüne Kästchen stimmen überein, rote Kästchen stimmen nicht überein.


    Also wenn die beiden Zeichen nicht übereinstimmen, setzt Du SequenceValid auf False und beendest die innere Schleife mit Exit For (weil ein Weiterarbeiten unnötig wäre).

    Nach der inneren Schleife prüfst Du, ob SequenceValid True ist.
    Ist das der Fall, nimmst Du iT in die Liste auf.

    Am Ende der Funktion gibst Du das Element N aus der Liste zurück.


    Das war dann auch schon die Funktion. Du musst halt noch auf Sonderfälle prüfen (gibt es überhaupt ein N-tes Element) und anderes einbauen. z.B. läuft die äußere Schleife nicht bis Target.Count - 1, sondern bis Target.Count - Content.Count, weil wenn nur noch 4 Zeichen vom TargetString übrig sind, der ContentString aber 5 Zeichen lang ist, kann es sowieso nicht mehr passen.


    Edit: Wenn Du ganz lustig gelaunt bist, kannst Du's auch in C# schreiben. Da gibt's unsafe-Methoden, bei denen Du direkt mit Pointern arbeiten kannst. Dadurch hast Du einen enormen Geschwindigkeitsschub. Das ganze in eine Dll ausgelagert und dann kannst Du's in anderen Projekten importieren.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Niko Ortner“ ()

    Function IndexOfNthContent(Target As String, Content As String, N As Integer) As Integer
    Nach n Whiskys versuche ich mal die Funktion aus dem Kopf zu schreiben

    VB.NET-Quellcode

    1. Function IndexOfNthContent(Target As String, Content As String, N As Integer) As Integer
    2. Dim Offset = 0
    3. Dim Idx = 1
    4. For i = 1 to N
    5. Offset = Target.IndexOf(Content, Idx)
    6. If Offset = 0 Then Return 0 Else Idx = Offset + 1
    7. Next
    8. Return Offset
    9. End Function
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    @petaod: Seeehr Spaghetticode-mäßig, aber könnte funktionieren. Nur glaube ich sind die Grenzwerte nicht ganz richtig.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Nüchtern betrachtet, mit richtigen Grenzwerten und einer Spaghetti-Wicklung weniger:

    VB.NET-Quellcode

    1. Function IndexOfNthContent(Target As String, Content As String, Optional n As Integer = 1) As Integer
    2. Dim Offset = -1, Idx = 0
    3. For i = 1 To n
    4. Offset = Target.IndexOf(Content, Idx)
    5. If Offset >= 0 Then Idx = Offset + Content.Length Else Exit For
    6. Next
    7. Return Offset
    8. End Function


    Edit2:
    Das Verfahren geht auch mit Suche von hinten (negatives n sucht das n-te Vorkommen von hinten)

    VB.NET-Quellcode

    1. Function IndexOfNthContent(Target As String, Content As String, Optional n As Integer = 1) As Integer
    2. Dim Offset = -1
    3. Dim Idx = If(n > 0, 0, Target.Length)
    4. For i = 1 To Math.Abs(n)
    5. Offset = If(n > 0, Target.IndexOf(Content, Idx), Target.LastIndexOf(Content, Idx))
    6. If Offset >= 0 Then Idx = Offset + If(n > 0, Content.Length, 0) Else Exit For
    7. Next
    8. Return Offset
    9. End Function
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „petaod“ ()

    Hey.

    Warum so komplitziert?


    VB.NET-Quellcode

    1. Private Sub ColorWord(Word As String, Rtb As RichTextBox, indx As Short)
    2. If Word.length = 0 OrElse Rtb is Nothing then Exit Sub
    3. Dim Words As MatchCollection = Regex.Matches(Rtb.Text, String.Concat("(", Word, ")"))
    4. If indx >= Words.Count then Exit Sub
    5. Rtb.SelectionFont = New Font("Calibri", 10, FontStyle.Bold) 'Kannst Du auch alles anpassen noch
    6. Rtb.SelectionStart = Words(indx).Index
    7. Rtb.SelectionLength = Words(indx).Groups(1).Value.Length
    8. Rtb.SelectionColor = Color.FromArgb(255, 0, 0) 'Rot, kanst Du ja selbst ändern.
    9. End Sub



    Du musst eine RichTextbox nutzen.

    Aufrufbeispiel:


    VB.NET-Quellcode

    1. ColorWord("Hallo", RichTextBox1, 0)


    Alle Zeichenfolgen "Hallo" werden gefunden in der RichTextBox1.

    Der dritte Parameter vom Datentyp Short gibt an welches Hallo Du haben willst(0 steht für das erste,
    da arraybasierte Zählung).


    9 Codezeilen gerade mal.


    Have fun :)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Kevin Hombre“ ()

    @Kevin Hombre:, @petaod:, @Niko Ortner: Wow danke erstmal für die vielen Beiträge. Ich werd am besten mal erst alles durchprobieren :D
    Edit: Also die IndexOfNthTarget Funktion funktioniert soweit ganz gut, allerdings wird -1 ausgeben. Vielleicht hätte ich dazu sagen sollen das das als Hexadezimal eingelesen werden muss. Kann man da was machen?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Xylon“ ()

    @Xylon: Was meinst Du mit Hexadezimal?
    Steht in der TextBox dann sowas wie

    Quellcode

    1. 93 45 E1 CF 49 0F 3A

    und Du möchtest dann die Hexadezimalwerte von "Hallo" finden?
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    @Niko Ortner:, @timmi31061: Nee aber irgendwie wird mir manchmal kein Wert angezeigt. Der String ist schon in Hex. Und wenn mit der Funktion ein Wert gefunden wird wo Buchstaben drin sind bekomme ich keinen Wert, sonst schon. Das nehme ich jedenfalls an. Vielleicht hilft es wenn ich mal das Projekt hochlade.
    mediafire.com/?2hocjzg5kp4xqp5

    Das Programm liest binäre Dateien und gibts sie in Hex aus. Ich habe schon einen Zähler wie oft der Wert der in TextBox1 eingegeben wird, die Position der Adresse in tb1, den Wert in der rtb der untergeordneten Adresse und eben diese Funktion zum Suchen. In der TextBox1 werden hexadezimale codes eingegeben wie z.B.
    04000024 00000001
    In der binären Datei sind immer solche 32bit Werte(Die Adresse ist das links, der Wert rechts). Hier würde dann der Wert 00000001 gesucht werden. Dann habe ich den Zähler der mir angibt wo der Wert dann in der 2. rtb ist.
    Ja ich weiß, ziemlich kompliziert...
    @timmi31061:: Bitte lass dem Threadersteller selber die Möglichkeit, sein Problem verständlich zu machen.
    Überlegungen, wasser gemeint haben könnte verkomplizieren die Diskussion und lähmen des Threaderstellers Eigeninitiative.

    Ein Problem hinreichend zu präzisieren ist oft 3/4 der Lösung.

    Edit: Ups - viieel zu spät!
    @Xylon: Bitte hänge dann auch an, was das Problem war und wie Du es gelöst hast. Dann hat die Nachwelt auch was davon ;)
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils