0

I have some VB source code and want to convert it to Delphi:

Do While Not EOF(textfile)
Line Input #textfile, Line

Dim retstring() As String         
retstring = Split(Line, Chr(32))
first  = retstring(0)
second = retstring(1)

I have some text file with lines similar to these:

hello all
nice to
good day

I tried some of the source code in the answers, but am still having problems. I see the messages 'hello all' and 'nice to', but actually I want to see 'hello' and 'all' instead.

procedure TForm1.BitBtn1Click(Sender: TObject);
var
  list : TStringList;
  first, second, third: string;
begin
  list := TStringList.Create;
  try
    list.Delimiter := #32;
    list.LoadFromFile('test.txt');
    first := list[0];
    second := list[1];
    ShowMessage(first);
    ShowMessage(second);
  finally
    list.Free;
  end;
end;
Aify
  • 3,543
  • 3
  • 24
  • 43
paul
  • 327
  • 1
  • 7
  • 24

5 Answers5

8

You can use the TStringList Class to split a text file.

see this example :

program SplitTextFile;

{$APPTYPE CONSOLE}

uses
  Classes,
  SysUtils;

var
 Lines : TStringList;
 Split : TStringList;
 i     : Integer;
 j     : Integer;
begin
  Lines := TStringList.Create;
  try
    Lines.LoadFromFile('c:\software\demo.txt'); //assign the file name

    Split := TStringList.Create;
    try
      Split.Delimiter := ' '; // set the delimiter

      for i := 0 to Lines.Count - 1 do //iterate over the lines of the file
      begin
        Split.DelimitedText := Lines[i];
        for j := 0 to Split.Count - 1 do //iterate over the split elements
          Writeln(Split[j]);
      end;
    finally
      Split.Free;
    end;
  finally
    Lines.Free;
  end;

  Readln;
end.
mghie
  • 32,028
  • 6
  • 87
  • 129
RRUZ
  • 134,889
  • 20
  • 356
  • 483
  • @RRUZ: It's obvious you know your stuff (+1), but *please* don't use "except" and "finally" at all in such sample code, or do it properly. Writing it like this won't take any more time really. – mghie Dec 18 '09 at 15:39
4

One of the ways to split a string on a delimiter is using a TStringlist:

var
  list : TStringList;

begin
  list := TStringList.Create;
  try
    list.Delimiter := #32;
    list.DelimitedText := 'abc def ghi';
    first := list[0];
    second := list[1];
    third := list[2];
  finally
    list.Free;
  end;
Toon Krijthe
  • 52,876
  • 38
  • 145
  • 202
  • I'm no VB expert but it seems he's trying to load a file. This can be done with a stringlist too. You just have to add list.LoadFromFile('textfile'); – johnny Dec 18 '09 at 11:57
  • Yes, I know. But the question was about string manipulation. So I assumed he knows how to read a string from a file. – Toon Krijthe Dec 18 '09 at 12:39
  • hello thanks! i was modified source based on your method, but still problem procedure TForm1.BitBtn1Click(Sender: TObject); var list : TStringList; first, second, third: string; begin list := TStringList.Create; try list.Delimiter := #32; list.LoadFromFile('c:\test.txt'); first := list[0]; second := list[1]; third := list[2]; ShowMessage(first); ShowMessage(second); ShowMessage(third); finally list.Free; end; end; – paul Dec 18 '09 at 13:04
1

If you just want to load a textfile for manipulation a Stringlist is handy. Note this is from memory and untested!

procedure loadtext;
var
  vList: TStringList;
  vFirst, vSecond: String; 
  i: Integer;
begin
  vList := TStringList.Create;
  try
    vList.LoadFromFile('myfile.txt');

    for i := 0 to vList.Count-1 do
    begin
      vFirst  := copy(vList[i], 0, pos(vList[i], ''));
      vSecond := copy(vList[i], pos(vList[i], ''), 1000);
    end;
  finally
    FreeAndNil(vList);
  end;  
end;
jpfollenius
  • 16,456
  • 10
  • 90
  • 156
Roland Bengtsson
  • 5,058
  • 9
  • 58
  • 99
1

I have a general purpose utility that I have used ever since my Turbo Pascal days which does just what your asking:

function NumStringParts(SourceStr,Delimiter:String):Integer;
var
  offset : integer;
  curnum : integer;
begin
  curnum := 1;
  offset := 1;
  while (offset <> 0) do
    begin
      Offset := Pos(Delimiter,SourceStr);
      if Offset <> 0 then
        begin
          Inc(CurNum);
            Delete(SourceStr,1,(Offset-1)+Length(Delimiter));
        end;
    end;
  result := CurNum;
end;

function GetStringPart(SourceStr,Delimiter:String;Num:Integer):string;
var
  offset : integer;
  CurNum : integer;
  CurPart : String;
begin
  CurNum := 1;
  Offset := 1;
  While (CurNum <= Num) and (Offset <> 0) do
    begin
      Offset := Pos(Delimiter,SourceStr);
      if Offset <> 0 then
        begin
          CurPart := Copy(SourceStr,1,Offset-1);
          Delete(SourceStr,1,(Offset-1)+Length(Delimiter));
          Inc(CurNum)
        end
      else
        CurPart := SourceStr;
    end;
  if CurNum >= Num then
    Result := CurPart
  else
    Result := '';
end;

For your specific case you can do something like the following:

var
  Data : tStringlist;
  iX,iY,iCnt : integer;
begin
  data := tStringlist.create;
  try
    data.loadFromFile( filename );
    for iX := 0 to Data.Count-1 do
    begin
      iCnt := NumStringParts(Data.Strings[ix],#32);
      for iY := 1 to iCnt do
        ShowMessage( GetStringPart(Data.Strings[ix],#32,iY) );
    end;
  finally
    data.free;
  end;
end;

this opens a file filename and then calls CallSomeFunction for every word (delimited by spaces) in your text file.

skamradt
  • 15,366
  • 2
  • 36
  • 53
  • Hi, i was tested your source but something error encounter, im not sure what is problem. i was just changed 'filename' to 'c:\test.txt' and try to execute source but error . thanks – paul Dec 18 '09 at 18:39
  • @paul - Corrected. The outer loop should be from 0 to count-1, the inner loop from 1 to count. – skamradt Dec 19 '09 at 00:10
0

Or if you really want an array you can try this method:

(copied from http://www.delphi3000.com/articles/article_2616.asp?SK=)

  TStringArray = array of string;


  function Split(const str: string;
                 const separator: string): TStringArray;
  // Returns an array with the parts of "str" separated by "separator"
  var
    i, n: integer;
    p, q, s: PChar;
  begin
    SetLength(Result, Occurs(str, separator)+1);
    p := PChar(str);
    s := PChar(separator);
    n := Length(separator);
    i := 0;
    repeat
      q := StrPos(p, s);
      if q = nil then q := StrScan(p, #0);
      SetString(Result[i], p, q - p);
      p := q + n;
      inc(i);
    until q^ = #0;
  end; 
Birger
  • 4,343
  • 21
  • 35
  • hello thanks for your reply..lack of my delphi knowledge ,i can't understand sorry but thanks a lot :) – paul Dec 18 '09 at 13:11
  • 1
    wow, that does look ugly. I can't imagine anyone to prefer this over the `TStringList` solution. – jpfollenius Dec 18 '09 at 13:31
  • well, this returns an array, and not a stringlist! Ofcourse you could also convert the stringlist to an array, but this will be a little bit slower. – Birger Dec 18 '09 at 14:10
  • This code seems to fail for perfectly legal strings with embedded #0 characters – Marco van de Voort Dec 18 '09 at 15:21