[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

Is this an efficient and safe way to grab front part of a string

Angus

9/3/2011 6:15:00 PM

Hello

I need to grab the first part of a string up till and including the
last backslash in a path. I am fairly new to C so was wondering if
the following code is a good approach?

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[]) {

char szPath[260] = {0};
strcpy(szPath, argv[0]);
char* p = szPath;

size_t len = strlen(argv[0]);
p+=len; //go to end of string

int backpos = 0;
while(*--p != '\\')
++backpos;

szPath[len-backpos] = 0;

printf("%s\n", szPath);

return 0;
}
3 Answers

Eric Sosman

9/3/2011 6:39:00 PM

0

On 9/3/2011 2:14 PM, Angus wrote:
> Hello
>
> I need to grab the first part of a string up till and including the
> last backslash in a path. I am fairly new to C so was wondering if
> the following code is a good approach?
>
> #include<stdio.h>
> #include<string.h>
>
> int main(int argc, char* argv[]) {
>
> char szPath[260] = {0};

Efficiency: Since the very next thing you do is overwrite whatever's
in the array, initializing it is pointless.

> strcpy(szPath, argv[0]);

Safety: If strlen(argv[0]) > 259 you're in trouble (see "buffer
overflow"). Also, it is just barely possible that argv[0] could be
NULL, so checking for that would make your code (marginally) safer.

> char* p = szPath;
>
> size_t len = strlen(argv[0]);
> p+=len; //go to end of string
>
> int backpos = 0;
> while(*--p != '\\')
> ++backpos;

Safety: If the string contains no '\\' characters at all, you
will walk merrily off the beginning and go traipsing through whatever
happens to lie in adjoining memory. With unpredictable consequences.

Efficiency: Check your C reference for the strrchr() function
(that's three r's, not two).

> szPath[len-backpos] = 0;
>
> printf("%s\n", szPath);

Efficiency: If you just need to print this prefix, as opposed
to using it for other purposes, there's a way to do it without making
a copy and without modifying the string argv[0] points to (which would
be un-safe). Suppose, after a little rummaging around, you have found
that there are prefix_len characters before the rightmost '\\':

int prefix_len = ...;
printf ("%.*s\n", prefix_len+1, argv[0]);

You'll probably find this in your C reference, although you may have
to look closely at the fine print. The "dot something" specifies the
so-called _precision_ of the conversion, which for "%s" means the
maximum number of characters printed, so "%.3s" prints at most three
characters, "%.42s" forty-two, and so on. The "*" means "get this
number from the argument list instead of from digits in the format
string," so in effect it makes prefix_len+1 part of the format.

> return 0;
> }

--
Eric Sosman
esosman@ieee-dot-org.invalid

gw7rib

9/4/2011 7:20:00 PM

0

On Sep 3, 7:14 pm, Angus <anguscom...@gmail.com> wrote:
> I need to grab the first part of a string up till and including the
> last backslash in a path.  I am fairly new to C so was wondering if
> the following code is a good approach?

Just one style point, in addition to what the others have said:

> #include <stdio.h>
> #include <string.h>
>
> int main(int argc, char* argv[]) {
>
>     char szPath[260] = {0};
>     strcpy(szPath, argv[0]);
>     char* p = szPath;
>
>     size_t len = strlen(argv[0]);

I would use "szPath" here, rather than "argv[0]". Once you've made a
copy of the thing you want, it seems more natural (and may be safer if
you modify the code later) to concentrate on the thing you're actually
working on rather than keep looking back to where it came from.

David Thompson

9/9/2011 5:29:00 AM

0

On Sat, 03 Sep 2011 14:39:19 -0400, Eric Sosman
<esosman@ieee-dot-org.invalid> wrote:

> On 9/3/2011 2:14 PM, Angus wrote:
> > Hello
> >
> > I need to grab the first part of a string up till and including the
> > last backslash in a path.
<snip>
> > strcpy(szPath, argv[0]);
>
> Safety: If strlen(argv[0]) > 259 you're in trouble (see "buffer
> overflow"). Also, it is just barely possible that argv[0] could be
> NULL, so checking for that would make your code (marginally) safer.
>
<snip other good points>

Also note that argv[0] is the 'name' of the program being run, but not
necessarily its full pathname. As Eric says, the standard allows it to
be null, but I don't believe any Windows implementation does so (and
Windows is the only platform I know of where \ is a path separator).

If you intended to do this operation on a pathname provided as an
argument to your program, use argv[1] after checking argc.

<OT++>
If you intended to do this on the program path, you probably need to
use GetModuleFilename instead.

<OT++>
And if you intended to do this on the program path to find a directory
to put writable data, don't. Windows officially dislikes that, even
though people did it a lot, and recent generations (>=Vista) are
stricter about it. Submit to the will of Bill and use envvar APPDATA
or similar. For installed read-only data, like a help file, it's okay.