Recent

Author Topic: Copy function and string manulipation  (Read 8884 times)

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Copy function and string manulipation
« on: February 20, 2018, 12:40:29 am »
Code: Pascal  [Select][+][-]
  1. function GetExtenion(S : String) : String;
  2. Var
  3.   LeftChar : Integer;
  4.   RightChar : Integer;
  5.   Extention : String;
  6. Begin
  7.   Result := '';
  8.   LeftChar := Pos('(',S);
  9.   RightChar := Pos(')',S);
  10.   If LeftChar > 0
  11.         then Begin
  12.          If RightChar > 0 then begin
  13.             Extension := copy(S,LeftChar,RightChar);
  14.             Result := Extension;
  15.             Exit;
  16.          End;
  17.   end;
  18. end;    

Making the following call to this function - Ext := GetExtention(Line);

Line = The Plane1 line and extention is at position 48 to 50. Looking for return of fms
but the function returns "(fms)    {X-Plane}        [\Output\FMS plans\] after the call"

 Can't see the mistake in coding.
          123456789012345678901234567890123456789012345678901234567890123456789012345
Line = Plane1=*SSGB747-800i                          (fms)    {X-Plane}        [\Output\FMS plans\]
« Last Edit: February 20, 2018, 12:42:04 am by JLWest »
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Copy function and string manulipation
« Reply #1 on: February 20, 2018, 12:58:52 am »
Just to make sure: that function should return "(fms)" for you ?

function copy's 3th parameter is the count of characters to copy, not the end-point (which pos returned for variable RightChar).
« Last Edit: February 20, 2018, 01:02:12 am by molly »

Josh

  • Hero Member
  • *****
  • Posts: 1274
Re: Copy function and string manulipation
« Reply #2 on: February 20, 2018, 01:08:01 am »
Hi

The 3rd parameter of the copy command is how many characters you wish to copy
the start position is the position of the '(' character, so I would assume you would want to copy from this location+1

ie
Code: Pascal  [Select][+][-]
  1. function GetExtenion(S : String) : String;
  2. Var
  3.   LeftChar : Integer;
  4.   RightChar : Integer;
  5. Begin
  6.   Result := '';
  7.   LeftChar := Pos('(',S);
  8.   RightChar := Pos(')',S);
  9.   if ((leftchar=0) or (rightchar=0)) then exit;
  10.   inc(leftchar); // increment by one to ignore the (
  11.   rightchar:=rightchar-leftchar;// this should give the count for the copy command
  12.   Result := copy(S,LeftChar,RightChar);
  13. end;    
  14.  

I have not tested it, but hopefully should be ok; I could have written it more concise; but kept same variable names and same flow idea.

Oops Molly already gave you same info.


Additional, you could increase the functionality so that it can search for other delimeters ie
Code: Pascal  [Select][+][-]
  1. function GetExt(S : String;AFind,BFind:String) : String;
  2. Var
  3.   LeftChar : Integer;
  4.   RightChar : Integer;
  5. Begin
  6.   Result := '';
  7.   LeftChar := Pos(AFind,S);
  8.   RightChar := Pos(BFind,S);
  9.   if ((leftchar=0) or (rightchar=0)) then exit;
  10.   inc(leftchar); // increment by one to ignore the AFind
  11.   rightchar:=rightchar-leftchar;// this should give the count for the copy command
  12.   Result := copy(S,LeftChar,RightChar);
  13. end;    
  14.  

tested with following on a form with 3 labels and a button
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. Var s:string='Plane1=*SSGB747-800i                          (fms)    {X-Plane}        [\Output\FMS plans\]';
  3. begin
  4.   Label1.caption:=GetExt(S,'(',')');
  5.   Label2.caption:=GetExt(S,'{','}');
  6.   Label3.caption:=GetExt(S,'[',']');
  7. end;    
  8.  

Results in
fms
X-Plane
\Output\FMS plans\
« Last Edit: February 20, 2018, 01:44:18 am by josh »
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: Copy function and string manulipation
« Reply #3 on: February 20, 2018, 01:27:52 am »
Yea all I want returned is 'fms' but it was the number of characters to copy I had wrong not the end position of the copy.

