String manipulation HELP!!!!!

capcom

Member
Joined
Aug 27, 2006
Messages
11
Programming Experience
5-10
Hope someone can help on this one!

What I have is lines of text in a richtextbox which look like this:
N1G01 F10 X0.5 Y0.0625
N2 Z0.02 F10
N3 Z-0.04 F1
N4 Y1.9375 F2.5
N5 X0.4 F5
N6 Y0.0625
N7 X0.6

What I need to do is find and replace the number right after the X. My problem has been that the number right after the X is not always the same length. Does anyone have an answer for this?

Thank You

Capcom
 
Things are looking good now, I redid it and it replaces everything it should!
But I just noticed a problem. Please run this section of my data through yours and look at the very last X on line N248 which is X0.9375. Now take that times 25.4 it should be 23.8125 but I get 22.86375. Now 25.4 * .9 is 22.86375. I am stumped on that one. It looks like it is only using the .9


N209 X0.1 F5
N210 Y0.0625
N211 X0.9
N212 Y1.9375
N213 X0.0625 F5
N214 Y0.0625
N215 X0.9375
N216 Y1.9375
N217 X0.5 F20
N218 Y0.0625
N219 Z-0.375 F1
N220 Y1.9375 F2.5
N221 X0.4 F5
N222 Y0.0625
N223 X0.6
N224 Y1.9375
N225 X0.3 F5
N226 Y0.0625
N227 X0.7
N228 Y1.9375
N229 X0.2 F5
N230 Y0.0625
N231 X0.8
N232 Y1.9375
N233 X0.1 F5
N234 Y0.0625
N235 X0.9
N236 Y1.9375
N237 X0.0625 F5
N238 Y0.0625
N239 X0.9375
N240 Y1.9375
N241 X0.5 F20
N242 Y0.0625
N243F5 Y0.0625
N244 Y0.0625 X0.9375
N245 Y1.9375
N246 X0.0625
N247 Y0.0625
N248 X0.9375
N249Z0.1
N250M02



Gary
 
You are right...this is weird... I am checking it out though.

edit: You know what is weird? If you only put the last few lines in the code it will show the correct number. Once you put this big list it doesnt work. I debugged my function and everything the listbox and it shows the correct answer on the debug but not on the rich text box. Very weird!

edit 2: After looking at it a bit more I tried to slowly convert parts of this big file you have. I noticed that if there is a X0.9 value first then it screws up. It is very weird as everything on my listbox shows perfectly!

VB.NET:
[B]-----------[COLOR=Red]Does NOT work if you add these 3 lines[/COLOR]----------[/B]
N234 Y0.0625
N235 X0.9 <--- Change this to X0.7 for example and it works!
N236 Y1.9375
[B]-----------works here and below----------[/B]
N237 X0.0625 F5
N238 Y0.0625
N239 X0.9375 
N240 Y1.9375
N241 X0.5 F20
N242 Y0.0625
N243F5 Y0.0625
N244 Y0.0625 X0.9375 
N245 Y1.9375
N246 X0.0625 
N247 Y0.0625
N248 X0.9375 
N249Z0.1
N250M02

Anyone can help?
 

Attachments

  • weirdo.JPG
    weirdo.JPG
    28.2 KB · Views: 80
Last edited:
another thing I noticed was if you add a 0 behind the .90 it will do it correctly. I am still stumped as to why this is.

Gary
 
Capcom, I think it has to do something with the replace function that actually makes the change.

If you do a MsgBox(str) which is the new string that is being built with the changed values it still shows the incorrect value.

I've looked through it but I am unable to find solution as of now.
 
Interesting thread!! I've just had a go using Regex.Replace and the early results look good although, writing regular expressions is a pain. I should have a working solution which i'll post later today.
 
Well, to be fair, you are asking VB to make guesses and implicit conversions between strings and doubles.. Turn Option Strict on in your project preferences to see a highlight of potential problems.

Here is a commented chunk of code of how to do this with regular expressions, it works correctly and does not suffer the bug you indicated:

VB.NET:
Imports System.Text.RegularExpressions
 
