Что-то вроде istream::getline(), но с альтернативными символами-разделителями?

Какой самый чистый способ получить эффект istream::getline(string, 256, '\n' OR ';')?

Я знаю, что написать цикл довольно просто, но я чувствую, что могу что-то упустить. Я?

Что я использовал:

while ((is.peek() != '\n') && (is.peek() != ';'))
    stringstream.put(is.get());

person Erika    schedule 15.10.2012    source источник


Ответы (3)


К сожалению, нет возможности иметь несколько «концов строк». Что вы можете сделать, это прочитать строку, например. std::getline и поместите его в std::istringstream и используйте std::getline (с разделителем ';') в цикле на istringstream.

Хотя вы можете проверить библиотеку Boost iostreams, чтобы посмотрите, у него есть функциональность для этого.

person Some programmer dude    schedule 15.10.2012
comment
Хорошо, спасибо, это довольно приятно! Я написал цикл, который std::stringstream.put(): вводил каждый символ, пока не находил '\n' или ';', а затем использовал stringstream.str() для получения строки. - person Erika; 15.10.2012

Существует std::getline. Для более сложных сценариев можно попробовать разделить istream_iterator или istreambuf_iterator с разделить ускорение или regex_iterator (вот пример использования итераторов потока).

person ArtemGr    schedule 15.10.2012
comment
std::getline хорош, потому что у него есть перегрузка для std::string, которая значительно упрощает ввод-вывод строк (по крайней мере, на мой взгляд). - person dreamlax; 15.10.2012
comment
std::getline не помогает в этом случае, когда OP хочет несколько окончаний/разделителей строк. - person Some programmer dude; 15.10.2012

Вот рабочая реализация:

enum class cascade { yes, no };
std::istream& getline(std::istream& stream, std::string& line, const std::string& delim, cascade c = cascade::yes){
    line.clear();
    std::string::value_type ch;
    bool stream_altered = false;
    while(stream.get(ch) && (stream_altered = true)){
        if(delim.find(ch) == std::string::npos)
            line += ch;
        else if(c == cascade::yes && line.empty())
            continue;
        else break;
    }
    if(stream.eof() && stream_altered) stream.clear(std::ios_base::eofbit);
    return stream;
}

Параметр cascade::yes сворачивает найденные последовательные разделители. С cascade::no он будет возвращать пустую строку для каждого найденного второго последовательного разделителя.

Использование:

const std::string punctuation = ",.';:?";
std::string words;
while(getline(istream_object, words, punctuation))
    std::cout << word << std::endl;

См. его использование Прямой эфир на Coliru

Более общей версией будет эта.

person WhiZTiM    schedule 26.08.2016