Got it now, Thanks.
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Copy function and string manulipation
« Reply #4 on: February 20, 2018, 01:30:36 am »
@josh:
in your defense, you had to take more time to come up with some code while i was lazy  :)

@JLWest:
Great !

I know, it can be confusing and can make your head spin. Josh provided some extra details on how to 'exclude' the brackets from your result.

Josh

  • Hero Member
  • *****
  • Posts: 1274
Re: Copy function and string manulipation
« Reply #5 on: February 20, 2018, 01:40:18 am »
@JLWest Just expanded my post; with some additional info you may find handy.

@Molly I was waiting for kettle to boil for a cup of coffee :)
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Copy function and string manulipation
« Reply #6 on: February 20, 2018, 01:49:47 am »
@JLWest:
BTW: if this is still about parsing the 'flight' information then i would advise to use single or double quotes around your fields (for every individual field), assuming that none of your fields include those.

In you would then then separate your fields with whitespace (tab, space etc) then you can use function extractword, which in the end is much easier to handle.

e.g.:
Plane1="*"  "SSGB747-800i"                          "fms"    "X-Plane"        "\Output\FMS plans\"
Plane2="*"  "SSGB747-800i"                          ""    "X-Plane"        "\Output\FMS plans\"

Code: Pascal  [Select][+][-]
  1. Line := .. copy a single line from your file
  2.  
  3. // You can check if a line contains all fields with:
  4. if WordCount(Line, [' ']) = 5 then ...
  5.  
  6.  
  7. // extract status:
  8. status := extractword(1, Line, [' ']);  // the set [' '] can be extended to also contain other whitespace characters.
  9. status := AnsiDequotedStr(status, '"');
  10.  
  11. // extract number:
  12. number := extractword(2, Line, [' ']);
  13. number := AnsiDequotedStr(number, '"');
  14.  
  15. // extract fms:
  16. fms := extractword(3, Line, [' ']);
  17. fms := AnsiDequotedStr(fms, '"');
  18.  
  19. // extract planetype
  20. planetype := extractword(4, Line, [' ']);
  21. planetype := AnsiDequotedStr(planetype, '"');
  22.  
  23. // extract location
  24. location := extractword(4, Line, [' ']);
  25. location := AnsiDequotedStr(location, '"');
  26.  
  27. // you can then check if a field actually contains data by checking if its empty or not
  28. if location = '' then writeln('location was empty') else writeln('location contains data');
  29.  

Much easier imho  :)
« Last Edit: February 20, 2018, 01:54:41 am by molly »

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: Copy function and string manulipation
« Reply #7 on: February 20, 2018, 07:01:44 am »
Wow Elegant code writer.

I have it working. Not the most concise, but I'm a beginner at this.
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: Copy function and string manulipation
« Reply #8 on: February 20, 2018, 07:19:55 am »
Really Elegant.

Could replace 4 functions I wrote to extract 5 different fields.
And very easy to read and understand

To bad that Free Pascal and Lazarus don't have examples like this instead of the dry hum drum Writeln, (OOPS forgot Readln() so I thought nothing happend) to a dos box.

You guys should get to gather and do some examples.  I would suggest the following:

Creating a text file.
Writing and reading from a text file.    <----- if your learning pascal every Programmer need this.

INI file processing.

Loading Listboxes from a file, ini file and directory.

How to do two form programs.               <------------------Took forever for me to learn.

How to do a unit and include it in a project.

Well maybe it's just me, hardes't 3 years of my life was third grade.

Where to put a unit in uses clauses.

And DON'T DO HELLO WORLD                <-------------------Worthless.
 
Well maybe it's just me.


