如何正确终止输入

时间:2020-06-19 04:50:05

标签: c++ c++11 vector input cin

当前正在研究从Stroustrup的介绍到C ++的练习,它要求:写一个给定两个向量的函数,price和weight计算一个值(“索引”),该值是所有price [i] * weight [一世]。确保具有weight.size()== price.size()

vector<double> weight;
vector<double> price;

void read_weight() {
  cout << "Input weight" << '\n';

  for (double weights; cin >> weights; ) {
    weight.push_back(weights);

    if (!(cin >> weights)) {
      cin.clear();
      cin.ignore(numeric_limits<double>::max(), '\n' );
      break;
    }
  }
}

void read_price() {
  cout << "Input price" << '\n';

  for (double prices; cin >> prices; ) {
    price.push_back(prices);

    if (!( cin >> prices)) {
      cin.clear();
      cin.ignore( numeric_limits<double>::max(), '\n' );
      break;
    }
  }
}

void calculate() {
  double sum = 0;
  for (int i = 0; i < price.size(); ++i)
    sum += price[i] * weight[i];

  cout << "Sum is " << sum << '\n';
}


int main() {
  read_weight();
  read_price();
  calculate();
}

这是我当前拥有的代码,但是我无法弄清楚如何正确终止输入。在之前的章节中,他的书中提到您可以使用输入(除了双精度字之外)来终止(例如|)。但是,我了解到这只会使cin进入失败状态,并且不允许我进入价格函数。不幸的是,这本书到目前为止还没有介绍如何处理这个问题,所以我只是复制了有关cin.clear和cin.ignore的代码,希望它能起作用。但这没什么用。我注意到,如果我将向量更改为int而不是double,并且实际上因行为差异而感到困惑,那么实际上允许我输入一个。我想知道是否有人可以给我提示如何解决此问题?

2 个答案:

答案 0 :(得分:2)

您可以使用std :: getline将cin的整行读取为字符串。此后,您需要确定输入的行是否为双精度行。我通常不建议对正则表达式使用太多内容(我在C ++中不经常使用它们),但是在这种情况下,我认为这是一个非常简单而合理的解决方案。如果字符串的格式为“ 32.23”(数字点数字),则可以使用std :: stod将其转换为双精度,将其压入向量并继续从cin读取。如果不是,则中断循环并继续执行程序流程。

远离使用全局变量,使用局部变量并将其传递给周围环境。

此外,请注意您的函数read_price和read_weight几乎相同。在这种情况下,您绝对只想编写一个(参数化的)函数。在这种情况下,您甚至都不需要参数,只需对两者使用相同的函数即可。

(您还可以将值直接从流(std :: cin)中读入双变量,由于您需要较少的转换,这可能被认为是更优雅的方法,但是下面的方法很简单,您不必担心在std :: cin中输入了什么)

#include <vector>
#include <string>
#include <iostream>
#include <regex>


std::vector<double> get_doubles_from_cin(){
    std::vector<double> doubles;
    std::regex double_regex ("\\d+\\.\\d+");
    std::string input;
    while(std::getline(std::cin, input)){
       if (std::regex_match(input, double_regex)){
           doubles.push_back(std::stod(input));
       }
       else{
           break;
       }
   }
    return doubles;
}


void calculate(std::vector<double>& weights, std::vector<double>& prices) {
  double sum = 0;
  for (int i = 0; i < prices.size(); ++i) {
      sum += weights[i] * prices[i];
  }
  std::cout << "Sum is " << sum << '\n';
}


int main() {
    std::cout << "Enter weights" << std::endl;
    auto weights = get_doubles_from_cin();
    std::cout << "Enter prices" << std::endl;
    auto prices = get_doubles_from_cin();
    calculate(weights, prices);
}

答案 1 :(得分:2)

您已经在那儿了。我已经写了read_weights()的评论替代品;您应该可以从那里拿走它。

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

// Use return values instead of working on global variables.
// Avoid using global variables whenever possible, they are a 
// maintenance pain.
std::vector< double > read_weights()
{
    std::vector< double > weights;
    double weight;

    // You can embed the \n right in the string, no need to put it as a
    // separate character.
    std::cout << "Input weights; enter a non-number to terminate input.\n";

    // If anything not double is entered, cin goes into fail state --
    // that is our terminating condition right there, so use it!
    while ( std::cin >> weight )
    {
        weights.push_back( weight );
    }

    // Clean up cin
    std::cin.clear();
    // Use the correct type for max(); you had 'double' here...
    cin.ignore( numeric_limits< std::streamsize >::max(), '\n' );

    // Don't worry about the apparent copying of the vector upon return.
    // Any modern compiler should be able to optimize this away.
    return weigths;
}

一个简单的main()进行测试:

int main()
{
    std::vector< double > weights = read_weights();

    std::cout << "Vector contents:\n";

    for ( auto & v : weights )
    {
        std::cout << v << "\n";
    }
}

现在您所需要添加的只是一个read_price() ...现在等等,您不是吗?由于您实际上所做的只是与read_weights()中的事情相同,因此请输入两倍!因此,将输入提示移出read_weights(),并使其成为 one 函数read_values(),您可以调用它两次,一次获取weights,一次获取{{ 1}} ...

prices

对于int main() { std::cout << "Enter weights; enter a non-number to terminate input.\n"; std::vector< double > weights = read_values(); std::cout << "Enter prices; enter a non-number to terminate input.\n"; std::vector< double > prices = read_values(); // ... } 函数,对参数使用引用,这样就不必复制向量:

calculate

一旦这一切运行起来,请记住,以后,您(至少应该是 )将学习void calculate( std::vector<double> & weights, std::vector<double> & prices ) ,函子和lambda。 。它应该消除对<algorithm>的需求,并用一个优雅的单行代码代替它……但这还没有到来,在这一点上,我不想让您感到困惑。

相关问题