Check if one string is a prefix of another

C++String ComparisonPrefix

C++ Problem Overview


I have two strings which I'd like to compare: String and String:. Is there a library function that would return true when passed these two strings, but false for say String and OtherString?

To be precise, I want to know whether one string is a prefix of another.

C++ Solutions


Solution 1 - C++

Use std::mismatch. Pass in the shorter string as the first iterator range and the longer as the second iterator range. The return is a pair of iterators, the first is the iterator in the first range and the second, in the second rage. If the first is end of the first range, then you know the the short string is the prefix of the longer string e.g.

std::string foo("foo");
std::string foobar("foobar");

auto res = std::mismatch(foo.begin(), foo.end(), foobar.begin());

if (res.first == foo.end())
{
  // foo is a prefix of foobar.
}

Solution 2 - C++

If you know which string is shorter, the procedure is simple, just use std::equal with the shorter string first. If you don't, something like the following should work:

bool
unorderIsPrefix( std::string const& lhs, std::string const& rhs )
{
    return std::equal(
        lhs.begin(),
        lhs.begin() + std::min( lhs.size(), rhs.size() ),
        rhs.begin() );
}

Solution 3 - C++

This is both efficient and convenient:

str.compare(0, pre.size(), pre) == 0

compare is fast because it uses the fast traits::compare method and doesn't have to copy any data.

Here, it will compare std::min(str.size(), pre.size()) characters but if the characters in the two ranges are equal it also checks the length of pre and returns a non-zero value if pre is longer than this.

See the documentation at cplusplus.com.

I've written a test program that uses this code to compare prefixes and strings given on the command line.

Solution 4 - C++

std::string(X).find(Y) is zero if and only if Y is a prefix of X

Solution 5 - C++

With string::compare, you should be able to write something like:

bool match = (0==s1.compare(0, min(s1.length(), s2.length()), s2,0,min(s1.length(),s2.length())));

Alternatively, in case we don't want to use the length() member function:

bool isPrefix(string const& s1, string const&s2)
{
    const char*p = s1.c_str();
    const char*q = s2.c_str();
    while (*p&&*q)
        if (*p++!=*q++)
            return false;
    return true;
}

Solution 6 - C++

If you can reasonably ignore any multi-byte encodings (say, UTF-8) then you can use strncmp for this:

// Yields true if the string 's' starts with the string 't'.
bool startsWith( const std::string &s, const std::string &t )
{
    return strncmp( s.c_str(), t.c_str(), t.size() ) == 0;
}

If you insist on using a fancy C++ version, you can use the std::equal algorithm (with the added benefit that your function also works for other collections, not just strings):

// Yields true if the string 's' starts with the string 't'.
template <class T>
bool startsWith( const T &s, const T &t )
{
    return s.size() >= t.size() &&
           std::equal( t.begin(), t.end(), s.begin() );
}

Solution 7 - C++

After C++20, we can use starts_with to check if a string begins with given prefix.

str.starts_with(prefix)

Also, there is ends_with to check suffix

Solution 8 - C++

How about simply:

bool prefix(const std::string& a, const std::string& b) {
  if (a.size() > b.size()) {
    return a.substr(0,b.size()) == b;
  }
  else {
    return b.substr(0,a.size()) == a;
  }
}

C++ not C, safe, simple, efficient.

Tested with:

#include <string>
#include <iostream>

bool prefix(const std::string& a, const std::string& b);

int main() {
  const std::string t1 = "test";
  const std::string t2 = "testing";
  const std::string t3 = "hello";
  const std::string t4 = "hello world";
  std::cout << prefix(t1,t2) << "," << prefix(t2,t1) << std::endl;
  std::cout << prefix(t3,t4) << "," << prefix(t4,t3) << std::endl;
  std::cout << prefix(t1,t4) << "," << prefix(t4,t1) << std::endl;
  std::cout << prefix(t1,t3) << "," << prefix(t3,t1) << std::endl;

}

If you have C++17 you can write a better version of this, using std::string_view instead:

#include <string>
#include <string_view>

bool prefix(const std::string& a, const std::string& b) {
  if (a.size() > b.size()) {
    return std::string_view(a.c_str(),b.size()) == b;
  }
  else {
    return std::string_view(b.c_str(),a.size()) == a;
  }
}