Hardest 3 years of my life was 3 grade.
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Copy function and string manulipation
« Reply #9 on: February 20, 2018, 08:09:06 am »
Code: Text  [Select][+][-]
  1. program examples;
  2.  
  3. {$MODE OBJFPC}{$H+}
  4. {$APPTYPE CONSOLE}
  5.  
  6. uses
  7.   classes, IniFiles;
  8.  
  9. // see also: http://wiki.freepascal.org/TStringList-TStrings_Tutorial
  10. procedure TextFiles;
  11. var
  12.   SomeTextLines: TStringList;
  13.   Line : String;
  14. begin
  15.   // Add some lines and save to a file
  16.   SomeTextLines := TStringList.Create;
  17.   SomeTextLines.Append('Hello');
  18.   SomeTextLines.Append('world');
  19.   SomeTextLines.SaveToFile('testfile.dat');
  20.   SomeTextLines.Free;
  21.  
  22.   // Load some lines from file and write
  23.   SomeTextLines := TStringList.Create;
  24.   SomeTextLines.LoadFromFile('testfile.dat');
  25.   for Line in SomeTextLines
  26.     do WriteLn(Line);  
  27.   SomeTextLines.Free;
  28. end;
  29.  
  30. // see also: http://wiki.freepascal.org/Using_INI_Files
  31. procedure IniFiles;
  32. var
  33.   MemIni: TMemIniFile;
  34.   String_Value: String;
  35.   Boolean_Value : Boolean;
  36.   Integer_Value : Integer;
  37. begin
  38.   // Create ini file
  39.   MemIni := TMemIniFile.Create('testfile.ini');
  40.   MemIni.WriteString('Section_Name', 'Identifier', 'value');
  41.   MemIni.WriteBool('Another_Section', 'Boolean_Identifier', True);
  42.   MemIni.WriteInteger('Another_Section', 'Integer_Identifier', 1234);
  43.   MemIni.Free;
  44.  
  45.   // read/parse ini  
  46.   MemIni := TMemIniFile.Create('testfile.ini');
  47.   MemIni.ReadString('Section_Name', 'Identifier', 'default_value_in_case_not_present_inside_inifile');
  48.   Boolean_value := MemIni.ReadBool('Another_Section', 'Boolean_Identifier', false);
  49.   Integer_Value := MemIni.ReadInteger('Another_Section', 'Integer_Identifier', -1);
  50.   WriteLn('integer_value = ', Integer_Value);
  51.   if MemIni.ValueExists('Some_Section', 'Some_Identifier')
  52.     then WriteLn('Section "Some_Section" contains identifier "Some_identifier"')
  53.   else WriteLn('Section "Some_Section" and/or identifier "Some_identifier" does not exist');
  54.   // add  new entry andcheck again
  55.   memIni.WriteString('Some_Section', 'Some_Identifier', 'now it does exist');
  56.   if MemIni.ValueExists('Some_Section', 'Some_Identifier') then
  57.   begin
  58.     WriteLn('Section "Some_Section" contains identifier "Some_identifier"');
  59.     WriteLn('The contents is :', memIni.ReadString('Some_Section', 'Some_Identifier', 'Oops somthing went wrong'));
  60.   end
  61.   else WriteLn('Section "Some_Section" and/or identifier "Some_identifier" does not exist');
  62.   MemIni.Free;
  63. end;
  64.  
  65. begin
  66.   TextFiles;
  67.   IniFiles;  
  68. end.
  69.  

Perhaps it is more profitable to check the wiki and/or apply some google-voodo  ;D. Plenty of examples/tutorials around.

A TListBox also contains TStrings (items property), so you can directly populate a ListBox from a stringlist. see also wiki. Even more directly: ListBox.Items.LoadFromFile('filename,txt') should be sufficient. (and ListBox.Items.SaveToFile('filename.txt') to save the contents)

Parsing a inifile to a listbox can be a bit more tricky, and depends on what you want to store where exactly. You can for example load a complete ini section with some simlpe steps if wanted. But if you require several identifier values across several section then it is manual labour.

More information on units in wiki

I take it you are able to find how to create two forms (also available on the wiki). google-foo  :)

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Copy function and string manulipation
« Reply #10 on: February 20, 2018, 09:09:49 am »
Why are you inventing the wheel? See https://www.freepascal.org/docs-html/rtl/sysutils/extractfileext.html There is already a tried and tested standard function for that!

It is usually a good exercise to try and write it yourself, but there are some intricacies involved that may not seem directly obvious.
Better to use sysutils.ExtractFileExt.
« Last Edit: February 20, 2018, 09:12:47 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

 

TinyPortal © 2005-2018