Можете ли вы указать, что НЕ является разделителем в std :: getline? - PullRequest
3 голосов
/ 14 февраля 2012

Я хочу, чтобы все, что не является символом алфавита, считалось разделителем.Как я могу это сделать?

Ответы [ 3 ]

3 голосов
/ 14 февраля 2012

Вы не можете. Разделитель по умолчанию: \n:

while (std::getline (std::cin, str) // '\n' is implicit

Для других разделителей, передайте их:

while (std::getline (std::cin, str, ' ') // splits at a single whitespace

Однако, разделитель имеет тип char, поэтому вы можете использовать только один «символ разделения», но не то, что не соответствует.

Если ваш ввод уже находится внутри контейнера, например std::string, вы можете использовать find_first_not_of или find_last_not_of.


В своем другом вопросе вы уверены, что рассмотрели все ответы? Каждый использует istream::operator>>(std::istream&, <string>), который будет соответствовать последовательности непробельных символов.

3 голосов
/ 14 февраля 2012

Ты не. getline - это простой инструмент для простой работы. Если вам нужно что-то более сложное, вам нужно использовать более сложный инструмент, такой как RegEx или что-то в этом роде.

0 голосов
/ 14 февраля 2012

Вы не можете делать то, что хотите, используя std::getline(), но вы можете бросить свой собственный.Вот вариант getline, который позволяет вам указать предикат (функция, функтор, лямбда, если это C ++ 11), чтобы указать, является ли символ разделителем, вместе с парой перегрузок, которые позволяют передавать строку символов-разделителей (видиз strtok()):

#include <functional>
#include <iostream>
#include <string>

using namespace std;

template <typename Predicate>
istream& getline_until( istream& is, string& str, Predicate pred)
{
    bool changed = false;
    istream::sentry k(is,true);

    if (bool(k)) {
        streambuf& rdbuf(*is.rdbuf());
        str.erase();

        istream::traits_type::int_type ch = rdbuf.sgetc(); // get next char, but don't move stream position
        for (;;ch = rdbuf.sgetc()) {
            if (istream::traits_type::eof() == ch) {
                is.setstate(ios_base::eofbit);
                break;
            }
            changed = true;
            rdbuf.sbumpc(); // move stream position to consume char
            if (pred(istream::traits_type::to_char_type(ch))) {
                break;
            }
            str.append(1,istream::traits_type::to_char_type(ch));
            if (str.size() == str.max_size()) {
                is.setstate(ios_base::failbit);
                break;
            }
        }

        if (!changed) {
            is.setstate(ios_base::failbit);
        }
    }            

    return is;
}

// a couple of overloads (along with a predicate) that allow you
// to pass in a string that contains a set of delimiter characters

struct in_delim_set : unary_function<char,bool>
{
    in_delim_set( char const* delim_set) : delims(delim_set) {};
    in_delim_set( string const& delim_set) : delims(delim_set) {};

    bool operator()(char ch) {
        return (delims.find(ch) != string::npos);
    };
private:
    string delims;

};

istream& getline_until( istream& is, string& str, char const* delim_set)
{
    return getline_until( is, str, in_delim_set(delim_set));
}

istream& getline_until( istream& is, string& str, string const& delim_set)
{
    return getline_until( is, str, in_delim_set(delim_set));
}

// a simple example predicate functor
struct is_digit : unary_function<char,bool>
{
    public:
        bool operator()(char c) const {
            return ('0' <= c) && (c <= '9');
        }
};


int main(int argc, char* argv[]) {
    string test;

    // treat anything that's not a digit as end-of-line
    while (getline_until( cin, test, not1(is_digit()))) {
        cout << test << endl;
    }

    return 0;
}
...