Search code examples
c++stdstring

In what case std::basic_string::find with a count argument greater than the string length can be useful?


One of the signatures of std::basic_string::find method is:

size_type find( const CharT* s, size_type pos, size_type count ) const;

The parameters are the following:

pos    - position at which to start the search

count - length of substring to search for

s         - pointer to a character string to search for

The description of the behavior of the method for this overload is:

Finds the first substring equal to the range [s, s+count). This range may contain null characters.

I would like to know in what case it can be useful to have a range that contain null characters. For instance:

s.find("A", 0, 2);

Here, s corresponds to a string with a length of 1. Because count is 2, the range [s, s+count) contains a null character. What is the point?


Solution

  • There is a false premise that you didn't spell out, but combining the title and the question it is:

    The null character indicates the end of a std::string.

    This is wrong. std::strings can contain null characters at any position. One has to be cautious with functions that expect a null-terminated c-string, but find is so nice that it explicitly reminds you that it also works in the general case.

    C-Strings are null terminated, hence this:

    std::string x("My\0str0ing\0with\0null\0characters");
    std::cout << x.size() << '\n';
    

    Prints: 2, ie only characters before the \0 are used to constuct the std::string.

    However, this

    std::string s("Hello world");
    s[5] = '\0';
    std::cout << s << '\n';
    

    Prints Helloworld (because \0 is not printable). Also char arrays can contain \0 at any postition. Usually this is interpreted as the terminating character of the string. However, as std::strings can contain null characters at any position, it is just consistent to provide also an overload that takes pointer to a character array that can contain null characters in the middle. An example for the usage of that overload is (s is the string from above)

    std::string f;
    f.push_back('\0');
    f.push_back('w');
    std::cout << s.find(f.c_str()) << '\n';
    std::cout << s.find("") << '\n';
    std::cout << s.find(f.c_str(),0,2) << '\n';
    

    Output:

    0
    0
    5
    

    The overload without the count parameter assumes a null terminated c-string, hence s.find(f.c_str()) is the same as s.find(""). Only with the overload that has the count paramter the substring \0w is found at index 5.