removing substring from string

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • becte

    #1

    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+str len(sub), strlen(p+strlen (sub))+1);

    // alternative
    // strcpy(p,p+strl en(sub));
    }
    }
  • Eric Sosman

    #2
    Re: removing substring from string

    becte wrote:
    [color=blue]
    > 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+str len(sub), strlen(p+strlen (sub))+1);[/color]

    Looks all right to me.
    [color=blue]
    > // alternative
    > // strcpy(p,p+strl en(sub));[/color]

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

    Comment

    • Al Bowers

      #3
      Re: removing substring from string



      becte wrote:[color=blue]
      > 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+str len(sub), strlen(p+strlen (sub))+1);
      >
      > // alternative
      > // strcpy(p,p+strl en(sub));
      > }
      > }[/color]

      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(numb er: 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: xabowers@myrapi dsys.com (remove the x to send email)
      Latest news coverage, email, free stock quotes, live scores and video are just the beginning. Discover more every day at Yahoo!


      Comment

      • Gregory Pietsch

        #4
        Re: removing substring from string


        becte wrote:[color=blue]
        > 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+str len(sub), strlen(p+strlen (sub))+1);
        >
        > // alternative
        > // strcpy(p,p+strl en(sub));
        > }
        > }[/color]

        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

        Comment

        • aegis

          #5
          Re: removing substring from string


          Eric Sosman wrote:[color=blue]
          > becte wrote:
          >[color=green]
          > > 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+str len(sub), strlen(p+strlen (sub))+1);[/color]
          >
          > Looks all right to me.
          >[color=green]
          > > // alternative
          > > // strcpy(p,p+strl en(sub));[/color]
          >
          > Undefined behavior if source and destination overlap
          > (i.e., if strlen(p+strlen (sub)) >= strlen(sub)).
          >[color=green]
          > > }
          > > }[/color][/color]

          That doesn't overlap. See


          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

          Comment

          • Al Bowers

            #6
            Re: removing substring from string



            aegis wrote:
            [color=blue]
            > Eric Sosman wrote:
            >[color=green]
            >>becte wrote:
            >>
            >>[color=darkred]
            >>>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+str len(sub), strlen(p+strlen (sub))+1);[/color]
            >>
            >> Looks all right to me.
            >>
            >>[color=darkred]
            >>> // alternative
            >>> // strcpy(p,p+strl en(sub));[/color]
            >>
            >> Undefined behavior if source and destination overlap
            >>(i.e., if strlen(p+strlen (sub)) >= strlen(sub)).
            >>
            >>[color=darkred]
            >>> }
            >>>}[/color][/color]
            >
            >
            > 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.
            >[/color]

            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,"aa bbccdd");
            printf("From the string: \"%s\"\n",s) ;
            printf("We will attempt to remove substring \"%s\"\n",subst r);
            func1(s,substr) ;
            printf("Using function Mystrcpy1. The result: \"%s\"\n\n", s);

            Mystrcpy2(s,"aa bbccdd");
            printf("From the string: \"%s\"\n",s) ;
            printf("We will attempt to remove substring \"%s\"\n",subst r);
            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+s trlen(sub));
            return;
            }

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

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

            --
            Al Bowers
            Tampa, Fl USA
            mailto: xabowers@myrapi dsys.com (remove the x to send email)
            Latest news coverage, email, free stock quotes, live scores and video are just the beginning. Discover more every day at Yahoo!


            Comment

            • Eric Sosman

              #7
              Re: removing substring from string

              aegis wrote:
              [color=blue]
              > Eric Sosman wrote:
              >[color=green]
              >>becte wrote:
              >>
              >>[color=darkred]
              >>>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+strl en(sub));[/color]
              >>
              >> Undefined behavior if source and destination overlap
              >>(i.e., if strlen(p+strlen (sub)) >= strlen(sub)).
              >>[/color]
              >
              > 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". [...][/color]

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

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

              Comment

              Working...