Public Class Form1
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
 
        'regex here matches an X followed by a number in possibly decimal format
        'the number part is surrounded by brackets so the matcher pulls it out as a captured group
        Dim decimalPattern As New Regex("X([0-9]+[.]{0,1}[0-9]*)")
        Dim potentialReplaces As MatchCollection
        Dim xNumber As Double
 
 
        Dim fromInchesToMM As Boolean = True
 
        Dim line As String
        Dim lines As String() = RichTextBox1.Lines
        For lineNumber As Integer = 0 To lines.Length - 1
 
            line = RichTextBox1.Lines(lineNumber)
 
            'search the line for all substrings that match the pattern
            potentialReplaces = decimalPattern.Matches(line)
 
            'if theres something we need to replace
            If potentialReplaces.Count > 0 Then
 
                'if the line contains multiple X numbers then we can process each of them
                For Each regexMatch As Match In potentialReplaces
 
                    'try to parse the number into a double. the Groups() indexer
                    'is 1 because Groups(0) is always the entire matched string
                    'e.g Groups(0) is X0.1, Groups(1) is 0.1
                    If Not Double.TryParse(regexMatch.Groups(1).ToString(), xNumber) Then
                        MessageBox.Show("Failed to convert this to a double:" & regexMatch.Captures(0).ToString())
                        Continue For
                    End If
 
                    'now xNumber is the value we want, convert it
                    If fromInchesToMM Then
                        xNumber = xNumber * 25.4
                    Else
                        xNumber = xNumber / 25.4
                    End If
 
                    'replace the old text with the new
                    line = line.Replace(regexMatch.ToString(), "X" & xNumber)
 
                Next
 
                'put the line back into the array
                lines(lineNumber) = line
            End If
        Next
 
        'put the array into the textbox
        RichTextBox1.Lines = lines
    End Sub
End Class
 
cjard,

Excellent solution provided and thanks because I am starting to see that RegExpressions are a hot topic in .NET. However, would it be more or less efficient than my solution when it comes to very large files? I am actually asking not implying anything.

I was digging through to find out and I tried all sorts of conversions only to see VB.NET did not do it right for me! Still though it would be nice to see the fix in my solution, if there is any?
 
cjard,

I tried that, but this part of the code won't work in my version of VB.net wich is 2002.

VB.NET:
If Not Double.TryParse(regexMatch.Groups(1).ToString(), xNumber) Then
  MessageBox.Show("Failed to convert this to a double:" & regexMatch.Captures(0).ToString())
  Continue For
End If
Gary
 
Capcom: As you can see by your message headers:

capcom
user_offline.gif

VB.NET Forum Newbie
Primary Platform: .NET 2.0 (VS 2005)


you have told us you are using VS2005, not 2002. Please go into your control panel on this forum, and correct the preferences that show which version of .NET youre using.


VS 2002 has no Double.TryParse() method. I'm not sure what the equivalent is, even though it was recently discussed in a thread to which I participated on this forum.
Hold on a moment while I take a look for that thread. If someone else knows, in the meanwhile, the Double.TryParse equivalent (it's wordy, i recall) of VS2002, then please post it

*Update:
Sorry, I've so far failed to recover the post. I cant find any info on .NET 1.0 on the web either. As a basic way of solving I recommend you press F2 to bring up the object browser, and search for PARSE. You might find that you have Double.Parse available, or something.
Also, look to see if you have Convert.ToDouble() available.

Both these methods throw exceptions so the code would look more like:

VB.NET:
[LEFT]Try 
  ' method that throws eception e.g. Double.Parse(regexMatch.Groups(1).ToString(), xNumber) 
Catch Exception
  MessageBox.Show("Failed to convert this to a double:" & regexMatch.Captures(0).ToString())
  Continue For
End Try

Good Luck!

PS: VS2005 is now available free (VB Express) from microsoft's downloads page - it has some limits, like inability to connect to non-MS databases but you can take a look at it (and it's very nice! :) )[/LEFT]
 
Last edited:
cjard,

Excellent solution provided and thanks because I am starting to see that RegExpressions are a hot topic in .NET. However, would it be more or less efficient than my solution when it comes to very large files? I am actually asking not implying anything.

