This content is provided AS IS for archive purposes only. Content may be out of date with no guarantee of correctness.

Extract Coordinates from a String - Manuals

Main Article

Extract Coordinates from a String

Given a string such as "123,456 27.5,-50 500.0,-500.0", I needed to extract the coordinate point-pairs. I wrote a simple parser to do this. This solution is more stable, robust and maintainable than an uglier brute-force method.

This code is for the Cobra programming language, however it should be easy to port to your language of choice.

Program

Var
   parseSvgPoints_index0: Integer
   parseSvgPoints_index1: Integer
   parseSvgPoints_string: String
   parseSvgPoints_strlen: Integer
   parseSvgPoints_lexeme: String

Function ParseSvgPoints(s: String) : Boolean
Var

   i: Integer
   c: String
   token: Integer
   active: Integer
   point1, point2: Real
Begin


   InitSvgPointsToken(s)
   active = -1

   Repeat
       token = GetNextSvgPointsToken()
       
       Case token of
            1: // Comma
               Case active of
                   -1: // Error (fail silently)
                    1: active=2
                    2: // Error (fail silently)
               EndCase
           
            2: // Float
               Case active of
                   -1: active = 1; point1 = ToReal(parseSvgPoints_lexeme)
                    1: // Error (fail silently)
                    2: active=-1; point2 = ToReal(parseSvgPoints_lexeme);
                       MessageBox("Points: "+point1+", "+point2)
                       // Do things with your points here!
               EndCase
           
           -1:
       EndCase
   
   Until
token = -1
       
End

Function InitSvgPointsToken(s: String) : Boolean
Begin

   parseSvgPoints_index0 = 0
   parseSvgPoints_index1 = 0
   parseSvgPoints_string = s
   parseSvgPoints_strlen = Length(s)
   parseSvgPoints_lexeme = ""
End

Function GetNextSvgPointsToken() : Integer
(*
   Result:
       -1: End of Stream / error
        1: Comma
        2: Float value
*)

Var
   l: Integer
   c: String
Begin


   parseSvgPoints_index0 = parseSvgPoints_index1
   result = -1
   
   // Skip through whitespace
   While (TRUE)                
       c = Mid(parseSvgPoints_string, parseSvgPoints_index0+1, 1)
       If Svg_CharIsWhiteSpace(c) = FALSE then break
       Inc
(parseSvgPoints_index0)
       
       If parseSvgPoints_index0 >= parseSvgPoints_strlen then break
   Wend

   
   parseSvgPoints_index1 = parseSvgPoints_index0
   
   // Scan through until a delimiter is met, incrementing index1    
   While (TRUE)    
       c = Mid(parseSvgPoints_string, parseSvgPoints_index1+1, 1)
       If Svg_CharIsPointsDelim(c) then break
       Inc
(parseSvgPoints_index1)
       
       If parseSvgPoints_index1 >= parseSvgPoints_strlen then break
   Wend
   
   If
(parseSvgPoints_index1 - parseSvgPoints_index0) = 0 then Inc(parseSvgPoints_index1)
   
   // Lexeme Isolatted, lies between index0 and index1       
   parseSvgPoints_lexeme = Mid(parseSvgPoints_string, parseSvgPoints_index0+1, (parseSvgPoints_index1-parseSvgPoints_index0))
   
   result = -1
   
   Conditions
       (parseSvgPoints_lexeme = ','): result = 1
       (Svg_StringIsFloat(parseSvgPoints_lexeme)): result = 2
   EndConditions    
   
End


Function Svg_CharIsPointsDelim(c: String) : Boolean
Begin

   result = FALSE
   If (c = ',') then result = TRUE  ; exit
   result = Svg_CharIsWhitespace(c)  
End

Function Svg_CharIsNumeric(c: String) : Boolean
Var

   a: Integer
Begin

   a = Asc(c)    
   If (a >= 48) and (a <= 57) then result = TRUE else result = FALSE    
End

Function Svg_CharIsWhitespace(c: String) : Boolean
Var

   a: Integer
Begin

   a = Asc(c) // Tab = 9, Space = 32, Newline = 10    
   If (a = 9) or (a = 32) or (a = 10) then result = TRUE else result = FALSE
End

Function Svg_StringIsFloat(s: String) : Boolean ; export
Var

   l, i: Integer
   radix: Integer = 0
   c: String
Begin

   result = FALSE
   l = Length(s)
   If l < 1 then exit
   
   For
i = 1 to l
       c = Mid(s, i, 1)
       
       If Not (Svg_CharIsNumeric(c) or (c = '-') or (c = '.')) then exit
       If
(i <> 1) and (c = '-') then exit
       
       If
(c = '.') then
           Inc
(radix)
           If i = l then exit
       Endif
       If
radix > 1 then exit
   Next

   
   result = TRUE        
End   

Begin
   ParseSvgPoints("123,456 27.5,-50 500.0,-500.0")
End

Stay Subscribed

Follow me on twitter @golightlyb, subscribe to the RSS feed or get updates by e-mail.

You can also contact me directly - I make an effort to reply to every e-mail.


Login
v0.34.archive