Separating directory from file name

J

Joe Laughlin

If I have a character array with "/some/file/directory/file_name", are there
any functions / libraries that I could use to separate the directory
("some/file/directory") from the file name ("file_name").

I looked at sscanf(), but that didn't seem to do what I wanted.

Thanks,
Joe
 
T

Tom St Denis

Joe said:
If I have a character array with "/some/file/directory/file_name", are there
any functions / libraries that I could use to separate the directory
("some/file/directory") from the file name ("file_name").

I looked at sscanf(), but that didn't seem to do what I wanted.

Homework question BEGONE!

[hint cuz I want you to fail at your job by being unable to solve
trivial problems yourself....: scan backwards in the string for the first /]

Tom
 
J

Joe Laughlin

Tom said:
Joe said:
If I have a character array with
"/some/file/directory/file_name", are there any
functions / libraries that I could use to separate the
directory ("some/file/directory") from the file name
("file_name").

I looked at sscanf(), but that didn't seem to do what I
wanted.

Homework question BEGONE!

[hint cuz I want you to fail at your job by being unable
to solve
trivial problems yourself....: scan backwards in the
string for the first /]

Tom

I'm not familar with C character array processing, sorry. Again, are there
any standard libraries that would let me scan backwards, or do I need to do
this manually?
 
K

Kieran Simkin

Joe Laughlin said:
Tom said:
Joe said:
If I have a character array with
"/some/file/directory/file_name", are there any
functions / libraries that I could use to separate the
directory ("some/file/directory") from the file name
("file_name").

I looked at sscanf(), but that didn't seem to do what I
wanted.

Homework question BEGONE!

[hint cuz I want you to fail at your job by being unable
to solve
trivial problems yourself....: scan backwards in the
string for the first /]

Tom

I'm not familar with C character array processing, sorry. Again, are there
any standard libraries that would let me scan backwards, or do I need to do
this manually?

There may be a library function that'll do this for you, but it's quite
quick to do it manually too. See the example below:


void extractfilename(const char *path, char *filename) {
int i,c=0;

/* put the highest value for n in path[n] into i (if we ignore the \0)
*/
i=strlen(path)-1;

/* itterate backwards through the array decreasing i until we get to a
'/' */
while (i>0) {
if (path == '/')
break;
i--;
}

/* itterate forwards through the array starting from the element after
after the '/' and dump the remaining characters into filename */
while (i<strlen(path)) {
filename[c++]=path[++i];
}
}

I wrote this to test my own knowledge more than anything, comments invited.
A better version of the function would take the size of the destination
array as an argument to avoid buffer overflows but I left this out for
simplicity. Code compiles without warnings in gcc with -Wall -pedantic.


~Kieran Simkin
Digital Crocus
http://digital-crocus.com/
 
K

Kieran Simkin

Kieran Simkin said:
Joe Laughlin said:
Tom said:
Joe Laughlin wrote:
If I have a character array with
"/some/file/directory/file_name", are there any
functions / libraries that I could use to separate the
directory ("some/file/directory") from the file name
("file_name").

I looked at sscanf(), but that didn't seem to do what I
wanted.

Homework question BEGONE!

[hint cuz I want you to fail at your job by being unable
to solve
trivial problems yourself....: scan backwards in the
string for the first /]

Tom

I'm not familar with C character array processing, sorry. Again, are there
any standard libraries that would let me scan backwards, or do I need to do
this manually?

There may be a library function that'll do this for you, but it's quite
quick to do it manually too. See the example below:

Forgot to paste the #include said:
void extractfilename(const char *path, char *filename) {
int i,c=0;

/* put the highest value for n in path[n] into i (if we ignore the \0)
*/
i=strlen(path)-1;

/* itterate backwards through the array decreasing i until we get to a
'/' */
while (i>0) {
if (path == '/')
break;
i--;
}

/* itterate forwards through the array starting from the element after
after the '/' and dump the remaining characters into filename */
while (i<strlen(path)) {
filename[c++]=path[++i];
}
}

