Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2003-02

ExtractFileDir ?

5 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Iván Montes

According to the docs
http://www.freepascal.org/docs-html/units/node23.html#SECTION002366000000000 000000

"ExtractFileDir returns only the directory part of FileName, not including a driveletter."

But it does return the driveletter, so either the docs are mistaken or the RTL.

If the docs are right here there is a function that will return only the dir, removing
any drive letter.
ie:
c:\testdir\test\file.ext => \testdir\test
c:\testdir\ => \testdir
c:testdir\ => testdir
\testdir\test.exe => \testdir

[objpas\fina.inc]

function ExtractFileDir(const FileName: string): string;
var i,j: longint;
begin
  if FileName[2]=':' then j:=3
                     else j:=1;
  I := Length(FileName);
  while (I > 0) and not (FileName[I] in ['/', '\', ':']) do Dec(I);
  if (I > j) and (FileName[I] in ['\', '/']) and
     not (FileName[I - 1] in ['/', '\', ':']) then Dec(I);
  Result := Copy(FileName, j, I-j+1);
end;

HTH, ivan

Reply by email

Iván Montes

According to the docs
http://www.freepascal.org/docs-html/units/node23.html#SECTION002366000000000 000000

"ExtractFileDir returns only the directory part of FileName, not including a
driveletter."

But it does return the driveletter, so either the docs are mistaken or the RTL.

If the docs are right here there is a function that will return only the dir, removing
any drive letter.
ie:
c:\testdir\test\file.ext => \testdir\test
c:\testdir\ => \testdir
c:testdir\ => testdir
\testdir\test.exe => \testdir

[objpas\fina.inc]

 function ExtractFileDir(const FileName: string): string;
 var i,j: longint;
 begin
   if FileName[2]=':' then j:=3
                      else j:=1;
   I := Length(FileName);
   while (I > 0) and not (FileName[I] in ['/', '\', ':']) do Dec(I);
   if (I > j) and (FileName[I] in ['\', '/']) and
      not (FileName[I - 1] in ['/', '\', ':']) then Dec(I);
   Result := Copy(FileName, j, I-j+1);
 end;

HTH, ivan

Reply by email

Anton Tichawa
to Iván Montes

Hi!

Let's have a look for filename "C:A":

Show quoted text 5 lines
function ExtractFileDir(const FileName: string): string; var i,j: longint; begin if FileName[2]=':' then j:=3 else j:=1;

Now j = 3, pointing to the letter "A". OK.

I := Length(FileName); while (I > 0) and not (FileName[I] in ['/', '\', ':']) do Dec(I);

Error: I is supposed to go from the string end back to the string start, but never below j. But exactly this happens here. I is decremented below j, from 3 to 2, so shit might happen ..

if (I > j) and (FileName[I] in ['\', '/']) and not (FileName[I - 1] in ['/', '\', ':']) then Dec(I);

skipped

Result := Copy(FileName, j, I-j+1);

Result = Copy(Filename, 3, 0).

Is this an error or wrong documentation? The line result should be '', but it actually is 'a:c'.

So there are two errors:

1. I decremented below j, but the programmer had in mind that i was above j. the while-statement should read 'while (I > J) ..'

2. The Copy returns the full string for length 0 -

Note: I don't like the while structure for combined conditions. I prefer a repeat-until with several breaks. That usually makes things more clear. I know that this is not considered 'well-structured' programming, but the world we live in is not 'well-structured'. Should I post a new, tested "repeat - break - break - until" version of this function?

Anton.

_______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
---------- "Adas Methode war, wie sich zeigen wird, Tagträume in offenbar korrekte Berechnungen einzuweben." Doris Langley Moore: Ada, Countess of Lovelace (London 1977). ---------- Anton Tichawa Volkertstrasse 19 / 20 A-1020 Wien mobil: +43 664 52 07 907 email: ----------

Reply by email

Iván Montes

[OT: Sorry if this was posted before but I'm having some weird problems with email]

According to the docs
http://www.freepascal.org/docs-html/units/node23.html#SECTION002366000000000 000000

"ExtractFileDir returns only the directory part of FileName, not including a driveletter."

But it does return the driveletter, so either the docs are mistaken or the RTL.

If the docs are right here there is a function that will return only the dir, removing any drive letter.
ie:
c:\testdir\test\file.ext => \testdir\test
c:\testdir\ => \testdir
c:testdir\ => testdir
\testdir\test.exe => \testdir

[objpas\fina.inc]

 function ExtractFileDir(const FileName: string): string;
 var i,j: longint;
 begin
   I := Length(FileName);
   if (I>1) and (FileName[2]=':') then j:=3
                      else j:=1;
   I := Length(FileName);
   while (I > 0) and not (FileName[I] in ['/', '\', ':']) do Dec(I);
   if (I > j) and (FileName[I] in ['\', '/']) and
      not (FileName[I - 1] in ['/', '\', ':']) then Dec(I);
   Result := Copy(FileName, j, I-j+1);
 end;

HTH, ivan

Reply by email

Iván Montes
to Anton Tichawa: Hi! Let's have a look for filename "C:A": Now j = 3, pointing to the letter "A". OK.…

----- Original Message -----
From: "Anton Tichawa"

So there are two errors: 1. I decremented below j, but the programmer had in mind that i was above

j.

Show quoted text 7 lines
the while-statement should read 'while (I > J) ..' 2. The Copy returns the full string for length 0 - Note: I don't like the while structure for combined conditions. I prefer a repeat-until with several breaks. That usually makes things more clear. I know that this is not considered 'well-structured' programming, but the

world

we live in is not 'well-structured'. Should I post a new, tested "repeat - break - break - until" version of this function?

my mistake, sorry, hopefully this should work fine

c:\test\ => \test
c:test\ => test
\test => \
c:a => <empty string>
c:\ => \
\\Workgroup\server\command.com => \\Workgroup\server

function ExtractFileDir( const FileName :string):string;
var
    len, j :integer;
begin
  //Get the filename length
  len := length(FileName);
  //Check if it has defined a drive
  if (len>1) AND (FileName[2]=':') then j:=3
                                   else j:=1;
  //Find the last directory separator if any
  while (len>=j) AND NOT(FileName[len] in ['\','/']) do Dec(len);
  //Remove the ending slash
  if len>j then dec(len);
  if len<j then result := '' //no directory found
           else result := Copy(FileName, j, len-j+1);
end;

Reply by email