467,905 Members | 1,837 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 467,905 developers. It's quick & easy.

removing substring from string

I am little bit confused
Is this a legal way of removing a substring
from a string? What about the second alternative
using strcpy, is it ok even though the source and
dest. strings overlap?

// Remove (first occurence of) sub from src
void func(char *src, char *sub)
{
char *p;
if ((p=strstr(src,sub)) != NULL)
{
memmove(p,p+strlen(sub), strlen(p+strlen(sub))+1);

// alternative
// strcpy(p,p+strlen(sub));
}
}
Nov 14 '05 #1
  • viewed: 21872
Share:
6 Replies
becte wrote:
I am little bit confused
Is this a legal way of removing a substring
from a string? What about the second alternative
using strcpy, is it ok even though the source and
dest. strings overlap?

// Remove (first occurence of) sub from src
void func(char *src, char *sub)
{
char *p;
if ((p=strstr(src,sub)) != NULL)
{
memmove(p,p+strlen(sub), strlen(p+strlen(sub))+1);
Looks all right to me.
// alternative
// strcpy(p,p+strlen(sub));
Undefined behavior if source and destination overlap
(i.e., if strlen(p+strlen(sub)) >= strlen(sub)).
}
}

Nov 14 '05 #2


becte wrote:
I am little bit confused
Is this a legal way of removing a substring
from a string? What about the second alternative
using strcpy, is it ok even though the source and
dest. strings overlap?

// Remove (first occurence of) sub from src
void func(char *src, char *sub)
{
char *p;
if ((p=strstr(src,sub)) != NULL)
{
memmove(p,p+strlen(sub), strlen(p+strlen(sub))+1);

// alternative
// strcpy(p,p+strlen(sub));
}
}


