1

How can I define a method which takes a string, let's say

asdfgsdfg:ijtij ijdfgh ija::saf 1999 bp

and returns the substring

ijtij ijdfgh ija::saf 1999

That is, I want all of the data between the first instance of a colon, until the bp character combination is found, at the end of the string.

user1876508
  • 12,864
  • 21
  • 68
  • 105
  • first make a copy of the string, then loop through this copy, while the first character is not a colon, remove it. When a colon is found, exit the loop and iterate through the string until *it == b && *(it+1) == p. remove the rest of the characters from it to string.end() – aCuria Apr 11 '13 at 20:46
  • What about the input "`asdfgsdfg:bpbp bpbp bp::bp 1999 bp`"? – Mooing Duck Apr 11 '13 at 21:08
  • That is not something that is a concern with the data that I am working with. – user1876508 Apr 11 '13 at 21:23
  • Are the last two characters _always_ "`bp`", or can there be characters after them? – Mooing Duck Apr 11 '13 at 21:31

3 Answers3

7
string original = "asdfgsdfg:ijtij ijdfgh ija::saf 1999 bp";

size_t s = original.find(":");
size_t e = original.find("bp", s);
string sub = original.substr(s + 1, e - s -1);
cout << sub ;
  • Excellent, but fails if the original string contains "`bp`" anywhere. :( – Mooing Duck Apr 11 '13 at 21:04
  • @MooingDuck what? What internal string? –  Apr 11 '13 at 21:04
  • @MooingDuck Whilst you're right, I feel that that is more a matter of the problem specification not being clear. Why is 'bp' the marker at the end? If it's always present, just always ignore the last two characters (in which case the 'bp' isn't even relevant to the question). – JBentley Apr 11 '13 at 21:06
  • @MooingDuck in that case it gives you an empty string. How is that failing? –  Apr 11 '13 at 21:06
  • @MooingDuck OP wants anything between the first `:` and the next `bp` –  Apr 11 '13 at 21:07
  • @stardust_: It's hard to tell, so you get an upvote. On the off-chance I'm right though, [here's a reverse_find](http://coliru.stacked-crooked.com/view?id=bd89ce63407041b4ebf93ed16baec923-50d9cfc8a1d350e7409e81e87c2653ba). – Mooing Duck Apr 11 '13 at 21:10
  • @MooingDuck :) I know man I think op doesn't know what he wants really. That is how I tried it first but i changed it thinking he needed this. Anyways `find_last(original, "bp");` can be `original.rfind("bp")` :P. –  Apr 11 '13 at 21:27
5

Use std::string::find to locate the first colon and the first occuring "bp" after the colon. Then use std::string::substr to get the substring between those positions.

#include <iostream>
#include <string>

int main()

{
    std::string str = "asdfgsdfg:ijtij ijdfgh ija::saf 1999 bp";
    int start = str.find(":");
    int end = str.find("bp", start);
    std::string substring;
    if (start != std::string::npos && end != std::string::npos)
    {
       substring = str.substr(start + 1, end - start - 1);
    }
    else
    {
       // Whatever you want to do if the markers are missing.
    }
    std::cout << substring;
}

Output here.

EDIT: As per MooingDuck's comment on stardust_'s answer, it's unclear what your intentions are regarding the "bp" marker. Does the first found instance of "bp" end the substring, or does the substring always end before the final two charaters of the original string? (in which case it is irrelevant whether they are "bp" or not). If the latter, then modify as follows:

#include <iostream>
#include <string>

int main()

{
    std::string str = "asdfgsdfg:ijtij ijdfgh ija::saf 1999 bp";
    int start = str.find(":");
    int end = str.length() - 2; // Changed here
    std::string substring;
    if (start != std::string::npos && end != std::string::npos)
    {
       substring = str.substr(start + 1, end - start - 1);
    }
    else
    {
       // Whatever you want to do if the markers are missing.
    }
    std::cout << substring;
}

Output here.

JBentley
  • 6,099
  • 5
  • 37
  • 72
1

Here you go, a complete function that can retrieve a sub-string from a std::string. A good documentation on this function is also included.

#pragma region INFO
/*
 * @ FUNCTION: GetSubStrBetween
 *
 * @ PARAMETER(s):
 *      [1st] std::string &in_Str = This paramter takes in a std::string, which
 *            is the string that contains the unknown sub-string.
 *
 *      [2nd] std::string in_A = This parameter takes in a std::string, which
 *            will be the beginning point of the unknown sub-string.
 *
 *      [3rd] std::string in_B = This parameter takes in a std::string, which
 *            happens to be the ending point of the unknown sub-string.
 *
 *      [4th] std::string in_out_SubStr = This parameter takes in a std::string,
 *            which will contain the unknown sub-string.
 *
 *      [5th] bool in_opt_Append = This optional* parameter takes in either a true
 *            or false value. If in_opt_Append = true, in_out_SubStr (see 4th
 *            param.) will append the unknown sub-str. Else, in_out_SubStr will be
 *            equal to the unknown sub-str. Note: The default value is false.
 *
 * @ RETURN VALUE(s):
 *      false = This function returns a false value because...
 *              - The length of in_Str/in_A/in_B is equal to 0.
 *              - The length of in_A/in_B is greater than or equal to the length
 *                of in_Str.
 *              - The length of in_Str is smaller than length of in_A + the length
 *                of in_B.
 *              - Unable to find in_A/in_B.
 *      true = Successfully found and return the unknown sub-str to in_out_SubStr.
 */
#pragma endregion INFO

bool GetSubStrBetween( std::string &in_Str,
                       std::string in_A,
                       std::string in_B,
                       std::string &in_out_SubStr,
                       bool in_opt_Append = false )
{
    //# Check for possible errors.
    if( in_A.length() == 0 ||
        in_B.length() == 0 ||
        in_Str.length() == 0 ||
        in_Str.length() <= in_A.length() ||
        in_Str.length() <= in_B.length() ||
        in_Str.length() < in_A.length() + in_B.length() )
    {   return false; }

    //# Try to find the positions of in_A and in_B within in_Str.
    const int A_Pos = in_Str.find( in_A );
    const int B_Pos = in_Str.find( in_B );

    //# Check if in_A and in_B does exist within in_Str.
    if( A_Pos < 0 || B_Pos < 0 )
    {   return false; }

    //# Retrieve the unknown-substr and either append it to in_out_SubStr
    //  or make in_out_SubStr equal to the unknown sub-string.
    ( in_opt_Append == true ) ?
        ( in_out_SubStr = in_Str.substr( A_Pos + 1, B_Pos - 1 - A_Pos ) ) :
        ( in_out_SubStr += in_Str.substr( A_Pos + 1, B_Pos - 1 - A_Pos ) );

    //# Success!
    return true;
};

Do not forget to include string.

Here is a usage example based on the question above:

std::string Str = "asdfgsdfg:ijtij ijdfgh ija::saf 1999 bp";
std::string SubStr = "";

if( GetSubStrBetween( Str, ":", "bp", SubStr ) ) {
    std::cout << std::endl << GetSubStrBetween << std::endl;
} else { std::cout << "\nGetSubStrBetween(...) has failed!\n"; }
CLearner
  • 532
  • 1
  • 6
  • 17
  • 2
    CLearner, there's a question over at http://stackoverflow.com/questions/27977333/which-documentation-system-uses-this-format that you are immensely qualified to answer. – paxdiablo Jan 16 '15 at 04:51