I was digging through to find out and I tried all sorts of conversions only to see VB.NET did not do it right for me! Still though it would be nice to see the fix in my solution, if there is any?

I will assess the problem with your code if you can post or PM the project!

RegularExpressions are a tradeoff; i dont doubt one could write a slightly faster routine without them, but the power they offer in this case would outweigh the cost. Also, it should be considered that this routine is intense in its string handling. The greatest improvements could be made there first. The fastest routine I could think of would be to crawl the string one character at a time, using X and <white space> as delimiters, and toggling between text-copying and number parsing modes. It doesnt cope with weird input quite as well as the regex, IMHO and would be a complex thing to look at
 
You can look at reply #13 to see all my code for this project.

I would like to agree on the fact that regExpressions just make it easier for this case!

Thanks again and I really just wanted to know why my code does this...Reply #17 actually shows whats happening and I think capcom posted some other info a bit further below.
 
I have reviewed your code and I seriously recommend you do not follow this course of action:

str = str.Replace(arr(i), "X" & <converted number>)


you see, you search and replace the entire original string and hope it will change just the instances you want to deal with.

Consider the situation where you have the following X values in succession:

X0.036
X0.9

The first X is converted from 0.036 to 0.9144, you find 0.036 and replace it with 0.9144. Your file now looks like:

X0.9144
X0.9

Then when processing the second X, you determine that 0.9 should be replaced by 22.86. Your file now looks like:

X22.86144
X22.86


What actually happens in your case is a related condition. The code encounters X0.9 and causes all values in the file to become X22.86, so the later values of X0.9375 become X22.86375. They are subsequently not subject to replacement because Find:X0.9375/Replace:X23.8125 fails to find any occurrences
-

Your algorithm would be better off splitting the string into an array then altering the individual array elements, then rejoining them. Additionally, your algorithm relies on spaces to delimit all the values. Given that is cannot be guaranteed that a space will precede every newline i do not recommend you persist with space as [the only] delimiter


I offer some other comments on your code:

Your functions and subs do not have access specifiers (public/protected/private etc). You should endeavour to learn the differences and use them appropriately

Your code relies on implicit conversions permitted when Option Strict is off, but some people feel that Option Strict Off promotes sloppy programming and increases the risk of software bugs developing. Though a personal decision, there is more to be gained from following a stricter and more specific mindset when programming, particularly with migration to other languages. To enable Option Strict, set the appropriate combo box in the project's compilation properties

The code makes inconsistent use of .NETcore and MS.VB compatibility methods; you say string.Replace, but Split(string). Again, largely the opinion of the individual, some people feel that using the provided compatibility methods is a cling to legacy VB and should be discarded if the individual wishes to progress to other .NET syntaxes such as C# or future revisions of VB where the legacy code is deprecated, or indeed if the goal is simply to more accurately embrace the OO underpinnings of any .NET syntax.
You can have the compiler assist you with this if you choose; in a project references, remove the reference to Microsoft.VisualBasic.dll and legacy syntax becomes a compiler error.
Note; there are some features provided by the legacy libraries that may not be present in .NET core. One example I can think of is reading of CSV files; I use a third party library rather than the readers in Microsoft.VisualBasic because I first had the need to read CSV when working in C#

All in, a good and creative solution for the problem, simpler to look at than my regex offering and more compatible with very early versions of the framework! Well done :)
 
Last edited:
cjard,

Your explanation was more than enough and I completely understand the problem that my solution faces.

Regarding Option Strict On, I will have to agree again that I must start using it further more in my projects and ensure that it is on.

As for private, public or protected functions do not worry, I have been using them it is just that this was a quick code that would answer the specific question hence the sloppiness of my declarations even for the variable names!

Thanks though, I understand completely now why my code fails to deliver an 100% answer. The array solution should fix everything.
 
You are indeed most welcome; many times in my organisation the developers call each other to review code that does not function. Sometimes in explaining the purpose of the code, the developer realises the mistake. Other times, the fresh pair of eyes is able to spot the problem that the tired mind has grown weary of looking at.. If the guys at work knew what .NET was, i'd use them for most my inane problems.. as it is, I bend ears here :D
 
Back
Top