58

Is there any way in C++ to check whether a string starts with a certain string (smaller than the original) ? Just like we can do in Java

bigString.startswith(smallString);
cpx
  • 17,009
  • 20
  • 87
  • 142
sufyan siddique
  • 1,461
  • 4
  • 13
  • 14

11 Answers11

89
std::string s("Hello world");

if (s.find("Hello") == 0)
{
    std::cout << "String starts with Hello\n";
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • @avakar I agree. I haven't tried the C++11 regular expressions yet, but that would also be a solution, and hopefully more efficient? – Some programmer dude Nov 11 '11 at 14:22
  • 3
    I think regex is a bad choice for such a simple check, see my answer for what I think is an efficient solution for this problem. Or even better Alan Stokes reply with string::compare(). – Kleist Nov 11 '11 at 14:24
  • 5
    An efficient solution should be `O(min(bigString.length(), smallString.length()))` – Alan Stokes Nov 11 '11 at 14:26
  • 17
    @sufyansiddique Simple, yes. Effective, not so very. If `smallString` is not longer than `bigString`, you only have to compare the first `smallString.size()` characters to know the answer; you don't have to search the entire `bigString` for a `smallString` other than at the initial position. – James Kanze Nov 11 '11 at 15:20
  • 2
    As others have commented, this can't be a very efficient idea if the string you're searching is really long and the string you're looking for is really short. Why iterate through the whole string when you're only interested in the bit at the beginning? – Dawood ibn Kareem May 05 '17 at 06:26
  • 1
    what if the "Hello" appears at the last or in middle? I think this program is supposed to find any occurence of a particular substring, not meant for "starts with". I think boost string algorithm is good option for this. Refer to https://stackoverflow.com/questions/1878001/how-do-i-check-if-a-c-string-starts-with-a-certain-string-and-convert-a-sub – Abhishek Chatterjee Jul 05 '17 at 08:38
  • 1
    @AbhishekChatterjee It's the comparison of the result from `find` with zero that does the "starts with" part. – Some programmer dude Jul 05 '17 at 08:40
  • Why not use: `if (s.rfind("Hello", 0) == 0) {` – Melroy van den Berg Dec 10 '20 at 16:49
70

You can do this with string::compare(), which offers various options for comparing all or parts of two strings. This version compares smallString with the appropriate size prefix of bigString (and works correctly if bigString is shorter than smallString):

bigString.compare(0, smallString.length(), smallString) == 0

I tend to wrap this up in a free function called startsWith(), since otherwise it can look a bit mysterious.

UPDATE: C++20 is adding new starts_with and ends_with functions, so you will finally be able to write just bigString.starts_with(smallString).

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
32

The approaches using string::find() or string::substr() are not optimal since they either make a copy of your string, or search for more than matches at the beginning of the string. It might not be an issue in your case, but if it is you could use the std::equal algorithm. Remember to check that the "haystack" is at least as long as the "needle".

#include <string>    

using namespace std;

bool startsWith(const string& haystack, const string& needle) {
    return needle.length() <= haystack.length() 
        && equal(needle.begin(), needle.end(), haystack.begin());
}
Kleist
  • 7,785
  • 1
  • 26
  • 30
10

The correct solution, as always, comes from Boost: boost::algorithm::starts_with.

avakar
  • 32,009
  • 9
  • 68
  • 103
  • 21
    Awful to use boost just to do this simple task. – Borzh May 15 '14 at 14:38
  • 3
    @Borzh, surely, you're already using Boost heavily in your projects, why not for this? – avakar May 16 '14 at 16:27
  • 50
    Not everyone uses boost. And to download it, put it in repository just to use starts_with() is a little exaggerating. Maybe you should consider remove "The correct solution, as always...". It is nor "correct" neither "always". – Borzh May 20 '14 at 15:01
  • 1
    I'm with avakar. In my eyes this *is* the correct solution. BTW you have to include boost/algorithm/string.hpp – anhoppe Oct 09 '15 at 08:26
  • 11
    Agree with Borzh. Not all projects use boost (far from it), so 'always' and 'correct' words do not belong here. To add this monstrosity to a project where STL or simple strcmp would work is madness. – Alex Dec 19 '15 at 09:51
  • I second (third?) Borzh and Alex. This is useful only if you are already using Boost, and even then it's arrogant to call it "_the_ correct solution" – it's not _wrong_, it's not _bad_, but The Boost Way is not the only way. – JuSTMOnIcAjUSTmONiCAJusTMoNICa Aug 04 '17 at 18:03
5

With C++20 you can use std::basic_string::starts_with (or std::basic_string_view::starts_with):

#include <string_view>

std::string_view bigString_v("Winter is gone"); // std::string_view avoids the copy in substr below.
std::string_view smallString_v("Winter");
if (bigString_v.starts_with(smallString_v))
{
    std::cout << "Westeros" << bigString_v.substr(smallString_v.size());
}
Roi Danton
  • 7,933
  • 6
  • 68
  • 80
4

To optimize a little bit:

if ( smallString.size() <= bigString.size() &&
     strncmp( smallString.c_str(), bigString.c_str(), smallString.length() ) == 0 )

Don't forget to #include <cstring> or #include <string.h>

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
Borzh
  • 5,069
  • 2
  • 48
  • 64
1

strstr() returns a pointer to the first occurrence of a string within a string.

makes
  • 6,438
  • 3
  • 40
  • 58
rogerlsmith
  • 6,670
  • 2
  • 20
  • 25
1

The simplest approach would be:

if ( smallString.size() <= bigString.size()
    && std::equals( smallString.begin(), smallString.end(), bigString.end() )

(This will also work if one of the two, or both, is a vector. Or any other standard container type.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • 1
    -1 1) I cannot find any std::equals. Did you mean std::equal? 2) are you sure with bigString.end() - one would expect bigString.begin()? 3) answer by Kleist posted before seems to get all of this right – Suma Jul 24 '12 at 23:35
  • Yes, to both. It's `std::equal`, and it should be `bigString.end()`. – James Kanze Jul 29 '12 at 15:26
0

I thought it makes sense to post a raw solution that doesn't use any library functions...

// Checks whether `str' starts with `start'
bool startsWith(const std::string& str, const std::string& start) {
    if (&start == &str) return true; // str and start are the same string
    if (start.length() > str.length()) return false;
    for (size_t i = 0; i < start.length(); ++i) {
        if (start[i] != str[i]) return false;
    }
    return true;
}

Adding a simple std::tolower we can make this case insensitive

// Checks whether `str' starts with `start' ignoring case
bool startsWithIgnoreCase(const std::string& str, const std::string& start) {
    if (&start == &str) return true; // str and start are the same string
    if (start.length() > str.length()) return false;
    for (size_t i = 0; i < start.length(); ++i) {
        if (std::tolower(start[i]) != std::tolower(str[i])) return false;
    }
    return true;
}
cute_ptr
  • 1,103
  • 9
  • 12
-1

Either create a substring that is the length of your smallString variable, and compare the two. Or do a search for the substring smallString and see if it returns index 0

Dan F
  • 17,654
  • 5
  • 72
  • 110
-1

http://www.cplusplus.com/reference/string/string/substr/

You can use string.substr() to see any number of characters from any position, or you could use a string.find() member.

John Humphreys
  • 37,047
  • 37
  • 155
  • 255