Link to home
Start Free TrialLog in
Avatar of itektas
itektas

asked on

Reading part of a line from a text file

I have a code which lets me read lines from a text file and displays each lines content into a separate Edit fields; I want to change it so that i can read parts of the line and not the entire line; for example say I have a text file which contains the following information.

Country France ;
Continent Europe ;
Language French ;


The following is my original code how would I change it so that  read "France" "Europe" "French" in each of my edit fields rather then reading the whole lines.
Note: i want to read the part of the line regardless of the content,  so if the content of the line is changed i still want to be able to read that same part of the line into the corresponding edit field; thanks

var
sl: TStringList;
begin
sl :=TStringList.Create;
sl.LoadFromFile('/home/user/test.txt');
Edit1.Text := sl[0];
Edit2.Text := sl[1];
Edit3.Text := sl[2];
sl.Free;

Avatar of arjanh
arjanh

 temp := Copy( sl[0], Pos(' ', sl[0])+1, Length(sl[0]) );   // everything from the first space
  Edit1.Text := Copy( temp, 1, Pos(' ', temp) );
Avatar of itektas

ASKER

ok, i get undeclared identifier "temp ; am i missing something somewhere?

var
sl: TStringList;
begin
sl :=TStringList.Create;
temp := Copy( sl[0], Pos(' ', sl[0])+1, Length(sl[0]) );
sl.LoadFromFile('/home/user/test.txt');
Edit1.Text := Copy( temp, 1, Pos(' ', temp) );
sl.Free;
end;
ASKER CERTIFIED SOLUTION
Avatar of arjanh
arjanh

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of itektas

ASKER

cool that works now, thanks. :) One thing tho, say when the contents of my text file are

country france ;

then it reads it but if they are

country france;  

 without a space after the semicolon then it doesnt not read it, can i change something so that  i can keep the word and the semicolon together and still read it to the edit field? thanks
You could change
  Edit1.Text := Copy( temp, 1, Pos(' ', temp) );
to
  Edit1.Text := Copy( temp, 1, Pos(';', temp) );

Then it reads everything from the first space to the first semicolon. However in case of 'france ;' the edit box would show 'france '. If the extra space is a problem it would get a bit tricky, and that's gonna cost ya more than 20 points :)
Avatar of itektas

ASKER

Ok  i will set another 30 points? But do i need to open a new question to give you more points or is there another way of doing it? I have done what you said ( adding the extra ';' ) but then when i run the program it displays the semicolon as well, so if the contents of my text file are " france;" then "france;" is displayed in the edit box and if they are "france ;" then that is displayed in the edit box. I would prefer not to have the semicolon displayed, and i think it would also be useful not to have an extra space when I have "France ;" thanks
You're in luck. As I had not tested my code, I oversaw that little problem with the ';'. So here is the final, correct, tested version:

function GetSecondWord( Source : String ) : String;
var
  p1,p2,p3 : Integer;
  temp : String;
begin
  p1 := Pos( ' ', Source );
  temp := Copy( Source, p1+1, Length(Source) );
  p2 := Pos( ' ', temp );
  p3 := Pos( ';', temp );

  if p2 = 0 then
    if p3 = 0 then
      Result := temp
    else
      Result := Copy( temp, 1, p3-1 )
  else  // p2 <> 0
    if p3 = 0 then
      Result := Copy( temp, 1, p2-1 )
    else  // p2 <> 0 AND p3 <> 0
      if p2 > p3 then
        Result := Copy( temp, 1, p3-1 )
      else
        Result := Copy( temp, 1, p2-1 )
end;

procedure TForm1.Button1Click(Sender: TObject);    // OR whatever your procedure is called!
var
  sl: TStringList;
begin
  sl :=TStringList.Create;
  sl.LoadFromFile('/home/user/test.txt');

  Edit1.Text := GetSecondWord( sl[0] );
  Edit2.Text := GetSecondWord( sl[1] );
  Edit3.Text := GetSecondWord( sl[2] );

  sl.Free;
end;



