How do I check if a C++ std::string starts with a certain string, and convert a substring to an int?
Asked Answered
C

24

420

How do I implement the following (Python pseudocode) in C++?

if argv[1].startswith('--foo='):
    foo_value = int(argv[1][len('--foo='):])

(For example, if argv[1] is --foo=98, then foo_value is 98.)

Update: I'm hesitant to look into Boost, since I'm just looking at making a very small change to a simple little command-line tool (I'd rather not have to learn how to link in and use Boost for a minor change).

Cumming answered 10/12, 2009 at 0:57 Comment(3)
This is also interesting.Stagecraft
c++ 20 has starts_withMezuzah
@LouisGo Thank god. No more rfind()Tanjatanjore
B
825

Use rfind overload that takes the search position pos parameter, and pass zero for it:

std::string s = "tititoto";
if (s.rfind("titi", 0) == 0) { // pos=0 limits the search to the prefix
  // s starts with prefix
}

Who needs anything else? Pure STL!

Many have misread this to mean "search backwards through the whole string looking for the prefix". That would give the wrong result (e.g. string("tititito").rfind("titi") returns 2 so when compared against == 0 would return false) and it would be inefficient (looking through the whole string instead of just the start). But it does not do that because it passes the pos parameter as 0, which limits the search to only match at that position or earlier. For example:

std::string test = "0123123";
size_t match1 = test.rfind("123");    // returns 4 (rightmost match)
size_t match2 = test.rfind("123", 2); // returns 1 (skipped over later match)
size_t match3 = test.rfind("123", 0); // returns std::string::npos (i.e. not found)

For C++20 onwards it got way simpler as both std::string and std::string_view has starts_with:

std::string s = "tititoto";
if (s.starts_with("titi"s)) {
  // s starts with prefix
}
Byrne answered 5/11, 2016 at 17:36 Comment(8)
@sweisgerber.dev, I'm confused on your first contention. The return value from find will only be zero if titi is at the start of the string. If it's found somewhere else, you'll get a non-zero return value and, if it's not found, you'll get npos which is also non-zero. Assuming I'm right, I'd prefer this answer since I don't have to bring in any non-standard stuff (yes, I know Boost is everywhere, I'd just prefer core C++ libs for simple stuff like this).Colocynth
@paxdiablo: you are right, it does indeed check if it starts with titi, but the conversion part is missing.Wakeless
Do we have any evidence that this is optimized in most compilers? I don't find elsewhere mentioning either "find" or "rfind" optimization is common practice based on the return value it's checking against.Rift
@alcoforado "rfind will start from the back of the string ..." No, that only applies to the overload of rfind() that does not take a pos parameter. If you use the overload that does take a pos parameter then it will not search the whole string, only that position and earlier. (Just like regular find() with pos parameter only looks in that position or later.) So if you pass pos == 0, as shown in this answer, then it will literally only consider for matches at that one position. That was already explaining in both the answer and comments.Willy
that position or earlier is the important phrase here.Matchbox
To instead find if a string ends with another string, you can do s.find("toto", s.length() - 4) != std::string::npos. Replace the number 4 with the length of the suffix you are looking for.Wayfarer
I think it's painful that this function was omitted and you need 1) StackOverflow and 2) a whole explanation of the intrinsics of s.rfind() to get a working answer. The first thing that itches in my case is to put this method in a library. Glaring omission in STL. Thanks for the answer though. ;-)Premature
For new readers) Why rfind, instead of just find? Actually the original version of this answer used find, but it's edited to use rfind with pos=0 because it only searches once(at pos=0), whereas find needlessly keeps searching even after pos=0 if the string doesn't start with the given substring.Argot
P
210

You would do it like this:

std::string prefix("--foo=");
if (!arg.compare(0, prefix.size(), prefix))
    foo_value = std::stoi(arg.substr(prefix.size()));

Looking for a lib such as Boost.ProgramOptions that does this for you is also a good idea.

Providential answered 10/12, 2009 at 1:7 Comment(8)
The biggest problem with this is that atoi("123xyz") returns 123, whereas Python's int("123xyz") throws an exception.Callas
The workaround, we can do, is to a sscanf() and compare the result and the original, to decide whether to proceed or throw exception.Mantellone
Or just replace atoi with strtol or strtoll, which lets us detect error conditions in the input value.Callas
This is better solution than the rfind one which depends on optimization to work.Wilden
@Wilden the rfind solution does not depend on any optimization. rfind's behavior by definition is to only look at a single index when given pos=0, hence it is always an efficient check. Which syntax is more pleasant is a matter of preference.Whirl
@Callas You said atoi -- did you mean atoi or stoi?Lyda
@RaleighL. I originally used atoi in my answer, but an editor replaced it with the more modern std::stoi. Tom's comment remains valid with stoi.Providential
Looking for a lib like Boost to check whether a string has a certain prefix? This is not a good idea!Korn
F
175

Just for completeness, I will mention the C way to do it:

If str is your original string, substr is the substring you want to check, then

strncmp(str, substr, strlen(substr))

will return 0 if str starts with substr. The functions strncmp and strlen are in the C header file <string.h>

(originally posted by Yaseen Rauf here, markup added)

For a case-insensitive comparison, use strnicmp instead of strncmp.

This is the C way to do it, for C++ strings you can use the same function like this:

strncmp(str.c_str(), substr.c_str(), substr.size())
Feodor answered 22/8, 2011 at 2:58 Comment(4)
indeed, everyone seems to just go "use boost" and i for one am thankful for an stl or OS library versionTattle
Yes. However, it assumes the string has no null characters in it. If it is not the case - one should use memcmp()Intolerable
why would anyone use anything other than this simple beautiful solution?Syllogize
@AvishaiY it assumes the string has no null characters in it. That is as much of an assumption as assuming that an ìnt` does not contain the value "-0.5" - C-string contains exactly a Single null-character as the end-marker. It is by definition NOT a C-string if it contains a \0 at any other position.Vendue
C
99

If you're already using Boost, you can do it with boost string algorithms + boost lexical cast:

#include <boost/algorithm/string/predicate.hpp>
#include <boost/lexical_cast.hpp>

try {    
    if (boost::starts_with(argv[1], "--foo="))
        foo_value = boost::lexical_cast<int>(argv[1]+6);
} catch (boost::bad_lexical_cast) {
    // bad parameter
}

This kind of approach, like many of the other answers provided here is ok for very simple tasks, but in the long run you are usually better off using a command line parsing library. Boost has one (Boost.Program_options), which may make sense if you happen to be using Boost already.

Otherwise a search for "c++ command line parser" will yield a number of options.

Carolecarolee answered 10/12, 2009 at 1:3 Comment(12)
"boost::algorithm::starts_with" instead of "boost::starts_with" ?Fibrin
@nerith: Seems they both work. I've always used the shorter form.Carolecarolee
boost::starts_with and boost::algorithm::starts_with are the same thing. If you look at the end of this file svn.boost.org/svn/boost/trunk/boost/algorithm/string/… you will see this: // pull names to the boost namespace using algorithm::starts_with; [...]Capitalization
Pulling in huge dependencies for a string prefix check is like shooting birds with canons.Galatia
"Use Boost" is always the wrong answer when someone asks how to do a simple string operation in C++.Ribbentrop
minus 1 for suggesting BoostIntricate
Using boost here is right, if you already use boost in your project.Spiracle
Using boost for this is wrong if this is the reason for which you would decide to link boost in the first place, if you are already using boost for other reasons I don't see why this would be huge a problem.Hadlee
The answer is prefixed with "If you're using Boost...". Clearly this is the right answer "...if you're using Boost". If not, look the suggestion by @ProvidentialShofar
Boost is always a solution if you use C++. There's no need to reinvent the wheel when there's no need to do it. We work, we are not doing homework assigments.Rack
Boost is not a BIG library.. is a set of libraries big and smalls. If a small boost library can solve the problem I don't see the reason to avoid it.Rack
Boost might be the right answer for your situation, e.g. if outside forces limit adoption of more recent standards. Boost unfortunately exists because standard C++ libraries have been so slow to progress: string::starts_with was added in C++20 (Dec 2020) whereas Java 1.0 included String.startsWith() in 1996.Spent
R
91

Code I use myself:

std::string prefix = "-param=";
std::string argument = argv[1];
if(argument.substr(0, prefix.size()) == prefix) {
    std::string argumentValue = argument.substr(prefix.size());
}
Reddick answered 29/12, 2011 at 19:41 Comment(4)
the most concise and only depends on std::string, except remove the optional and misleading argument.size() at the end of the final substr.Mcguinness
@ben-bryant: Thanks for the heads up. Didn't know it was optional.Reddick
Using substr leads to unnecessary copying. The str.compare(start, count, substr) method used in Thomas' answer is more efficient. razvanco13's answer has another method which avoids copying by using std::equal.Feodor
@HüseyinYağlı Thomas uses atoi which is only for windows Huh? atoi has been a C standard library function since... ever. In point of fact, atoi is bad- not because it's Windows-specific- but because it's (1) C, not C++, and (2) deprecated even in C (you should be using strtol or one of the other, related functions. Because atoi has no error handling. But, again, that's only in C, anyway).Ladin
O
54

Nobody used the STL algorithm/mismatch function yet. If this returns true, prefix is a prefix of 'toCheck':

std::mismatch(prefix.begin(), prefix.end(), toCheck.begin()).first == prefix.end()

Full example prog:

#include <algorithm>
#include <string>
#include <iostream>

int main(int argc, char** argv) {
    if (argc != 3) {
        std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
                  << "Will print true if 'prefix' is a prefix of string" << std::endl;
        return -1;
    }
    std::string prefix(argv[1]);
    std::string toCheck(argv[2]);
    if (prefix.length() > toCheck.length()) {
        std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
                  << "'prefix' is longer than 'string'" <<  std::endl;
        return 2;
    }
    if (std::mismatch(prefix.begin(), prefix.end(), toCheck.begin()).first == prefix.end()) {
        std::cout << '"' << prefix << '"' << " is a prefix of " << '"' << toCheck << '"' << std::endl;
        return 0;
    } else {
        std::cout << '"' << prefix << '"' << " is NOT a prefix of " << '"' << toCheck << '"' << std::endl;
        return 1;
    }
}

Edit:

As @James T. Huggett suggests, std::equal is a better fit for the question: Is A a prefix of B? and is slight shorter code:

std::equal(prefix.begin(), prefix.end(), toCheck.begin())

Full example prog:

#include <algorithm>
#include <string>
#include <iostream>

int main(int argc, char **argv) {
  if (argc != 3) {
    std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
              << "Will print true if 'prefix' is a prefix of string"
              << std::endl;
    return -1;
  }
  std::string prefix(argv[1]);
  std::string toCheck(argv[2]);
  if (prefix.length() > toCheck.length()) {
    std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
              << "'prefix' is longer than 'string'" << std::endl;
    return 2;
  }
  if (std::equal(prefix.begin(), prefix.end(), toCheck.begin())) {
    std::cout << '"' << prefix << '"' << " is a prefix of " << '"' << toCheck
              << '"' << std::endl;
    return 0;
  } else {
    std::cout << '"' << prefix << '"' << " is NOT a prefix of " << '"'
              << toCheck << '"' << std::endl;
    return 1;
  }
}
Ovid answered 13/1, 2013 at 0:9 Comment(5)
Why not use std::equal?Hegelian
Sounds good to me. It would be shorter code too. I spose, I'll have to edit the answer now :pOvid
Using std::equal for strings has the downside that it doesn't detect the string end, so you need to manually check whether the prefix is shorter than the whole string. (As correctly done in the example prog, but omitted in the one-liner above.)Feodor
So, no benefit over rfind?Sharla
And method endsWith will be std::equal(suffix.rbegin(), suffix.rend(), toCheck.rbegin()Politick
H
40

With C++17 you can use std::basic_string_view & with C++20 std::basic_string::starts_with or std::basic_string_view::starts_with.

The benefit of std::string_view in comparison to std::string - regarding memory management - is that it only holds a pointer to a "string" (contiguous sequence of char-like objects) and knows its size. Example without moving/copying the source strings just to get the integer value:

#include <exception>
#include <iostream>
#include <string>
#include <string_view>

int main()
{
    constexpr auto argument = "--foo=42"; // Emulating command argument.
    constexpr auto prefix = "--foo=";
    auto inputValue = 0;

    constexpr auto argumentView = std::string_view(argument);
    if (argumentView.starts_with(prefix))
    {
        constexpr auto prefixSize = std::string_view(prefix).size();
        try
        {
            // The underlying data of argumentView is nul-terminated, therefore we can use data().
            inputValue = std::stoi(argumentView.substr(prefixSize).data());
        }
        catch (std::exception & e)
        {
            std::cerr << e.what();
        }
    }
    std::cout << inputValue; // 42
}
Hurwitz answered 4/5, 2018 at 20:49 Comment(6)
@RolandIllig No, std::atoi is completely fine. It throws exceptions on bad input (which is handled in this code). Did you have something else in mind?Hurwitz
Are you talking about the atoi from <cstdlib>? The documentation says "it never throws exceptions".Sternutatory
@RolandIllig I'm referring to your first comment. It seems, you are mistakenly talking about atoi instead of std::atoi. The first is unsafe to use, while the latter is fine. I'm using the latter in the code here.Hurwitz
Please prove to me that std::atoi indeed throws an exception, by citing a suitable reference. Until you do, I don't believe you since it would be very confusing to have both ::atoi and std::atoi acting in a completely different way.Sternutatory
@RolandIllig Thanks for being persistent! You are right, it was an oversight that std::atoi was used instead of std::stoi. I've fixed that.Hurwitz
This answer is the most modern way to do it. +1 for the use of string_view. Thanks for such a curated and robust code sample!Christiansand
N
26

Given that both strings — argv[1] and "--foo" — are C strings, @FelixDombek's answer is hands-down the best solution.

Seeing the other answers, however, I thought it worth noting that, if your text is already available as a std::string, then a simple, zero-copy, maximally efficient solution exists that hasn't been mentioned so far:

const char * foo = "--foo";
if (text.rfind(foo, 0) == 0)
    foo_value = text.substr(strlen(foo));

And if foo is already a string:

std::string foo("--foo");
if (text.rfind(foo, 0) == 0)
    foo_value = text.substr(foo.length());
Narration answered 28/7, 2013 at 1:11 Comment(3)
rfind(x, 0) == 0 should really be defined in the standard as starts_withCountrydance
No, because rfind() (in place of startswith()) is very inefficient - it keeps searching till the end of the string.Gaudreau
@Gaudreau rfind(x) searchs from the end till the start until it finds x, indeed. But rfind(x,0) starts searching from the start (position=0) till the start; so it only searches where it needs searching; does not search from/till the end.Gabrielson
F
20

Starting with C++20, you can use the starts_with method.

std::string s = "abcd";
if (s.starts_with("abc")) {
    ...
}
Fick answered 16/5, 2020 at 22:44 Comment(0)
S
16

C++20 update :

  • Use std::string::starts_with

https://en.cppreference.com/w/cpp/string/basic_string/starts_with

std::string str_value = /* smthg */;
const auto starts_with_foo = str_value.starts_with(std::string_view{"foo"});
Supervene answered 15/4, 2021 at 15:44 Comment(2)
is there an upside to using a string_view of a literal here? (compared to just using a literal)Bicameral
I'd rather use string-view-literals here en.cppreference.com/w/cpp/string/basic_string_view/… using the ""sv operator.Supervene
E
15
text.substr(0, start.length()) == start
Engrossment answered 13/4, 2018 at 10:4 Comment(4)
@GregorDoroschenko it does answer the "check if string starts with another" part.Convalescent
Efficient and elegant using std::string. I learnt the most from this.Flowerpot
extra points for being a one-liner suitable for use with if (one-liner)Glioma
@Roland Illig Why do you believe that the behaviour in that case is undefined? The expression will return false because substr returns a string of the same length as text according to en.cppreference.com/w/cpp/string/basic_string/substrEngrossment
L
12

Using STL this could look like:

std::string prefix = "--foo=";
std::string arg = argv[1];
if (prefix.size()<=arg.size() && std::equal(prefix.begin(), prefix.end(), arg.begin())) {
  std::istringstream iss(arg.substr(prefix.size()));
  iss >> foo_value;
}
Libna answered 21/12, 2011 at 21:56 Comment(1)
That should be if (prefix.size()<=arg.size() && std::equal(...)).Scevour
C
11

At the risk of being flamed for using C constructs, I do think this sscanf example is more elegant than most Boost solutions. And you don't have to worry about linkage if you're running anywhere that has a Python interpreter!

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
    for (int i = 1; i != argc; ++i) {
        int number = 0;
        int size = 0;
        sscanf(argv[i], "--foo=%d%n", &number, &size);
        if (size == strlen(argv[i])) {
            printf("number: %d\n", number);
        }
        else {
            printf("not-a-number\n");
        }
    }
    return 0;
}

Here's some example output that demonstrates the solution handles leading/trailing garbage as correctly as the equivalent Python code, and more correctly than anything using atoi (which will erroneously ignore a non-numeric suffix).

$ ./scan --foo=2 --foo=2d --foo='2 ' ' --foo=2'
number: 2
not-a-number
not-a-number
not-a-number
Callas answered 10/12, 2009 at 3:29 Comment(1)
If argv[i] is "--foo=9999999999999999999999999", the behavior is undefined (though most or all implementations should behave sanely). I'm assuming 9999999999999999999999999 > INT_MAX.Wilinski
G
11

I use std::string::compare wrapped in utility method like below:

static bool startsWith(const string& s, const string& prefix) {
    return s.size() >= prefix.size() && s.compare(0, prefix.size(), prefix) == 0;
}
Grindle answered 23/11, 2017 at 2:13 Comment(0)
L
10

In C++20 now there is starts_with available as a member function of std::string defined as:

constexpr bool starts_with(string_view sv) const noexcept;

constexpr bool starts_with(CharT c) const noexcept;

constexpr bool starts_with(const CharT* s) const;

So your code could be something like this:

std::string s{argv[1]};

if (s.starts_with("--foo="))
Laborious answered 18/11, 2020 at 10:18 Comment(0)
D
6

In case you need C++11 compatibility and cannot use boost, here is a boost-compatible drop-in with an example of usage:

#include <iostream>
#include <string>

static bool starts_with(const std::string str, const std::string prefix)
{
    return ((prefix.size() <= str.size()) && std::equal(prefix.begin(), prefix.end(), str.begin()));
}

int main(int argc, char* argv[])
{
    bool usage = false;
    unsigned int foos = 0; // default number of foos if no parameter was supplied

    if (argc > 1)
    {
        const std::string fParamPrefix = "-f="; // shorthand for foo
        const std::string fooParamPrefix = "--foo=";

        for (unsigned int i = 1; i < argc; ++i)
        {
            const std::string arg = argv[i];

            try
            {
                if ((arg == "-h") || (arg == "--help"))
                {
                    usage = true;
                } else if (starts_with(arg, fParamPrefix)) {
                    foos = std::stoul(arg.substr(fParamPrefix.size()));
                } else if (starts_with(arg, fooParamPrefix)) {
                    foos = std::stoul(arg.substr(fooParamPrefix.size()));
                }
            } catch (std::exception& e) {
                std::cerr << "Invalid parameter: " << argv[i] << std::endl << std::endl;
                usage = true;
            }
        }
    }

    if (usage)
    {
        std::cerr << "Usage: " << argv[0] << " [OPTION]..." << std::endl;
        std::cerr << "Example program for parameter parsing." << std::endl << std::endl;
        std::cerr << "  -f, --foo=N   use N foos (optional)" << std::endl;
        return 1;
    }

    std::cerr << "number of foos given: " << foos << std::endl;
}
Dhoti answered 16/11, 2018 at 15:51 Comment(1)
I like to use ::compare, which gives identical result: return str.size() >= prefix.size() && str.compare(0, prefix.size(), prefix) == 0;Varnish
H
5

Why not use gnu getopts? Here's a basic example (without safety checks):

#include <getopt.h>
#include <stdio.h>

int main(int argc, char** argv)
{
  option long_options[] = {
    {"foo", required_argument, 0, 0},
    {0,0,0,0}
  };

  getopt_long(argc, argv, "f:", long_options, 0);

  printf("%s\n", optarg);
}

For the following command:

$ ./a.out --foo=33

You will get

33
Hemangioma answered 11/6, 2013 at 12:8 Comment(0)
S
3

Ok why the complicated use of libraries and stuff? C++ String objects overload the [] operator, so you can just compare chars.. Like what I just did, because I want to list all files in a directory and ignore invisible files and the .. and . pseudofiles.

while ((ep = readdir(dp)))
{
    string s(ep->d_name);
    if (!(s[0] == '.')) // Omit invisible files and .. or .
        files.push_back(s);
}

It's that simple..

Straticulate answered 15/2, 2011 at 11:56 Comment(2)
A lesson in history: plus.sandbox.google.com/+RobPikeTheHuman/posts/R58WgWwN9jpDissociate
@Dissociate Google+ is no longer availableAgility
M
2

You can also use strstr:

if (strstr(str, substr) == substr) {
    // 'str' starts with 'substr'
}

but I think it's good only for short strings because it has to loop through the whole string when the string doesn't actually start with 'substr'.

M answered 26/8, 2012 at 23:41 Comment(0)
T
2

With C++11 or higher you can use find() and find_first_of()

Example using find to find a single char:

#include <string>
std::string name = "Aaah";
size_t found_index = name.find('a');
if (found_index != std::string::npos) {
    // Found string containing 'a'
}

Example using find to find a full string & starting from position 5:

std::string name = "Aaah";
size_t found_index = name.find('h', 3);
if (found_index != std::string::npos) {
    // Found string containing 'h'
}

Example using the find_first_of() and only the first char, to search at the start only:

std::string name = ".hidden._di.r";
size_t found_index = name.find_first_of('.');
if (found_index == 0) {
    // Found '.' at first position in string
}

Good luck!

Tanjatanjore answered 8/6, 2019 at 0:36 Comment(3)
Why not rfind? rfind(str, 0) will not needlessly scan an entire string to make a selection as it cannot advance. See others.Glyph
@Glyph Because rfind can lead to false positive since it "Find last occurrence of content in string". So "prefixblabla" matches but also "blablaprefixbla" would match.Bandaranaike
@merloy-van-den-berg according to this doc the find_first_of method is implemented or backported also on C++98: cplusplus.com/reference/string/string/find_first_ofBandaranaike
J
1
std::string text = "--foo=98";
std::string start = "--foo=";

if (text.find(start) == 0)
{
    int n = stoi(text.substr(start.length()));
    std::cout << n << std::endl;
}
Jonjona answered 9/10, 2017 at 7:44 Comment(4)
It would be great, if you avoid pasting code without code explanation. Thank you.Unnecessary
Inefficient code, would continue searching past the start of the string.Gaudreau
I was going to post the same thing. @Reborn Simple explanation: - This is the equivalent of saying if string start is found inside of string text at index 0 go into the if statement. - More specifically std::string find returns the first index of the original std::string that matches the string in parentheses. When it is equal to 0 it is the start of the string.Heaves
@Gaudreau this code would be very efficient since it is optimized by the compiler and improved in subsequent compiler enhancements.Heaves
T
0

Since C++11 std::regex_search can also be used to provide even more complex expressions matching. The following example handles also floating numbers thorugh std::stof and a subsequent cast to int.

However the parseInt method shown below could throw a std::invalid_argument exception if the prefix is not matched; this can be easily adapted depending on the given application:

#include <iostream>
#include <regex>

int parseInt(const std::string &str, const std::string &prefix) {
  std::smatch match;
  std::regex_search(str, match, std::regex("^" + prefix + "([+-]?(?=\\.?\\d)\\d*(?:\\.\\d*)?(?:[Ee][+-]?\\d+)?)$"));
  return std::stof(match[1]);
}

int main() {
    std::cout << parseInt("foo=13.3", "foo=") << std::endl;
    std::cout << parseInt("foo=-.9", "foo=") << std::endl;
    std::cout << parseInt("foo=+13.3", "foo=") << std::endl;
    std::cout << parseInt("foo=-0.133", "foo=") << std::endl;
    std::cout << parseInt("foo=+00123456", "foo=") << std::endl;
    std::cout << parseInt("foo=-06.12e+3", "foo=") << std::endl;

//    throw std::invalid_argument
//    std::cout << parseInt("foo=1", "bar=") << std::endl;

    return 0;
}

The kind of magic of the regex pattern is well detailed in the following answer.

EDIT: the previous answer did not performed the conversion to integer.

Thrombophlebitis answered 7/5, 2018 at 15:43 Comment(0)
Z
0

From C++23 onwards, you can use std::ranges::starts_with(), which works on any sequence type, including std::string and std::string_view, in any combination:

#include <algorithm>
#include <cassert>
#include <string>
#include <string_view>

int main()
{
    using namespace std::literals;
    assert(std::ranges::starts_with("abcde"s, "abc"sv));
    assert(!std::ranges::starts_with("abcde"sv, "bcd"s));
}

There's also a similar std::ranges::ends_with() function that behaves as you would expect.

Zuleika answered 19/1 at 13:7 Comment(0)
C
-4
if(boost::starts_with(string_to_search, string_to_look_for))
    intval = boost::lexical_cast<int>(string_to_search.substr(string_to_look_for.length()));

This is completely untested. The principle is the same as the Python one. Requires Boost.StringAlgo and Boost.LexicalCast.

Check if the string starts with the other string, and then get the substring ('slice') of the first string and convert it using lexical cast.

Chapeau answered 10/12, 2009 at 1:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.