4

I currently have a function that reads from a stream until a predefined stream-stopper is found. The only way I could currently get it up and running is by using std::getline and having one character followed by a newline (in my case char(3)) as my stream-stopper.

std::string readuntil(std::istream& in) {
    std::string text;
    std::getline(in, text, char(3));
    return text;
}

Is there any way to achieve the same but with a larger string as my stream-stopper? I don't mind it having to be followed by a new-line, but I want my delimiter to be a random string of some size so that the probability of it occurring by change in the stream is very very low.

Any idea how to achieve this?

Simon Streicher
  • 2,638
  • 1
  • 26
  • 30
  • Possible duplicate of [Split a string in C++?](http://stackoverflow.com/questions/236129/split-a-string-in-c) – ForceBru Jan 25 '17 at 12:20
  • 1
    @ForceBru not exactly a duplicate, since I don't want to read the stream past the delimiter, so that the after-the-delimiter parts can be read at another time. – Simon Streicher Jan 25 '17 at 12:23
  • Doing this efficiently is non trivial if you can't load the whole file into memory. You can repeatedly fill a buffer and check that but you need to allow for the buffer slicing your search term in half. – Galik Jan 25 '17 at 12:44

1 Answers1

8

I assume that your requirements are:

  • a function taking an istream ref and a string as parameter
  • the string is a delimiter and the function must return a string containing all the characters that arrived before it
  • the stream must be positioned immediately after the delimiter for further processing.

AFAIK, neither the C++ nor the C standard library contain a function for that. I would just:

  • read until the last character of the delimiter in a temporary string
  • accumulate that in a global string
  • iterate the 2 above actions if the global string does not end with the delimiter
  • optionaly remove the delimiter from the end of the global string
  • return the global string

A possible C++ implementation is:

std::string readuntil(std::istream& in, std::string delimiter) {
    std::string cr;
    char delim = *(delimiter.rbegin());
    size_t sz = delimiter.size(), tot;
    do {
        std::string temp;
        std::getline(in, temp, delim);
        cr += temp + delim;
        tot = cr.size();
    } while ((tot < sz) || (cr.substr(tot - sz, sz) != delimiter));
    return cr.substr(0, tot - sz);  // or return cr; if you want to keep the delimiter
}
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252