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!

Parse String

Status
Not open for further replies.

monxxx

Programmer
May 10, 2009
4
PH
Hi, anybody can help me with my problem? :) i am trying to parse a string and i want this to put into a ComboBox.

the string format that i want to parse is like this:

[TEST]
12345678=abcdef / fhdfkjd|Sample
45464454=fffdfdsfs|Sample
44343232=jrhewrj / dsadasd|Sample
43452355=fdsfsd|Example
53532532=yuyuyiuy|Example
44124444=hfjahfajsfh / hjrhwrqwr|String
41242141=hrjerheerhe|String

i want the Sample, Example, String to be appear in ComboBox1 and if select 'Example' i want the fdsfsd, yuyuyiuy in ComboBox2 the same with if select Sample, String. and the rest i will do like reading INI.

Thanks

BR,
:)

 
Post your parse function code and we'll help you with it.

Roo
Delphi Rules!
 
this is what i did:

var
myFile : TextFile;
text : string;
begin
AssignFile(myFile, ExtractFilePath(Application.ExeName) + 'Providers.ini');
Reset(myFile);

while not Eof(myFile) do
begin
ReadLn(myFile, text);
ComboBox1.AddItem(Parsing('|', text, 2), pointer(0));
end;

if (Parsing('|', text, 2) = Parsing('|', text, 2)) then
begin
ComboBox1.Items.Delete(0);
end;

CloseFile(myFile);

i dont know how to call to backward.
 
function Parsing(Char, Str: string; Count: Integer): string;
var
i : Integer;
strResult : string;
begin
if Str[Length(Str)] <> Char then
Str := Str + Char;
for i := 1 to Count do
begin
strResult := Copy(Str, 0, Pos(Char, Str) - 1);
Str := Copy(Str, Pos(Char, Str) + 1, Length(Str));
end;
Result := strResult;
end;
 
May I recommend a more versatile Parse function:

Code:
[navy][i]// for automatic syntax highlighting see faq102-6487 
[/i][/navy][navy][i]{ Takes a delimited string and returns the n'th field }[/i][/navy]
[b]function[/b] Parse(str: String; delimiter: Char; param_num: Integer): String;
[b]var[/b]
  c, x, y : LongInt;
[b]begin[/b]
  x := [purple]1[/purple];   [navy][i]// param number that we're currently 'in'
[/i][/navy]  y := [purple]0[/purple];   [navy][i]// position of previous delimiter
[/i][/navy]  [b]for[/b] c := [purple]1[/purple] [b]to[/b] Length(str) [b]do[/b]
    [b]if[/b] str[c] = delimiter [b]then[/b]  [navy][i]// this char is a delimiter
[/i][/navy]    [b]begin[/b]
      [b]if[/b] x = param_num [b]then[/b]
        Break;
      inc(x);
      y := c;
    [b]end[/b];
  [b]if[/b] x = param_num [b]then[/b]
    Result := Copy(str, y + [purple]1[/purple], c - y - [purple]1[/purple])
  [b]else[/b]
    Result := [teal]''[/teal];
[b]end[/b];

It allows you to have a string with multiple delimiters and you simply request a particular portion of the string.

Also, are you aware of the TIniFile class? You'll need to add Inifiles to your uses clause. You can retrieve a whole section of your .ini file into a TStringList and go through it that way.

Change your reference of pointer(0) to nil. That's how indicate a null pointer.

I'm not sure what you're trying to do with this bit:
Code:
[b]if[/b] (Parsing([teal]'|'[/teal], text, [purple]2[/purple]) = Parsing([teal]'|'[/teal], text, [purple]2[/purple])) [b]then[/b]
[b]begin[/b]
  ComboBox1.Items.Delete([purple]0[/purple]);
[b]end[/b];

Can you explain that better?
 
I would ditch the INI file and make this structure in XML.
-> no parsing, do queries via XPath (look here :
sample xml could be:

Code:
<?xml version="1.0" encoding="utf-8"?>
<Test>
 <Items>
  <Item Sample="jnjnjnj" Example="hjjhhj" String ="kknknk">2152151</Item>
  <Item Sample="jferrer" Example="aaahj" String ="knknk">484848</Item>
 </Items>
</Test>

my 2 ç

/Daddy

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
the file i was trying to load is like this:

[Providers]
00101000=ALL Operator|-
20201000=Cosmote|Greece
20205000=Vodafone / Panafon|Greece
20209000=Q-Telecom|Greece
20210000=Telestet / TIM|Greece
20404000=Vodafone / Libertel|Netherlands
20408000=KPN Telecom|Netherlands
20412000=Telfort / O2|Netherlands
20416000=T Mobile - Ben |Netherlands
20420000=Dutchtone / Orange|Netherlands
20601000=Belgacom Mobile Proximus|Belgium
20610000=Mobistar|Belgium
20620000=KPN Orange Belgium SA|Belgium
20801000=Orange + France Telecom Itineris|France
20810000=SFR|France
20820000=Bouygues Telecom |France
21303000=S.T.A. MobilAnd|Andorra
21401000=Vodafone / Airtel Movil|Spain

so, in my ComboBox1 there is blank line because '[Providers]' will not be inserted thats why i use ComboBox1.Items.Delete(0); to remove the blank line.
 
Give us a little insight on what form your final output will be in. I don't understand why you are putting these in two separate ComboBoxes. I can only assume you are doing some additional processing with the data after the ComboBoxes are populated. Are they going into some record format? The reason I'm asking is because It would be much more simple to rewrite your parse function to parse out the fields directly into the record, bases on the delimiters, something like this:
Code:
unit Unit14;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TMyRec = record
    fld1: string;
    fld2: string;
    fld3: string;
    fld4: string;
  end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    MyRec: TMyRec;
    MyList: TStringList;
    procedure Process;
    procedure Parse(s: string; var fld1, fld2, fld3, fld4: string);
    procedure SaveRec(MyRec: TMyRec);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.SaveRec(MyRec: TMyRec);
begin
  //do what you need to save the record
end;

procedure TForm1.Parse(s: string; var fld1, fld2, fld3, fld4: string);
const
  Delims: set of char = ['=', '|', '-', '/', '*'];
var
  dummy: string;
  delim: char;
begin
  s:= s + '*'; //add delimiter to the end of the string (see why below)
  while length(s) > 0 do begin
    dummy:= '';
    while (length(s) > 0) and (not (s[1] in Delims)) do begin
      dummy:= dummy + s[1];
      delete(s, 1, 1);
    end;
    Delim:= s[1];
    delete(s, 1, 1);
    case Delim of
      '=': fld1:= dummy;
      '|': fld2:= dummy;
      '-': ; //ignore
      '/': fld3:= dummy;
      '*': fld4:= dummy;  //we need a final delimiter
    end; //case
  end
end;

procedure TForm1.Process;
var i: integer;
begin
  MyList:= TStringList.Create;
  try
    MyList.LoadFromFile('File1.txt');
    if MyList[0] = '[Providers]' then
      for i:= 1 to MyList.Count -1 do
        with MyRec do begin
          fillchar(MyRec, sizeof(MyRec), #0);  //clear all fields
          Parse(MyList[i], fld1, fld2, fld3, fld4);
          SaveRec(MyRec)
        end
    else
      showmessage('unknown header type: ' + MyList[0]);
  finally
    MyList.Free
  end
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Process
end;

end.
Set a break-point on 'SaveData' and you will see the record is populated with your data. The field names are arbitrary, you'll want to make them something more descriptive.

Tested code. Works with D7 under WXP SP3.

Roo
Delphi Rules!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top