If you want to, you could create a new question in this topic area with the title "Points for arjanh re: Question 20792222". In the body of the new question, post the URL of the original question, and in this question post the URL of that new question.
But don't feel obliged...
Avatar of itektas

ASKER

wow, the code suddenly got quiet complicated, i dont really understand what happens behind that :/ is there like an easier way that i could just remove the inital problem where the ";" appeared after france? as the extra space seems to make the coding quiet confusing! I will do what you said now for the points, also is there any websites that you would recommend me to learn about the text files manupilating? I have a book on Delphi 7 and Kylix but i find it difficult to find relevant information for what i want to do with text files. thanks
We agree on the code being more complex than it ought to be. So here is an improved version (my motto: get it working; get it right; get it optimized).

function GetSecondWord( Source : String ) : String;
var
  p1,p2 : Integer;
  temp : String;
begin
  p1 := Pos( ' ', Source );
  temp := Copy( Source, p1+1, Length(Source) );

  // replace the first space (if any) with ';'
  temp := StringReplace( temp, ' ', ';', [] );

  // Now return everything up to the first ';'
  p2 := Pos( ';', temp );
  if p2 = 0 then
    Result := temp
  else
    Result := Copy( temp, 1, p2-1 );
end;


I don't know any relevant books. Just play around a lot with it, I guess :)
And the Delphi help pages (F1 within the IDE) are also helpful. And search the web, or ask here.
But hands-on experience seems the best way....
Avatar of itektas

ASKER

that works perfectly, but can you briefly explain me what this bit of coding actually does

  p1 := Pos( ' ', Source );
  temp := Copy( Source, p1+1, Length(Source) );
 
temp := StringReplace( temp,' ', ';', [] );

  p2 := Pos( ';', temp );
  if p2 = 0 then
    Result := temp
  else
    Result := Copy( temp, 1, p2-1 );

by pasting it and changing the "p2" to "p3" then "p4"... I can add more edit fields to my program, all i want to be able to do is to be able to read say for example a third word rather then the second but i cant change the coding as i dont really understand what it does. thanks a lot
[example string = 'a b ;']

>   p1 := Pos( ' ', Source );
p1 is the index of the first space within the string Source. If no space is found, Pos returns 0. If you place your cursor on the word Pos and press F1, you get the online help for the Pos function. Very handy!
[p1 = 2]

>   temp := Copy( Source, p1+1, Length(Source) );
temp is the substring of Source that starts 1 position AFTER the space (so the first character of the word). The third parameter is the length of the substring you want to copy, if this value is larger than the remainder of the source string, just the remainder is returned.
[temp = Copy('a b ;', 3, 5) = 'b ;']

> temp := StringReplace( temp,' ', ';', [] );
Replace the first space found in temp with a semicolon.
[temp = 'b;;']

>   p2 := Pos( ';', temp );
p2 is the index of the first ';'
[p2 = 2]

>   if p2 = 0 then
This happens if temp doesn't contain any ';' at all

>     Result := temp
So we return the whole substring

>   else
Otherwise (P2 <> 0)

>     Result := Copy( temp, 1, p2-1 );
Get the substring from temp that starts at position 1 and has a length of p2-1, which is the character just before the ';'
[Result = Copy('b;;',1,1) = 'b']
function index(t:String):String;
var
 p  : Integer;
 i  : String;
begin
 p:=pos(' ',t);
 i:=copy(t,p+1,length(t));
 result:=copy(t,1,p-1)+'='+copy(i,1,pos(' ',i)-1);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 sl : TStringList;
 j  : Integer;
begin
 sl :=TStringList.Create;
//sl.LoadFromFile('/home/user/test.txt');
 sl.Add('Country France ;');
 sl.Add('Continent Europe ;');
 sl.Add('Language French ;');
 for j:=0 to sl.Count-1 do
  sl[j]:=index(sl[j]);
 edit1.Text:=sl.Values['Country'];
 edit2.Text:=sl.Values['Continent'];
 edit3.Text:=sl.Values['Language'];
 sl.Free;
end;

Good coding....

ManChesTer.