0

I saw very many solution with only one limiter, but i needed someting to parse this $deli: entry :deli$ . One limiter before the entry and on after it. Does anybody have an idea?

#include <iostream>
#include <string>
#include <vector>

std:string delimiterOpen    = ("$deli:");
std:string delimiterClose   = (":deli$");
std::vector<std:string> vec;

std:string str ("start $deli:foo:deli$ something else $deli:baa:deli$ doesnt matter");

// calculate


//this should be the vector contend:
foo
ba
Morwenn
  • 21,684
  • 12
  • 93
  • 152
post4dirk
  • 313
  • 4
  • 16
  • 2
    `` is overkill for simple parsing problems and insufficient for really complex parsing problems, but here it seems to be quite appropriate. – MSalters Feb 26 '14 at 12:24
  • use `:` as delimeter and store alternate string in vector – EmptyData Feb 26 '14 at 12:26
  • @Vinay this would need escaping `:` for other uses, or using another delimiter not used for anything else; but neither would work if strings are already fixed – iavr Feb 26 '14 at 12:30
  • Consider this: http://stackoverflow.com/a/21875033/3099074 – mockinterface Feb 26 '14 at 12:34

5 Answers5

0

Try this:

#include <string>
#include <vector>
#include <iostream>

int main()
{
    std::string delimiterOpen    = ("$deli:");
    std::string delimiterClose   = (":deli$");
    std::vector<std::string> vec;

    std::string str ("start $deli:foo:deli$ something else $deli:baa:deli$ doesnt matter");
    int pos1=0,pos2=0;
    while ( (pos1=str.find(delimiterOpen,pos2))!=std::string::npos ){
        if( (pos2=str.find(delimiterClose,pos1))==std::string::npos){
            //error start without end...
            break;
        }else{
            int start=pos1+delimiterOpen.size();
            int length = pos2-start;
            std::string val = str.substr(start,length);
            vec.push_back(val);
        }

    }
    return 0;
}
SHR
  • 7,940
  • 9
  • 38
  • 57
0

You can use regular expressions. Or you can use simple std::string::find method with std::string::substr method. Like this:

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>

using namespace std;


int _tmain(int argc, _TCHAR* argv[])
{
    string delimiterOpen    = ("$deli:");
    string delimiterClose   = (":deli$");
    vector<string> vec;

    string str("start $deli:foo:deli$ something else $deli:baa:deli$ doesnt matter");

    size_t posOpen = 0;
    do 
    {
        string lexeme;
        posOpen = str.find(delimiterOpen, posOpen);
        if (posOpen != string::npos)
        {
            posOpen += delimiterOpen.length();

            size_t posClose = str.find(delimiterClose, posOpen);
            if (posClose != string::npos)
            {
                lexeme = str.substr(posOpen, posClose - posOpen);
                vec.push_back(lexeme);
            }
        }
    } while (posOpen != string::npos);

    vector<string>::iterator it;
    for (it = vec.begin(); it != vec.end(); ++it)
    {
        cout << it->c_str() << endl;
    }

    return 0;
}
Alexander
  • 959
  • 5
  • 11
  • 29
0

If you don't want to use regex...

#include <iostream>
#include <string>
#include <vector>

using namespace std;

string delimiterOpen    = ("$deli:");
string delimiterClose   = (":deli$");
int shift = delimiterOpen.size();
vector<string> vec;

string str ("start $deli:foo:deli$ something else $deli:baa:deli$ doesnt matter");

int main() {
vector<string> founds;
int firstPos = str.find(delimiterOpen);
  while (firstPos != string::npos) {
      int lastPos = str.find(delimiterClose, firstPos);
      if (lastPos!=string::npos) {
         founds.push_back(str.substr(firstPos+shift, lastPos-firstPos-shift));
      }
      firstPos = str.find(delimiterOpen, (lastPos==string::npos? firstPos+1:lastPos+1));
  }

  for (vector<string>::iterator it = founds.begin(); it!=founds.end();it++) {
      cout<<(*it)<<endl;
  }
  return 0;
}
Ashalynd
  • 12,363
  • 2
  • 34
  • 37
0
void parse(const string& str, 
           const string& delOpen, 
           const string& delClose
           vector<string>& founds /*out*/;)
{
  const string::size_type 
    szOpen (delOpen.sise()), 
    szClose(delClose.size());

  string::size_type p1 (str.find(delOpen));

  while(p1!=string::npos) {
    string::size_type p2(p1==string::npos ? p1 : str.find(delClose, p1+szOpen));
    founds.push_back(str.substr(p1+szOpen, p2));
    p1 = p2==string::npos ? p2 : str.find(dOpen, p2+szClose);
  }

}
ArunasR
  • 1,907
  • 1
  • 14
  • 15
0

Boost.Spirit is always the right way to go: you'll be benefitted by type-safety, clear parser structure and syntax.

#include <boost/spirit/home/qi.hpp>
#include <vector>
#include <string>

namespace qi = boost::spirit::qi;
using std::vector;
using namespace qi;

template <typename Iterator = std::string::const_iterator>
struct my_parser : grammar<Iterator, vector<std::string>(), blank_type>
{
  my_parser(const std::string &openingDelim, const std::string &closingDelim) : my_parser::base_type(query)
  {
    open = openingDelim;
    close = closingDelim;
    beforeOpen = *(char_ - open);
    afterOpen = *(char_ - close);
    //when synthesizing the resulting attribute, ignore everything before openingDelim and after closingDelim
    query = (omit[beforeOpen >> open] >> afterOpen >> omit[close]) % beforeOpen;
  }
  rule<Iterator, vector<std::string>(), blank_type> query;
  rule<Iterator, std::string(), blank_type> open, close, beforeOpen, afterOpen;
};


int main()
{
  my_parser<> p("$deli:", ":deli$");
  std::string s("start $deli:foo:deli$ something else $deli:baa:deli$ doesnt matter");
  vector<std::string> result;
  bool b = phrase_parse(s.begin(), s.end(), p, blank, result);
}
Igor R.
  • 14,716
  • 2
  • 49
  • 83