2

I have any sequence (or sentence) and i want to extract the last 2 strings.

For example,

  • sdfsdfds sdfs dfsd fgsd 3 dsfds should produce: 3 dsfds
  • sdfsd (dfgdg)gfdg fg 6 gg should produce: 6 gg
vehomzzz
  • 42,832
  • 72
  • 186
  • 216
  • See also this question: http://stackoverflow.com/questions/53849/how-do-i-tokenize-a-string-in-c. Also, this has little to do with the STL (which is the part of the std lib dealing with containers, iterators, and algorithms), so I changed the tags. – sbi Oct 06 '10 at 18:22
  • @sbi: std::string and its find methods (rfind is useful in this case) are part of STL. So I would rather not remove STL tag. –  Oct 06 '10 at 18:28
  • @Vlad: "The STL" is a colloquial name for those parts of the std lib, which came from the original STL. [It is __not a synonym__ for the Standard Library.](http://en.wikipedia.org/wiki/Standard_Template_Library) One could argue whether `std::string` (not even mentioned in the question), which was in the draft standard for a long time when the STL came and was only later "STLified", belongs to the STL. It's myriads of member functions definitely don't. (The fact that algorithms are separate from containers is what sets the STL apart, after all.) I won't fight over that tag, but it is wrong. – sbi Oct 08 '10 at 16:21

5 Answers5

4

You can use std::string::find_last_of function to find spaces.

int main()
{
    std::string test = "sdfsdfds sdfs dfsd fgsd 3 dsfds";

    size_t found1 = test.find_last_of( " " );
    if ( found1 != string::npos ) {
        size_t found2 = test.find_last_of( " ", found1-1 );
        if ( found2 != string::npos ) 
            std::cout << test.substr(found2+1, found1-found2-1) << std::endl;
        std::cout << test.substr(found1+1) << std::endl;
    }

    return 0;
}
Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
2

The following will work if your strings are whitespace separated.

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;

int main()
{
    string str = "jfdf fhfeif shfowejef dhfojfe";
    stringstream sstr(str);
    vector<string> vstr;

    while(sstr >> str)
    {
        vstr.push_back(str);
    }

    if (vstr.size() >= 2)
        cout << vstr[vstr.size()-2] << ' ';
    if (vstr.size())
        cout << vstr[vstr.size()-1] << endl;

    return 0;
}
Donotalo
  • 12,748
  • 25
  • 83
  • 121
  • you might want to check for the vector's size being > 2 before accessing it. – sbi Oct 06 '10 at 18:26
  • yep, thanks. i assumed that there will be enough strings for extraction. – Donotalo Oct 06 '10 at 18:28
  • @Donato: (You need to properly @address comment replies for them to show up in other people's responses tab. I only came by here by accident.) Up-voted now. – sbi Oct 08 '10 at 16:14
  • @sbi, didn't know about this feature. thanks. i thought it is automatic. – Donotalo Oct 08 '10 at 16:16
1

Returns the strings in the wrong order, but if that doesn't matter,

std::string s ("some words here"); 

std::string::size_type j;
for(int i=0; i<2; ++i) {
    if((j = s.find_last_of(' ')) == std::string::npos) {
        // there aren't two strings, throw, return, or do something else
        return 0;
    }   
    std::cout << s.c_str()+j+1;
    s = " " + s.substr(0,j); 
}  

Alternatively,

struct extract_two_words {
    friend std::istream& operator>> (std::istream& in , extract_two_words& etw);
    std::string word1;
    std::string word2;
};

std::istream& operator>> (std::istream& in , extract_two_words& etw) {
    std::string str1, str2;
    while(in) {
        in >> str1;
        in >> str2;
    }
    etw.word2 = str1;
    etw.word1 = str2;
}
tjm
  • 7,500
  • 2
  • 32
  • 53
1

I would encourage you to have a look at the Boost library. It has algorithms and data structures that help you tremendously. Here's how to solve your problem using Boost.StringAlgo:

#include <boost/algorithm/string/split.hpp>
#include <iostream>
#include <vector>
#include <string>

int main()
{
   std::string test = "sdfsdfds sdfs dfsd fgsd 3 dsfds";

   std::vector<std::string> v;
   boost::algorithm::split(v, test, [](char c) { return c==' ';});
   std::cout << "Second to last: " << v.at(v.size()-2) << std::endl;
   std::cout << "Last:           " << v.at(v.size()-1) << std::endl;
}

I would also encourage you to always use the vector::at method instead of []. This will give you proper error handling.

Daniel Lidström
  • 9,930
  • 1
  • 27
  • 35
1
int main()
{
     std::string test = "sdfsdfds sdfs dfsd fgsd 3 dsfds";
     size_t pos = test.length();
     for (int i=0; i < 2; i++)
         pos = test.find_last_of(" ", pos-1);
     std::cout << test.substr(pos+1) << std::endl;
 }

Simpler :)

dr.manhattan
  • 4,842
  • 3
  • 19
  • 10