keddad
keddad

Reputation: 1796

Getting a substring from a std::string with iterators

I want to get a substring from the first appearance of char in string to the end of the string. I thought that I can just use constructor, like in this question, but it doesn't really work. When I do like this:

string(input.find(' ')+1, input.end()-1)

I face "no constructor" error

error: no matching constructor for initialization of 'std::__cxx11::string' (aka 'basic_string<char>')

How can I fix this problem and get my code working?

Upvotes: 5

Views: 15762

Answers (3)

Richard Hodges
Richard Hodges

Reputation: 69864

For the sake of defensive programming, you may want to consider the pathalogical case where there is no space in the input.

Here are two solutions, one using iterators and standard algorithms, the other using string's find method.

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

std::string 
all_after_space_iters(std::string const& input)
{
    auto last = input.end();

    auto after_found = [&]
    {
        auto current = std::find(input.begin(), last, ' ');
        if (current != last)
            current = std::next(current);
        return current;
    };

    return std::string(after_found(), last);
}


std::string 
all_after_space_no_iters(std::string const& input)
{
    auto pos = input.find(' ');

    auto result = std::string();
    if (pos != std::string::npos)
    {
        result = input.substr(pos + 1);
    }
    return result;
}

std::string check(std::string s)
{
    if (s.empty())
        s = "**empty**";
    return s;
}


int main()
{
    std::cout << check(all_after_space_iters("dog cat")) << '\n';
    std::cout << check(all_after_space_no_iters("dog cat")) << '\n';
    std::cout << check(all_after_space_iters("dogcat")) << '\n';
    std::cout << check(all_after_space_no_iters("dogcat")) << '\n';
}

Expected Output:

cat
cat
**empty**
**empty**

http://coliru.stacked-crooked.com/a/44e484d3325d195e

Note: these are examples only. There are many ways to skin this cat.

Upvotes: 1

eerorika
eerorika

Reputation: 238311

I assume that input is a std::string

If you take a look at the documentation of std::string::find, you'll find that it returns the index of the found character; not an iterator. In order to use the iterator constructor, you must use:

auto str = std::string(input.begin() + input.find(' '), input.end());

Alternatively, you could use substr member of input:

auto str = input.substr(input.find(' '));

The +1 and -1 in your example are confusing. If you add 1 to first, then you get the substring starting after the found character, not starting from the character. If you subtract 1 from the end, you copy until one before the last character, not up to the end of the string.


Note that you probably also need to also handle the case where the character is not found. The constructor approach (as I've implemented) would have undefined behaviour. The substr approach would throw an exception.

Upvotes: 11

Yashas
Yashas

Reputation: 1234

The find member function of std::string does not return an iterator.

There is also std::string::substr which you can use as input.substr(input.find(' ') + 1);

Upvotes: 1

Related Questions