I wrote this to test my own knowledge more than anything, comments invited.
A better version of the function would take the size of the destination
array as an argument to avoid buffer overflows but I left this out for
simplicity. Code compiles without warnings in gcc with -Wall -pedantic.


~Kieran Simkin
Digital Crocus
http://digital-crocus.com/
 
S

SM Ryan

# Tom St Denis wrote:
# > Joe Laughlin wrote:
# >> If I have a character array with
# >> "/some/file/directory/file_name", are there any
# >> functions / libraries that I could use to separate the
# >> directory ("some/file/directory") from the file name
# >> ("file_name").

The problem as stated is not answerable without specifying the
operating system. NOS and TSOS didn't even have directories. On Mac System
7, that is a single file name.

# I'm not familar with C character array processing, sorry. Again, are there
# any standard libraries that would let me scan backwards, or do I need to do
# this manually?

If you have a unix available, try
manpage 3 string
and then follow the see-alsos.

You can also browse
http://www.squarebox.co.uk/cgi-squarebox/manServer/usr/share/man/man3/string.3
and follow the links.
 
J

Jack Klein

If I have a character array with "/some/file/directory/file_name", are there
any functions / libraries that I could use to separate the directory
("some/file/directory") from the file name ("file_name").

I looked at sscanf(), but that didn't seem to do what I wanted.

Thanks,
Joe

While the format of path names, or even file names, are properties of
the operating system and not specified by C, you have a string issue
here that the C library can easily handle.

Look up the function strrchr() -- note two 'r' characters in the
middle, not just one. That will return a pointer to the rightmost '/'
(or any other) character in your string, or NULL if the character is
not present.
 
B

Barry Schwarz

If I have a character array with "/some/file/directory/file_name", are there
any functions / libraries that I could use to separate the directory
("some/file/directory") from the file name ("file_name").

I looked at sscanf(), but that didn't seem to do what I wanted.
There is a function in the standard library, for which string.h
contains the prototype, that you can use to determine where the last
'/' occurs in your array. It should not be hard for you to find it in
your text or reference and then to figure out how to use this
information to perform the separation you want.


<<Remove the del for email>>
 
M

Martin Dickopp

Kieran Simkin said:
Joe Laughlin said:
I'm not familar with C character array processing, sorry. Again, are
there any standard libraries that would let me scan backwards, or do
I need to do this manually?

There may be a library function that'll do this for you, but it's quite
quick to do it manually too. See the example below:


void extractfilename(const char *path, char *filename) {
int i,c=0;

/* put the highest value for n in path[n] into i (if we ignore
the \0) */
i=strlen(path)-1;

/* itterate backwards through the array decreasing i until we get
to a '/' */
while (i>0) {
if (path == '/')
break;
i--;
}

/* itterate forwards through the array starting from the element
after after the '/' and dump the remaining characters into
filename */
while (i<strlen(path)) {
filename[c++]=path[++i];
}
}

I wrote this to test my own knowledge more than anything, comments
invited. A better version of the function would take the size of the
destination array as an argument to avoid buffer overflows but I left
this out for simplicity. Code compiles without warnings in gcc with
-Wall -pedantic.

Three comments:

- `int' does not necessarily have a large enough range to represent
the size of an object. Better use `size_t', the type returned
by `strlen'. However, if you just change `int' to `size_t' (an
/unsigned/ type), your algorithm won't work anymore - think about
what happens when `path' is an empty string.

- Your algorithm is inefficient in that it first scans the complete
string to find its end (strlen), and then scans part of the string
/again/ to find the last slash. This can be avoided by scanning the
string once and in the process remembering the last slash encountered.

- It is also inefficient to call `strlen (path)' in the while loop.
Unless the compiler recognizes that it can optimize this by moving the
`strlen' call out of the loop, the string will be scanned once for
every iteration!


#include <stdio.h>

/* Undefined behavior if `path' is a null pointer, or if `filename'
doesn't point to a large enough buffer. Return `filename'. */
char *extractfilename (const char *path, char *const filename)
{
/* Pointer the first character that should be copied. */
const char *src = path;

/* Pointer to the buffer where the filename should be copied. */
char *dst = filename;

while (*path != '\0')
{
/* Increment `path' and look for a slash. */
if (*path++ == '/')
{
/* If a slash has been found, `path' has already been
incremented, so that `src' points one past the slash. */
src = path;
}
}

/* Copy remaining characters. */
while (*dst++ = *src++)
continue;

return filename;
}

