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 IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

removing a substring from a char* 1

Status
Not open for further replies.

bitwise

Programmer
Mar 15, 2001
269
US
I'm browsing directory paths. Currently I start at the users home directory:

char* dir;
dir = getenv("HOME");
dir = strcat(dir, "/");

Now 'dir' most likely equals something like this:
"/home/user/"

To go down into a directory is easy just...
dir = strcat(dir, "mydir/");

...add the directory name to the path and open it. My question is how can I remove "mydir/" when I want to go up? I know that you can just append "../" to the entire directory path and achieve the same results, but I don't want the char* dir to grow indefinitely as the program is in use. The problem is that this is more of a regular expression type thing not a hardcoded substring type thing. Is there a string.h function that can accomplish this or another efficient way to do it?

Thanks,
-bitwise
 
You could just repeatedly save a pointer where your directory string ends. Also, you really don't want to be messing with the buffer returned to you by getenv(), you should copy the results into your own variable and then manipulate that (as shown below):

#include <string.h>

char *home;
char *bookmark;
char dir[FILENAME_MAX+1];

home=getenv(&quot;HOME&quot;);
if (home!=NULL) {
strcpy(dir,home);
strcat(dir, &quot;/&quot;);

bookmark=strrchr(dir,'/');
while (whatever) {

strcat(dir, &quot;mydir/&quot;);
/* do stuff with new directory */
/* now &quot;shorten the string back to $HOME */
*bookmark='\0';
}
}

strrchr() returns a pointer to the LAST place in a string that the char in the 2nd argument occurs.

This code fragment probably doesn't reflect exactly what you're doing, but I'm sure you can adapt it.

BTW, though not really /wrong/, it's redundant to assign result of strcat() to the 1st argument.

Russ
bobbitts@hotmail.com
 
Hm, that is a possiblity. I'll have to tweak it, but thanks for the input. Also, thanks for explaining that I should not use the char* returned to me by getev(&quot;HOME&quot;); I've just been learning C, so I miss those types of things.

What is the best way to get the current working directory?
Currently I'm:

char* cwd, *getcwd();

/* get the working directory */
if((cwd = getcwd((char*)NULL, 1024)) == NULL)
{
perror(&quot;pwd&quot;);
exit(1);
}
printf(&quot;CURRENT DIRECTORY: %s\n&quot;, cwd);
...
free(cwd);

I have read that getcwd() may not be the best function to use. Is there something better?

Thanks,
-bitwise
 
Hey rbobbitt thanks a lot! I tweaked slightly, but your little trick by making the 'bookmark' the end of the string therefore removing the added directory worked great. Now I can browse directories up and down and all around, and my dir char array never grows larger than the current directory length.

A pointer question:
How does changing the value of bookmark affect the dir character array?

Thanks,
-bitwise
 
You seemed to have got it working, but I made a mistake up there. bookmark should have been incremented after the strchr() call:

bookmark=strrchr(dir,'/');
++bookmark;

This way it points to the terminating null and doing:

*boomark='\0';

terminates the string after the last '/' in the 1st path.

As to the pointer question, it depends on what you mean by &quot;change the value of.&quot;

If you were to set bookmark to point to something else, it wouldn't effect dir at all:

char *bookmark;
char foo[]=&quot;bar&quot;;
char dir[FILENAME_MAX+1]=&quot;/path/to/something/&quot;;

bookmark=strrchr(dir,'/');

bookmark=foo; /* now bookmark points to the 1st element of
* foo, dir unaffected
*/

But, something like this would effect dir:

char *bookmark;
char dir[FILENAME_MAX+1]=&quot;/path/to/foo/&quot;;

bookmark=strrchr(dir,'/');
++bookmark; /* bookmark now points to the terminating null */

strcat(dir,&quot;bar/&quot;);

/* now dir contains &quot;/path/to/foo/bar/&quot; */

strcpy(bookmark,&quot;spam/&quot;);

/* now dir contains &quot;/path/to/foo/spam/&quot; */

Does that answer your question?

Russ

Russ
bobbitts@hotmail.com
 
Yes, I did notice you had it off by one, but like I said I tweaked slightly. Anyway, it was enough to get me on the right path. Also, thanks for the char* pointer lesson. It did answer my question, and I understand char* that much better now.

Thanks,
-bitwise
 
Oh, forgot about the current directory path question.

Since it's implementation-dependent, whatever works on your system is appropriate. getcwd() is a POSIX function, so you'll at least be able to port it across Unices.

You aren't really calling it right up there though. getcwd() expects the 1st parameter to be a pointer to the buffer it fills with the current directory, so it should never be NULL. In other words, you are supposed to allocate the memory for the buffer that it fills. The return value is just a pointer to the buffer you supplied, or NULL if the function fails. Try this instead:

char buf[FILENAME_MAX+1];

if (getcwd(buf,sizeof buf)==NULL) {
/* error ... */

Also, I noticed that you free()'ed the pointer returned by getcwd() above. You should /never/ call free() on a pointer unless you are absolutely sure that it was allocated by malloc, calloc or realloc(). The documentation for a given function should tell you whether or not this is the case. In this case, you are calling free() on the buffer that you supply, so you should only call free() on it if you allocated it as described above.

Russ
bobbitts@hotmail.com
 
Opps! Thanks again rbobbitt. My C is coming along. It's this type of advice that is making it better. I'll make sure to make the appropriate changes. I think getcwd() directory does call malloc on the buffer if needed, but I don't think it is recommended to do it the way I was. Your way seems much more stable and compliant.

Thanks,
-bitwise
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top