With g++ 7 at -O3 this collapses to a single memcmp call, which is a fairly substantial improvement over the older version.

Solution 9 - C++

Easiest way is to use substr() and compare() member functions:

string str = "Foobar";
string prefix = "Foo";

if(str.substr(0, prefix.size()).compare(prefix) == 0) cout<<"Found!";

Solution 10 - C++

You can use this:

for c++14 or less

bool has_prefix
	(const std::string& str, const std::string& prefix)  {
	return str.find(prefix, 0) == 0;
}

for c++17

//it's a little faster
auto has_prefix
	(const std::string& str, const std::string_view& prefix) -> decltype(str.find(prefix) == 0) {
	return str.find(prefix, 0) == 0;
}

Solution 11 - C++

I think strncmp is the closest to what you're looking for.

Though, if reworded, you may be looking for strstr(s2,s1)==s2, which is not necessarily the most performant way to do that. But you do not want to work out n ;-)

Okay, okay, the c++ version would be !s1.find(s2).

Okay, you can make it even more c++, something like this: std::mismatch(s1.begin(),s1.end(),s2.begin()).first==s1.end().

Solution 12 - C++

str1.find(str2) returns 0 if entire str2 is found at the index 0 of str1:

#include <string>
#include <iostream>

// does str1 have str2 as prefix?
bool StartsWith(const std::string& str1, const std::string& str2)
{	
	return (str1.find(str2)) ? false : true;
}

// is one of the strings prefix of the another?
bool IsOnePrefixOfAnother(const std::string& str1, const std::string& str2)
{   
    return (str1.find(str2) && str2.find(str1)) ? false : true;
}

int main()
{
    std::string str1("String");
    std::string str2("String:");
    std::string str3("OtherString");

    if(StartsWith(str2, str1))
    {
	    std::cout << "str2 starts with str1" << std::endl;		
    }
    else
    {
	    std::cout << "str2 does not start with str1" << std::endl;
    }

    if(StartsWith(str3, str1))
    {
	    std::cout << "str3 starts with str1" << std::endl;		
    }
    else
    {
	    std::cout << "str3 does not start with str1" << std::endl;
    }

        if(IsOnePrefixOfAnother(str2, str1))
        {
            std::cout << "one is prefix of another" << std::endl;      
        }
        else
        {
            std::cout << "one is not prefix of another" << std::endl;
        }

        if(IsOnePrefixOfAnother(str3, str1))
        {
            std::cout << "one is prefix of another" << std::endl;      
        }
        else
        {
            std::cout << "one is not prefix of another" << std::endl;
        }
        
    return 0;
}

Output:

  str2 starts with str1
  str3 does not start with str1
  one is prefix of another
  one is not prefix of another

Solution 13 - C++

What's wrong with the "find" and checking the result for position 0 ?

string a = "String";
string b = "String:";

if(b.find(a) == 0)
{
// Prefix

}
else
{
// No Prefix
}

Solution 14 - C++

bool IsPrefix(const std::string& prefix, const std::string& whole)
{
  return whole.size() >= prefix.size() && whole.compare(0, prefix.size(), prefix) == 0;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionfredleyView Question on Stackoverflow
Solution 1 - C++NimView Answer on Stackoverflow
Solution 2 - C++James KanzeView Answer on Stackoverflow
Solution 3 - C++Neil MayhewView Answer on Stackoverflow
Solution 4 - C++MSaltersView Answer on Stackoverflow
Solution 5 - C++VladView Answer on Stackoverflow
Solution 6 - C++Frerich RaabeView Answer on Stackoverflow
Solution 7 - C++RY_ ZhengView Answer on Stackoverflow
Solution 8 - C++FlexoView Answer on Stackoverflow
Solution 9 - C++user2180737View Answer on Stackoverflow
Solution 10 - C++xninjaView Answer on Stackoverflow
Solution 11 - C++Michael Krelin - hackerView Answer on Stackoverflow
Solution 12 - C++Bojan KomazecView Answer on Stackoverflow
Solution 13 - C++João AugustoView Answer on Stackoverflow
Solution 14 - C++user31264View Answer on Stackoverflow