int main (void)
{
const char *test1 = "/path/and/filename";
const char *test2 = "filename_without_path";
const char *test3 = "/trailing/slash/";
const char *test4 = "";
char buffer [22];

printf ("test1: \"%s\" -> \"%s\"\n", test1, extractfilename (test1, buffer));
printf ("test2: \"%s\" -> \"%s\"\n", test2, extractfilename (test2, buffer));
printf ("test3: \"%s\" -> \"%s\"\n", test3, extractfilename (test3, buffer));
printf ("test4: \"%s\" -> \"%s\"\n", test4, extractfilename (test4, buffer));
return 0;
}


Martin
 
D

Dan Pop

In said:
# Tom St Denis wrote:
# > Joe Laughlin wrote:
# >> If I have a character array with
# >> "/some/file/directory/file_name", are there any
# >> functions / libraries that I could use to separate the
# >> directory ("some/file/directory") from the file name
# >> ("file_name").

The problem as stated is not answerable without specifying the
operating system. NOS and TSOS didn't even have directories. On Mac System
7, that is a single file name.

The problem, as stated, came with a concrete example that makes it
perfectly answerable.
# I'm not familar with C character array processing, sorry. Again, are there
# any standard libraries that would let me scan backwards, or do I need to do
# this manually?

If you have a unix available, try
manpage 3 string
and then follow the see-alsos.

All the advice provided by this command on the average Unix system is:

fangorn:~ 11> manpage 3 string
manpage: Command not found.

Not particularly helpful...

Dan
 
D

Dan Pop

In said:
If I have a character array with "/some/file/directory/file_name", are there
any functions / libraries that I could use to separate the directory
("some/file/directory") from the file name ("file_name").

I looked at sscanf(), but that didn't seem to do what I wanted.

If you want to deal with strings in C, you *really* need to study the
description of <string.h> in your favourite C book.

It is obvious that what you need is the address of the last '/' character
in your character array. The standard library function that finds the
last occurrence of a character in a string is strrchr. If the function
fails to find it, the whole character array must be considered the file
name.

So, if you can overwrite your character array, after

char *fn = strrchr(array, '/');
if (fn != NULL) *fn++ = 0;
else fn = array;

fn will point to the file name and, if fn != array, array will contain the
path name.

Dan
 
C

CBFalconer

Martin said:
.... snip ...

Your algorithm is inefficient in that it first scans the complete
string to find its end (strlen), and then scans part of the string
/again/ to find the last slash. This can be avoided by scanning the
string once and in the process remembering the last slash encountered.

Not necessarily so. The comparisons made in the combined scan can
be much less efficient, and necessarily encompass the complete
string. The second half of the separated scan starts from the
end, and may be much shorter.
 
A

Alan Balmer

Tom said:
Joe said:
If I have a character array with
"/some/file/directory/file_name", are there any
functions / libraries that I could use to separate the
directory ("some/file/directory") from the file name
("file_name").

I looked at sscanf(), but that didn't seem to do what I
wanted.

Homework question BEGONE!

[hint cuz I want you to fail at your job by being unable
to solve
trivial problems yourself....: scan backwards in the
string for the first /]

Tom

I'm not familar with C character array processing, sorry. Again, are there
any standard libraries that would let me scan backwards, or do I need to do
this manually?
If this is a homework question, you need to have a talk with your
instructor. If it isn't homework, I think you need to hire a
programmer.
 
N

nobody

Joe Laughlin said:
If I have a character array with "/some/file/directory/file_name", are there
any functions / libraries that I could use to separate the directory
("some/file/directory") from the file name ("file_name").

