Как работает getline()?

422
18 января 2017, 00:23

Задача очень проста: на вход поступает количество принимаемых строк, и затем сами строки. На выход должно выйти (через пробел) количество гласных в этих строках.

// Подсчет гласных в строке
#include <iostream>
#include <string>
#include <algorithm> 
#include <conio.h>   
using namespace std;
class count_predicate {
public:
    bool operator()(const char& expr) {
        if (
            expr == 'a' || expr == 'o' || expr == 'i'
            || expr == 'u' || expr == 'y' || expr == 'e'
           ) return true;
        return false;
    }
};
int main()
{
    int N; // Нужное количество строк
    cin >> N;
    string strs[N];
    for (int i = 0; i < N; i++)
        getline(cin, strs[i]);
    for (int i = 0; i < N; i++) {
        int n = count_if(strs[i].begin(), strs[i].end(), count_predicate());
        cout << n << " ";
    }
    return 0;
}

Когда вместо getline() я использую обычный cin>>, то все работает, но строки попадаются с пробелами, поэтому гласные считаются некорректно. Здесь же почему-то getline() каким-то образом "перебивает" cin сверху, и считывает количество строк как еще одну строку, как я понял из теста программы (но это не точно). Собственно, почему так происходит?

И еще, у меня такое ощущение, что я решаю задачу очень топорно, есть ли какое-то более элегантное решение?
Особенно меня смущает количество проверок в предикате. Если такое решение есть, можно и без STL, ей я пользуюсь исключительно в учебных целях, закрепляю, так сказать, пройденный материал.

Answer 1

Здесь же почему-то getline() каким-то образом "перебивает" cin сверху, и считывает количество строк как еще одну строку, как я понял из теста проги(но это не точно)

Нет, все проще. После считывания количества строк в буфере остается символ перевода строки. Вам просто надо сбросить буфер после считывания N - например, так:

cin.ignore(std::numeric_limits<size_t>::max(), '\n');

(это означает - считать и игнорировать все, пока не встретим '\n').

Еще - я бы переписал ваш оператор как

bool operator()(char expr) {
    return strchr("aoiuye",expr) != nullptr;
}

Остальное не смотрел...

Answer 2

После этого предложения

cin >> N;

в буфере потока ввода сохранился символ новой строки '\n'. Поэтому первое обращение к буферу ввода с помощью функцииgetline` приводит к тому, что считывается пустая строка.

Следует удалить этот символ новой строки из буфера перед использованием getline Делается это следующим образом

#include <iostream>
#include <string>
#include <algorithm> 
#include <limits>
^^^^^^^^^^^^^^^^^
#include <conio.h>   
using namespace std;
class count_predicate {
public:
    bool operator()(const char& expr) {
        if (
            expr == 'a' || expr == 'o' || expr == 'i'
            || expr == 'u' || expr == 'y' || expr == 'e'
           ) return true;
        return false;
    }
};
int main()
{
    int N; // Нужное количество строк
    cin >> N;
    string strs[N];
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   // ...

Предикат может быть записан проще

#include <cstring>
//...
struct count_predicate 
{
    bool operator()( const char &c ) const
    {
        const char *vowels = "aeiouy";
        return std::strchr( vowels, c );
    }
};
READ ALSO
Границы диаграммы вороного, Boost Voronoi

Границы диаграммы вороного, Boost Voronoi

Как можно задать границы для диаграммы вороного? С помощью boost построил диаграмму вороного

379
Сортировка в QTableView

Сортировка в QTableView

При установке setSortingEnabled(true) экземпляра QTableView в хэдерах колонок появляются переключаемые значки сортировки, но при нажатиях на них сама сортировка...

597
сложный SQL запрос

сложный SQL запрос

Есть 2 таблицы posts и likes нужно чтобы значение postslikes было равно количеству записей в таблице likes где likes

442
Как в запросе select (mysql) можно посчитать количество последних значений, равных между собой, и идущих непрерывно?

Как в запросе select (mysql) можно посчитать количество последних значений, равных между собой, и идущих непрерывно?

Как в запросе select (mysql) можно посчитать количество последних значений, равных между собой, и идущих непрерывно?

427