The Standard's Description of function strcpy says
"If copying takes place between objects that
overlap, the behavior is undefined."
p, pointing to an array than includes the string
pointed to by p+strlen(sub), is an overlap.
An implementator is free to implement function strcpy
similiar to this:
char *MyStrCpy(char *s, const char *cs)
{
const char *tmp;
size_t n = strlen(cs);

for(tmp = cs+n; ; tmp--,n--)
{
*(s+n) = *tmp;
if(!n) break;
}
return s;
}
Using this as your strcpy function in the function func
will fail to give the expected result.
The Standard's description of function memmove describes
the behavior is AS IF the characters(number: strlen(p+strlen(sub))
pointed to by p+strlen(sub) are first copied to a seperate
temporary object. Therefore this function would be safe
to use in the code above. There is no overlapping problem.

Of the two, I would stick with function memmove.

--
Al Bowers
Tampa, Fl USA
mailto: xa******@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/

Nov 14 '05 #3

becte wrote:
I am little bit confused
Is this a legal way of removing a substring
from a string? What about the second alternative
using strcpy, is it ok even though the source and
dest. strings overlap?

// Remove (first occurence of) sub from src
void func(char *src, char *sub)
{
char *p;
if ((p=strstr(src,sub)) != NULL)
{
memmove(p,p+strlen(sub), strlen(p+strlen(sub))+1);

// alternative
// strcpy(p,p+strlen(sub));
}
}


Since the source and destination operands overlap, memmove() is your
safest bet. Don't use strcpy() for something like this, ever.

Also, for newsgroups, don't use // comments because of wordwrapping
issues.

Gregory Pietsch

Nov 14 '05 #4

Eric Sosman wrote:
becte wrote:
I am little bit confused
Is this a legal way of removing a substring
from a string? What about the second alternative
using strcpy, is it ok even though the source and
dest. strings overlap?

// Remove (first occurence of) sub from src
void func(char *src, char *sub)
{
char *p;
if ((p=strstr(src,sub)) != NULL)
{
memmove(p,p+strlen(sub), strlen(p+strlen(sub))+1);


Looks all right to me.
// alternative
// strcpy(p,p+strlen(sub));


Undefined behavior if source and destination overlap
(i.e., if strlen(p+strlen(sub)) >= strlen(sub)).
}
}


That doesn't overlap. See
http://groups-beta.google.com/group/...8?dmode=source

imagine that you have, "aabbccdd"
and you search for the substring "dd"
then p points to the first "d" and
p + strlen(sub) would point one past the
second "d". This means a distinct value of
an object is used to assign to another
distinct object. Overlap does not mean
any two pointers pointing in the same
memory region. It is an overlap when
the objects within the memory region
are not distinct. Consider this:

strcpy(p + 3, p); p overlaps p + 3 here
the converse cannot be said for p+offset
overlapping p.

--
aegis

Nov 14 '05 #5


aegis wrote:
Eric Sosman wrote:
becte wrote:

I am little bit confused
Is this a legal way of removing a substring
from a string? What about the second alternative
using strcpy, is it ok even though the source and
dest. strings overlap?

// Remove (first occurence of) sub from src
void func(char *src, char *sub)
{
char *p;
if ((p=strstr(src,sub)) != NULL)
{
memmove(p,p+strlen(sub), strlen(p+strlen(sub))+1);


Looks all right to me.

// alternative
// strcpy(p,p+strlen(sub));


Undefined behavior if source and destination overlap
(i.e., if strlen(p+strlen(sub)) >= strlen(sub)).

}
}

That doesn't overlap. See
http://groups-beta.google.com/group/...8?dmode=source

imagine that you have, "aabbccdd"
and you search for the substring "dd"
then p points to the first "d" and
p + strlen(sub) would point one past the
second "d". This means a distinct value of
an object is used to assign to another
distinct object. Overlap does not mean
any two pointers pointing in the same
memory region. It is an overlap when
the objects within the memory region
are not distinct. Consider this:

strcpy(p + 3, p); p overlaps p + 3 here
the converse cannot be said for p+offset
overlapping p.


No, there is an overlap problem. For strcpy(), the Standard does
not define in what order the characters from the string(arg 2)
are copied to the character array(arg1). Among possiblities,
an implementor may copy from the beginning of the string to the
end terminating character, as in function Mystrcpy1 example below.
Another possibility is for the implementor to copy to the character
array from the string's terminating character to the beginning of the
string, as shown in the function Mystrcpy2 example below.

Now, take the string "aabbccdd", and, attempt to remove the
substring "cc". It the implementor made strcpy like the Mystrcpy1
example, you will get away with using the strcpy. But, if the
the implementation was similiar to function Mystrcpy2 then the
resulting string will be wrong, "aabb" instead of "aabbdd".

Run the following to see the effect.

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

char *Mystrcpy1(char *s, const char *cs);
char *Mystrcpy2(char *s, const char *cs);
void func1(char *src, char *sub);
void func2(char *src, char *sub);

int main(void)
{
char s[32], *substr = "cc";

Mystrcpy2(s,"aabbccdd");
printf("From the string: \"%s\"\n",s);
printf("We will attempt to remove substring \"%s\"\n",substr);
func1(s,substr);
printf("Using function Mystrcpy1. The result: \"%s\"\n\n",s);

Mystrcpy2(s,"aabbccdd");
printf("From the string: \"%s\"\n",s);
printf("We will attempt to remove substring \"%s\"\n",substr);
func2(s,substr);
printf("Using function Mystrcpy2. The result: \"%s\"\n",s);
return 0;
}

char *Mystrcpy1(char *s, const char *cs)
{ /* Copy from beginning of string cs to the end */
char *s1;
const char *cs1;

for(s1 = s,cs1 = cs; '\0' != (*s1 = *cs1); s1++,cs1++) ;
return s;
}

char *Mystrcpy2(char *s, const char *cs)
{ /* Copy from the end of string cs to the beginning */
const char *tmp;
size_t n = strlen(cs);

for(tmp = cs+n; ; tmp--,n--)
{
*(s+n) = *tmp;
if(!n) break;
}
return s;
}

void func1(char *src, char *sub)
{ /* Using function Mystrcpy1 */
char *p;

if ((p=strstr(src,sub)) != NULL)
Mystrcpy1(p,p+strlen(sub));
return;
}

void func2(char *src, char *sub)
{ /* Using function Mystrcpy2 */
char *p;

if ((p=strstr(src,sub)) != NULL)
Mystrcpy2(p,p+strlen(sub));
return;
}

--
Al Bowers
Tampa, Fl USA
mailto: xa******@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/

Nov 14 '05 #6
aegis wrote:
Eric Sosman wrote:
becte wrote:

I am little bit confused
Is this a legal way of removing a substring
from a string? What about the second alternative
using strcpy, is it ok even though the source and
dest. strings overlap?

// Remove (first occurence of) sub from src
void func(char *src, char *sub)
{
char *p;
if ((p=strstr(src,sub)) != NULL)
{
[...]
// alternative
// strcpy(p,p+strlen(sub));


Undefined behavior if source and destination overlap
(i.e., if strlen(p+strlen(sub)) >= strlen(sub)).


That doesn't overlap. See
http://groups-beta.google.com/group/...8?dmode=source

imagine that you have, "aabbccdd"
and you search for the substring "dd"
then p points to the first "d" and
p + strlen(sub) would point one past the
second "d". [...]


Then strlen(p+strlen(sub)) will be zero and
strlen(sub) will be two. 0 >= 2 yields "false."

--
Eric Sosman
es*****@acm-dot-org.invalid
Nov 14 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

23 posts views Thread by Peter Row | last post: by
2 posts views Thread by Patrick.O.Ige | last post: by
2 posts views Thread by ankit | last post: by
reply views Thread by nhmark64 | last post: by
1 post views Thread by Gene Kelley | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.