I looked at sscanf(), but that didn't seem to do what I wanted.
I don't know about any standard C answer to the stated problem,
but your example might imply UNIX pathname syntax (although
also acceptend on Windoze, though not on command line). So even
standard C answer (e.g. strrchr(), as suggested) may be platform specific.
If you are on UNIX, there should be basename(3C). For details
see e.g. here:
http://docs.sun.com/db/doc/805-3175/6j31emn1l?a=view#basename-3c-indx-1

My apologies to the group for an OT answer. But in this case I consider
it worth giving. It's not portable, but neither are some others. I've
already
forgotten what path looked like on VAX. Original problem was to extract
file name from the full path name, not to find last '/'.
 
M

Mabden

CBFalconer said:
Not necessarily so. The comparisons made in the combined scan can
be much less efficient, and necessarily encompass the complete
string. The second half of the separated scan starts from the
end, and may be much shorter.

I'm afraid I have to agree with Martin. (Ouch)

All algorithms I have seen in c that "start at the end" of a string,
actually scan forwards to a '/0'. If this were Pascal, where the length is
given and you could jump to the end of the string with a memory read (and a
256 byte size limit) then you might be correct. But in C you are better off
storing the slashes as you find them and only scan once through the string.
I have never found strrchr() to be very useful, as I can build a loop that
does what I want better than the standard function.
 
M

Martin Dickopp

Mabden said:
I'm afraid I have to agree with Martin. (Ouch)

Chuck does have a point. I think the important message is that my
implementation is not guaranteed to be more efficient than the original
one, but neither vice versa. If it matters, some benchmarking for
typical input strings must be done.

Martin
 
M

Mabden

Hey, Martin! I thought you killfiled me over some comedy I posted once! Did
you grow a sensual humor?
 
C

CBFalconer

Mabden said:
I'm afraid I have to agree with Martin. (Ouch)

All algorithms I have seen in c that "start at the end" of a string,
actually scan forwards to a '/0'. If this were Pascal, where the length is
given and you could jump to the end of the string with a memory read (and a
256 byte size limit) then you might be correct. But in C you are better off
storing the slashes as you find them and only scan once through the string.
I have never found strrchr() to be very useful, as I can build a loop that
does what I want better than the standard function.

The difference lies in the complexity of the initial scan. The
two scan looks something like:

p = ptr;
while (*p++) continue;
p--;
while (('/' != *p) && (p > ptr)) p--;

while the complex single scan is something like:

pp = NULL; p = ptr;
while (*p) {
if ('/' == *p) pp = p;
p++;
}
 
C

Chris McDonald

The difference lies in the complexity of the initial scan. The
two scan looks something like:
p = ptr;
while (*p++) continue;
p--;
while (('/' != *p) && (p > ptr)) p--;
while the complex single scan is something like:
pp = NULL; p = ptr;
while (*p) {
if ('/' == *p) pp = p;
p++;
}


Is there something inherently wrong with using standard functions, here,
or is this just a macho contest? Such as:

argv0 = (argv0 = strrchr(argv[0],'/')) ? argv0+1 : argv[0];

and assuming that the standard functions will be reasonably implemented
and tested?

_______________________________________________________________________________
Dr Chris McDonald EMAIL: (e-mail address removed)
School of Computer Science & Software Engineering
The University of Western Australia WWW: http://www.csse.uwa.edu.au/~chris
Crawley, Western Australia, 6009 PH: +61 8 6488 2533, FAX: +61 8 6488 1089
 
D

Dan Pop

In said:
I'm afraid I have to agree with Martin. (Ouch)

All algorithms I have seen in c that "start at the end" of a string,
actually scan forwards to a '/0'. If this were Pascal, where the length is
given and you could jump to the end of the string with a memory read (and a
256 byte size limit) then you might be correct. But in C you are better off
^^^^^^^^^^^^^^^^^^^^^^^^^^^
storing the slashes as you find them and only scan once through the string.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I have never found strrchr() to be very useful, as I can build a loop that
does what I want better than the standard function.

What makes you think that strrchr() doesn't work exactly as you have
described above? All the generic C implementations of strrchr() I am
familiar with do a single scan, until they find the null character and
"remember" the last address of the target character.

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top