90

I need to check whether an std:string begins with "xyz". How do I do it without searching through the whole string or creating temporary strings with substr().

Alexis Wilke
  • 15,168
  • 8
  • 60
  • 116
jackhab
  • 15,012
  • 32
  • 92
  • 129

5 Answers5

164

I would use compare method:

std::string s("xyzblahblah");
std::string t("xyz")

if (s.compare(0, t.length(), t) == 0)
{
// ok
}
Wacek
  • 4,246
  • 2
  • 17
  • 28
  • I'd forgotten about compare - this is the best method, but there is no need to use c_str(0 to get a character string –  May 31 '09 at 11:27
  • You can do string s("xyz") == "xyz" too. :) – Skurmedel May 31 '09 at 11:29
  • Neil, you're absolutely right, I edited answer and removed c_str() call – Wacek May 31 '09 at 11:36
  • 3
    Why don't you simply use s.compare(t)? – Franck Mesirard Jun 24 '09 at 13:17
  • 5
    @FranckMesirard: That's because by default _compare_ would try to compare the whole length of the passed string against the member data and would return false, while giving the length as the passed parameter's length would make it return true (meaning _std::basic_string::compare_, when used with offset & length, can be made use of like String.BeginsWith() in other libraries.) Without the offset and length, this wouldn't be true. – legends2k Nov 04 '11 at 14:53
  • 1
    This returns true if t is empty. – gliderkite Jul 06 '12 at 17:12
  • 14
    @gliderkite As it should ... the empty string is an initial prefix of every string. – Jim Balter Nov 05 '14 at 21:33
  • 1
    As it should is correct... If you want to rule out empty strings: if (!t.empty() && !s.compare(0, t.length(), t)) – ericcurtin Jun 20 '18 at 08:52
14

An approach that might be more in keeping with the spirit of the Standard Library would be to define your own begins_with algorithm.

#include <algorithm>
using namespace std;


template<class TContainer>
bool begins_with(const TContainer& input, const TContainer& match)
{
    return input.size() >= match.size()
        && equal(match.begin(), match.end(), input.begin());
}

This provides a simpler interface to client code and is compatible with most Standard Library containers.

Paweł Bylica
  • 2,785
  • 25
  • 40
Neutrino
  • 6,048
  • 4
  • 37
  • 64
  • Cool! This should be added to boost! – David Apr 25 '14 at 19:40
  • 2
    @David: If boost is a allowed dependency, see boost::algorithm::[starts_with](http://www.boost.org/doc/libs/1_65_1/doc/html/boost/algorithm/starts_with.html) — 'Starts with' predicate – Gabor Oct 08 '17 at 10:06
10

Look to the Boost's String Algo library, that has a number of useful functions, such as starts_with, istart_with (case insensitive), etc. If you want to use only part of boost libraries in your project, then you can use bcp utility to copy only needed files

Alex Ott
  • 49,058
  • 5
  • 62
  • 91
4

It seems that std::string::starts_with is inside C++20, meanwhile std::string::find can be used

std::string s1("xyzblahblah");
std::string s2("xyz")

if (s1.find(s2) == 0)
{
   // ok, s1 starts with s2
}
Alejadro Xalabarder
  • 1,243
  • 17
  • 13
  • 1
    This is much better than the accepted answer using `std::string::compare` because it makes it easy to check if the string begins with a literal without repeating the literal itself to find its size. And thanks for pointing to the C++20 direct solution. – Ruslan Sep 10 '19 at 10:45
  • If s1 does not begin with s2, this will still try to match it afterwards, which is not as good as compare(). – A117 Nov 26 '19 at 02:31
0

I feel I'm not fully understanding your question. It looks as though it should be trivial:

s[0]=='x' && s[1]=='y' && s[2]=='z'

This only looks at (at most) the first three characters. The generalisation for a string which is unknown at compile time would require you to replace the above with a loop:

// look for t at the start of s
for (int i=0; i<s.length(); i++)
{
  if (s[i]!=t[i])
    return false;
}
1800 INFORMATION
  • 119,313
  • 29
  • 152
  • 234
  • Well, I know how to compare strings in using C functions. My question was about doing it object-oriented way by means of C++ STL. – jackhab May 31 '09 at 11:01
  • There is no C function being used here. And the Standard Library does not preclude you from writing unctions of your own. –  May 31 '09 at 11:05
  • 6
    and what if t is shorter than s? – vidstige Jan 22 '13 at 14:00
  • @jackhab The author of STL says "STL is not object oriented. I think that object orientedness is almost as much of a hoax as Artificial Intelligence." -- http://www.stlport.org/resources/StepanovUSA.html – Jim Balter Nov 05 '14 at 21:38
  • 1
    @vidstige Then the loop terminates when it encounters the terminating NUL in `t`. – Jim Balter Nov 05 '14 at 21:39
  • @JimBalter That's probably the stupidest thing Stephanov ever said. OOD/OOP has been prevalent in system development for the last 20 years as a result of its unparalled ability to manage complexity. Generic programming has also become ubiquitous in that time, but it is more likely to be used for internal implementation instead of for high level components and client interfaces. We have learned to use the two together. – Neutrino Feb 16 '18 at 16:47
  • @Neutrino The issue isn't whether Stepanov is right or wrong about OO, it's whether the STL is OO. (It's not, of course.) – Jim Balter Feb 17 '18 at 12:06
  • @JimBalter I think that's debatable. STL classes expose their functionality through an interface behind which they hide private implementation and they can be composed and subclassed just like other OO types. Being generic their interface does not fully insulate the client from their implementation to the extent that a non-generic implementation would, but I don't think that means they are not OO at all. – Neutrino Feb 19 '18 at 10:13
  • It's not debatable when its creator says that the STL is not OO ... and when the above argument is utter nonsense; the fact that STL containers are implemented as C++ classes doesn't make the STL OO. – Jim Balter Feb 20 '18 at 02:03