Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Extract letters and numbers from a string.

Status
Not open for further replies.

andjem1

Technical User
Jul 16, 2007
16
GB
Hi
I want to write a program to convert CNC GCode files.
My problem is this;
From the following code; N230G01X78.54Y34.75f300.
I need to extract the letter X and the numbers 78.54, change X to B, perform a calculation and then pass back to the origional string.
To get this; N230G01B90.0Y34.75f300.

While the code I wrote below works fine, the value of X may not be followed by a Y value (which I am using to mark the end of the X value) or any other value and the numbers are not always the same length. eg.
N230G01X674.887f300.
N230G01X4.3

So, is there a way to extract the numbers after X or search for either 'Y' or 'F' or 'D' or 'H' or ''
I have tried to use sets without sucsess.

I'm a raw beginer using Turbo Delphi and any help will be very much appreciated. Thanks.



Code:
procedure TForm2.Button1Click(Sender: TObject);

Var
  source, target, Numbers, Newaxis, NewBlock : string;
  Xposition, EndPosition, Length : integer;
  Angle, Radius, FormatedAngle : Double;

begin
      edit1.Text:= ansiuppercase(edit1.Text); //Change text in edit1 to uppercase.
      source := edit1.Text;  //Variable 'Source' gets edit1.text

      //Variable 'Radius' gets edit2.text converted from a string to floating point number.
      Radius := strtofloat(edit2.text);

      //look for position of 'X' in 'Source'. Stores position as Integer in variable Xposition.
      Xposition:= ansipos('X',source);

   //*************************************************************************
      //My problem is here 
        //finds 'Y' position.
        //Would like to find 'Y' or 'F' or ''.
        //Alternativly, find 'Y' and number after.

        Endposition:= ansipos('Y', source);

   //*************************************************************************

      //Subtract X position from Y position to find length of target string.
      Length := (Endposition - Xposition);
      //Extract target string.
      Target:= ansimidstr(source, Xposition, Length);

      Numbers := ansimidstr(target,2,8); //Extract the numbers

          //Angle = numbers*180/Pi/Radius
          //Calculate Angle.
          Angle := strtofloat(Numbers)*180/Pi/(Radius);
          //Format angle to 3 decimal places.
          FormatedAngle := strtofloat(Format('%.3f', [Angle]));

              //Check to see if formated angle conains a decimal point.
              if AnsiContainsStr(FloatToStr(FormatedAngle), '.')
                then
                    //If yes, then add 'B' before angle
                    NewAxis := Concat('B' + FloatToStr(FormatedAngle))
                else
                    //If No, then add 'B' before angle and a decmal point and '0' after.
                    NewAxis := Concat('B' + FloatToStr(FormatedAngle) + '.0');

          //Replace target from old block with Newaxis.
          NewBlock := AnsiReplaceStr(source,(Target), (NewAxis));

       if
          Xposition=0
          then
            showmessage('X not found')
            else
            //Display variables at diferent stages in labels.
            Label1.Caption:=('Target ='+' ' +(target));
            Label2.Caption:=('Extract Numbers ='+' ' +(numbers));
            Label3.Caption:=('Value of Pi ='+' '+FloatToStr(Pi));
            Label4.Caption:=('4th axis Angle ='+' ' +floattostr(angle));
            Label6.Caption:=('Formated Angle ='+' ' +floattostr(FormatedAngle));
            Label7.Caption:=('New Axis ='+' '+(NewAxis));
            Label8.Caption:=(NewBlock);
 end;
 
try to think out of the box:

find 'X' and then look for any character that fits in this set (until the end of the string)

a valid set is ['0'..'9', '.']
so whatever that's after 'X', it must fall into this set and belongs to X.

I hope this is clear to you, if I have some more time I will make you a code sample.

Cheers,
Daddy



-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
I'm just not seeing this at all. I sort of get the idea of using sets but the more i try the worse it gets.
Here's my latest failure.
Every attempt yields yet more Incompatible types errors.
In need of some real help here to get over this mental block. Thanks.

Code:
procedure TForm2.Button1Click(Sender: TObject);
var
   Source : String;
   Numbers : String;
   Xposition, Target: integer;
begin
    Source := 'N8870G01X23.87Y34.556F300.';
    Numbers := ['0'..'9','.'];
    Xposition := ansipos(Source, 'X');

       Target:= ansimidstr(Source, Xposition, Numbers);
       Label1.Caption:=(Target);
end;
 
ok let's see what we can do:

(untested)
Code:
...
uses SysUtils;
...
function ExtractNumberFromString(Str : string; Var Number : Extended) : String;

var Index : Integer
    Ch : Char; 
    StrLen : Integer; 
    NumStr : string; 
begin
 Result := '';
 Number := 0;
 StrLen := Length(Str);
 if StrLen = 0 then Exit; // Sanity Check
 Index := 0;
 NumStr := ''; 
 repeat
  Inc(Index);
  Ch := Str[Index];
  case Ch of // valid char
   '0'..'9','.' : NumStr := NumStr + Ch;
  end
  else 
   begin
    Result := Copy(Str, Index, MaxInt); // function returns the rest of the string
    Index := MaxInt; // we are done here
   end;
 until Index => StrLen;
 if NumStr <> '' then
  Number := StrToFloat(NumStr); 
end;

call function like this :

Code:
procedure TForm2.Button1Click(Sender: TObject);
var
   Source : String;
   Xposition: integer;
   XValue : Extended;
   WorkStr : string;
begin
    Source := 'N8870G01X23.87Y34.556F300.';
    Numbers := ['0'..'9','.'];
    Xposition := ansipos(Source, 'X');
    WorkStr := copy(Source, XPosition+1, Maxint);
    // Workstr contains '23.87Y34.556F300.'
    WorkStr := ExtractNumberFromString(WorkStr, XValue);
    // WorkStr contains 'Y34.556F300.', XValue contains 23.87
   // process WorkStr and merge it with source
   ...
end;

I hope this example is clears things up.
Im sure there are better ways to write the extract routine but I wanted to keep it as simple as possible so you won't be confused, I leave you to optimize it :)

Cheers,
Daddy


[cheers]


-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Thanks for your time with this.[smile] Won't compile for me as is, but I've now got a direction to follow.
I'll need to spend some time to try and get my head around this.[dazed]
 
sorry for that, this one should compile:

Code:
function ExtractNumberFromString(Str : string; Var Number : Extended) : String;

var Index : Integer;
    Ch : Char;
    StrLen : Integer;
    NumStr : string;
begin
 Result := '';
 Number := 0;
 StrLen := Length(Str);
 if StrLen = 0 then Exit; // Sanity Check
 Index := 0;
 NumStr := '';
 repeat
  Inc(Index);
  Ch := Str[Index];
  case Ch of // valid char
   '0'..'9','.' : NumStr := NumStr + Ch;

  else
   begin
    Result := Copy(Str, Index, MaxInt); // function returns the rest of the string
    Index := MaxInt; // we are done here
   end;
  end;
 until Index >= StrLen;
 if NumStr <> '' then
  Number := StrToFloat(NumStr);
end;

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Thanks again. This is going to open up a few more possibilities for some ideas I would like to incoporate.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top