Another testsuite patch and a bug in string.find

Nathan Myers ncm@cantrip.org
Wed Jun 14 03:45:00 GMT 2000


On Tue, Jun 13, 2000 at 04:45:49PM -0700, Benjamin Kosnik wrote:
> Nathan, did you get a chance to review this? If this is indeed a 
> bug, or a change in this behavior is necessary, then perhaps string 
> should be fixed?

I agree that it's a bug in basic_string<>.
Thank you, Anthony, for reporting it.

Here is what the standard says:

  21.3.6.1 - basic_string::find [lib.string::find]
      size_type find(const basic_string<charT,traits,Allocator>& str,
                     size_type pos = 0) const;
  -1- Effects: Determines the lowest position xpos , if possible,
  such that both of the following conditions obtain:
      . pos <= xpos and xpos + str.size() <= size(); 
      . at(xpos+I) == str.at(I) for all elements I of the string 
         controlled by str . 
  -2- Returns: xpos if the function can determine such a value for
  xpos. Otherwise, returns npos.

To me, this implies that find() should return i for all positions
in Anthony's example below, including position 5.  That is, for 
an empty string argument str, only the first condition above need 
be met, and it is clearly met for the case of 5.  In the test case,
then, it should report _npos_ on an empty-string argument only for
_pos_ > size(), not >=.

Nathan Myers
ncm at cantrip dot org
 
----------------------------
> On Wed, 7 Jun 2000, Anthony Williams wrote:
> > Here is a patch to testsuite/21_strings/find.cc, which I think makes
> > it more standard compliant.
> > 
> > The patch relates to empty strings. An empty string object contains
> > no characters, so I believe that it should be found at all positions,
> > and the following code should produce the given output. This
> > highlights a bug in string.find, since libstdc++ produces the second
> > set of output.
> > 
> > include <iostream>
> > #include <string>
> >  
> > int main()
> > {
> >     std::string a("hello");
> >     std::string b;
> >  
> >     for(unsigned i=0;i<=a.size();++i)
> >         std::cout<<a.find(b,i)<<std::endl;
> > }
> >  
> > Expected output:
> > 0
> > 1
> > 2
> > 3
> > 4
> > 4294967295
> >  
> > libstdc++-v3 output:
> > 5
> > 5
> > 5
> > 5
> > 5
> > 5
> > 
> > Anthony
> > 
> > testsuite/21_strings/find.cc: Empty strings can be found at all
> > positions
> > 
> > Index: find.cc
> > ===================================================================
> > RCS file: /cvs/gcc/egcs/libstdc++-v3/testsuite/21_strings/find.cc,v
> > retrieving revision 1.1
> > diff -u -p -r1.1 find.cc
> > - --- find.cc     2000/04/21 20:33:33     1.1
> > +++ find.cc     2000/06/07 10:36:09
> > @@ -56,21 +56,22 @@ bool test01(void)
> >    test &= csz01 == 8;
> >    csz01 = str01.find(str03, 12);
> >    test &= csz01 == npos;
> > - -  // It is implementation-defined if a given string contains an
> > empty
> > - -  // string. The only two times a char_type() (== empty string)
> > ending
> > - -  // element is required to be part of the string is on c_str() and
> > - -  // operator[size()] const: the indeterminate, stored state of the
> > - -  // string can vary, and not include a terminal char_type().
> > +
> > +  // An empty string consists of no characters
> > +  // therefore it should be found at every point in a string,
> > +  // except beyond the end
> >    csz01 = str01.find(str04, 0);
> > - -  test &= csz01 == npos || csz01 == str01.size();
> > +  test &= csz01 == 0; 
> >    csz01 = str01.find(str04, 5);
> > - -  test &= csz01 == npos || csz01 == str01.size();
> > +  test &= csz01 == 5; 
> > +  csz01 = str01.find(str04, str01.size());
> > +  test &= csz01 == npos; 
> >    
> >    // size_type find(const char* s, size_type pos, size_type n)
> > const;
> >    csz01 = str01.find(str_lit01, 0, 3);
> >    test &= csz01 == 0;
> >    csz01 = str01.find(str_lit01, 3, 0);
> > - -  test &= csz01 == npos;
> > +  test &= csz01 == 3; // zero length string should be found at pos
> >  
> >    // size_type find(const char* s, size_type pos = 0) const;
> >    csz01 = str01.find(str_lit01);
> > @@ -107,15 +108,15 @@ bool test01(void)
> >    csz01 = str01.find_first_of(str05, 4);
> >    test &= csz01 == 4;
> >  
> > - -  // It is implementation-defined if a given string contains an
> > empty
> > - -  // string. The only two times a char_type() (== empty string)
> > ending
> > - -  // element is required to be part of the string is on c_str() and
> > - -  // operator[size()] const: the indeterminate, stored state of the
> > - -  // string can vary, and not include a terminal char_type().
> > +  // An empty string consists of no characters
> > +  // therefore it should be found at every point in a string,
> > +  // except beyond the end
> > +  // However, str1.find_first_of(str2,pos) finds the first character
> > in 
> > +  // str1 (starting at pos) that exists in str2, which is none for
> > empty str2
> >    csz01 = str01.find_first_of(str04, 0);
> > - -  test &= csz01 == npos || csz01 == str01.size();
> > +  test &= csz01 == npos; 
> >    csz01 = str01.find_first_of(str04, 5);
> > - -  test &= csz01 == npos || csz01 == str01.size();
> > +  test &= csz01 == npos; 
> >    
> >    // size_type find_first_of(const char* s, size_type pos, size_type
> > n) const;
> >    csz01 = str01.find_first_of(str_lit01, 0, 3);


More information about the Libstdc++ mailing list