Второй cin либо пропущен, либо не работает должным образом

У меня есть пара проблем, которые, как мне кажется, тесно связаны, но я не смог их исправить после того, что я ранее нашел на веб-сайте.

Мои проблемы связаны с двойным использованием cin в моей основной функции. Мне нужно читать числа с клавиатуры, чтобы либо строить небольшие векторы, либо хранить отдельные коэффициенты. Я не могу знать заранее длину векторов, которые собираюсь построить.

Вот задействованные строки:

#include <vector>
#include <iostream>
#include <limits>

int main() {
    ...
    double a=0;
    std::vector<double> coefficients;
    while (std::cin>>a) {
       coefficients.push_back(a);
    }
    ...
    std::vector<double> interval;
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max());
    while(std::cin>>a) {
       interval.push_back(a);
    }
    std::cout<<interval.size()<<std::endl;
    std::cout<<*interval.cbegin()<<" "<<*(interval.cend()-1)<<std::endl;
    ...
}

Я использую как macOS с g++ 6.3.0, так и Linux с g++ 5.3.0. Компилятору я отправляю флаги -Wall -std=c++14 -o.
На машине с macOS второй cin полностью пропускается, а на машине с Linux второй процесс чтения ведет себя не так, как ожидалось. Я имею в виду, что если я дам -1 1 во втором cin, напечатанный размер вектора будет равен 0 и, очевидно, программа остановится из-за ошибки сегментации.

На каждом cin я ввожу запрошенные числа в одну строку, например 1 0 0 1, затем нажимаю ввод, а затем ctrl+D.

Заранее спасибо всем! :)


person Sandro    schedule 30.01.2017    source источник
comment
Рассматривали ли вы вместо этого использование getline?   -  person molbdnilo    schedule 30.01.2017
comment
Да, я это сделал, и это, наряду с избавлением от строки cin.ignore, позволяет моему коду работать, как и ожидалось, на машине с Linux. Однако это не относится к macOS. Значит, я должен отказаться от cin раз и навсегда?   -  person Sandro    schedule 30.01.2017


Ответы (2)


Ваш вызов std::cin.ignore(...) устанавливает бит ошибки потока. Это делает невозможным вход в петлю. Вам нужно переместить вызов std::cin.clear() прямо перед циклом, чтобы он заработал. Также у вас есть чтение за пределами привязки, когда во втором контейнере нет данных.

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

int main() {
    double a=0;
    std::vector<double> coefficients;
    while (std::cin>>a) {
       coefficients.push_back(a);
    }
    std::cout << coefficients.size() << '\n';

    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), 'X');
    std::cin.clear();
    char c;
    std::cin>>c;
    if(c != 'X')
    {
        std::cerr << "Invalid separator\n";
        return 1;
    }

    std::vector<double> interval;
    while(std::cin >> a) {
       interval.push_back(a);
    }
    std::cout<< interval.size()<<std::endl;
    if(interval.size())
        std::cout<<*interval.cbegin()<<" "<<*(interval.cend()-1)<<std::endl;

    return 0;
}

Со следующим файлом данных,

$ cat data.txt
12 23
42
X
1 2
3 4 5

этот вывод генерируется:

$ ./a.out < data                  
3
5
1 5
person Rudi    schedule 30.01.2017
comment
Спасибо! Я не знал, что std::cin.ignore() устанавливает бит ошибки потока. Теперь программа хорошо работает на Linux. Все еще без изменений в macOS, но теперь это второстепенно. - person Sandro; 30.01.2017

Вам нужно добавить перевод строки '\n' в качестве второго параметра в cin.ignore(), чтобы он отключил игнорирование при нажатии клавиши ввода.

person FallenWarrior    schedule 30.01.2017
comment
Да, я тоже пробовал, но ничего не меняется. В macOS второй cin просто пропускается, а в Linux он по-прежнему не работает, как я объяснял выше. - person Sandro; 30.01.2017