Проблема: Когда я пытаюсь остановить первый цикл и перейти ко второму, нажав CTRL-D или введя букву в качестве ввода, программа выйдет и пропустит второй цикл.Я понял, что это относится к механизму cin, но мне не удалось вылечить его.
Это потому, что когда вы пытаетесь прочитать письмо или EOF (Ctrl-D), это устанавливает состояние потокав плохом состоянии.Как только это происходит, все операции в потоке терпят неудачу (пока вы не сбросите его).Это можно сделать, вызвав clear ()
std::cin.clear();
Вопрос: как мне это запрограммировать?Какой наименее болезненный способ преодолеть проблему?
Я бы не использовал эту технику.
Я бы использовал что-то вроде пустой строки в качестве разделителя между циклами.Таким образом, код выглядит следующим образом:
while(std::getline(std::cin, line) && !line.empty())
{
// STUFF
}
while(std::getline(std::cin, line) && !line.empty())
{
// STUFF
}
Попробуйте это:
Примечание: в C ++ потоки работают лучше всего, когда числа разделены пробелом.Так что легко использовать пробел или табуляцию для разделения чисел.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
struct Average
{
Average(): result(0.0), count(0) {}
void operator()(double const& val) { result += val;++count;}
operator double() { return (count == 0) ? 0.0 : result/count;}
double result;
int count;
};
struct Sum
{
Sum(): result(0.0) {}
void operator()(double const& val) { result += val;}
operator double() { return result;}
double result;
};
int main()
{
std::string line;
// Read a line at a time.
// If the read fails or the line read is empty then stop looping.
while(std::getline(std::cin, line) && !line.empty())
{
// In C++ we use std::Vector to represent arrays.
std::vector<double> data;
std::stringstream lineStream(line);
// Copy a set of space separated integers from the line into data.
// I know you wanted doubles (I do this next time)
// I just wanted to show how easy it is to change between the types being
// read. So here I use integers and below I use doubles.
std::copy( std::istream_iterator<int>(lineStream),
std::istream_iterator<int>(),
std::back_inserter(data));
// Sum is a functor type.
// This means when you treat it like a function then it calls the method operator()
// We call sum(x) for each member of the vector data
Sum sum;
sum = std::for_each(data.begin(), data.end(), sum);
std::cout << "Sum: " << static_cast<double>(sum) << "\n";
}
// Read a line at a time.
// If the read fails or the line read is empty then stop looping.
while(std::getline(std::cin, line) && !line.empty())
{
// In C++ we use std::Vector to represent arrays.
std::vector<double> data;
std::stringstream lineStream(line);
// Same as above but we read doubles from the input not integers.
// Notice the sleigh difference from above.
std::copy( std::istream_iterator<double>(lineStream),
std::istream_iterator<double>(),
std::back_inserter(data));
// Average is a functor type.
// This means when you treat it like a function then it calls the method operator()
// We call average(x) for each member of the vector data
Average average;
average = std::for_each(data.begin(), data.end(), average);
std::cout << "Average: " << static_cast<double>(average) << "\n";
}
}
// Или мы могли бы слегка шаблонизировать код:
template<typename T, typename F>
void doAction()
{
std::string line;
// Read a line at a time.
// If the read fails or the line read is empty then stop looping.
while(std::getline(std::cin, line) && !line.empty())
{
std::stringstream lineStream(line);
// F is a functor type.
// This means when you treat it like a function then it calls the method operator()
// We call action(x) for each object type 'T' that we find on the line.
// Notice how we do not actual need to store the data in an array first
// We can actually processes the data as we read it from the line
F action;
action = std::for_each( std::istream_iterator<T>(lineStream),
std::istream_iterator<T>(),
action);
std::cout << "Action Result: " << static_cast<double>(action) << "\n";
}
}
int main()
{
doAction<int, Sum>();
doAction<double, Average>();
}