将 STL 函数与结构一起使用?

Using STL functions with a struct?

我最近阅读了 C++ 中的 STL 函数。我了解函数的基本用法,但我很难让它们使用结构的成员变量。

我有这个结构:

struct Apples
{
   double weight; // oz
   string color;  // red or green
   void print() const { cout << color << ", " <<  weight << endl; }
};

基本上,我将 Apples 插入 vector 存储随机权重和随机颜色。现在,我想使用 count_if 函数来确定有多少个苹果大于给定的重量。我想转换这样的函数:

int cnt = 0;
for(auto it = crate.cbegin(); it != crate.cend(); ++it) 
    if(it->weight > toFind) 
        cnt++;

count_if() 版本(这不起作用):

int cnt = count_if(crate.begin(), crate,end(), isGreater())

isGreater()是这样的:

void isGreater()
{
   if(it->weight > toFind) 
      return it->weight > toFind;
}

我对 STL 函数不了解,struct 是如何将结构内部的成员变量与 STL 函数一起使用。我也不确定在 STL 函数内部传递什么。在这种情况下使用 lambda 函数会更好吗?如果是,为什么?

这是目前所有的代码,如果看不懂:

#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <deque>
#include <string>


using namespace std;

struct Apples
{
   double weight; // oz
   string color;  // red or green
   void print() const { cout << color << ", " <<  weight << endl; }
};

void isGreater()
{
   if(it->weight > toFind) 
      return it->weight > toFind;
}

int main()
{
   srand(time(nullptr));
   const double minWeight = 8.;
   const double maxWeight = 3.;

   cout << "Input crate size: ";
   int size;
   cin >> size;

   vector <Apples> crate(size);
   for(auto it = crate.begin(); it != crate.end(); ++it)
   {
      it->weight = minWeight + static_cast<double>(rand())/RAND_MAX*(maxWeight - minWeight);
      it->color = rand() % 2 == 1 ? "green" : "red";
   }

   cout << "Enter weight to find: ";
   double toFind;
   cin >> toFind;

  //this is what I want to convert to count if
   int cnt = 0;
   for(auto it = crate.cbegin(); it != crate.cend(); ++it) 
      if(it->weight > toFind) 
         cnt++; 

您没有将苹果存储在向量中。 您必须在循环中初始化每个苹果,然后将它们存储在向量中。 crate.push_back(新苹果)。 所以 运行 从 0 到 size 的循环。 在该循环内初始化新苹果并赋予它们重量和颜色 然后 push_back 在向量中:

for(int i = 0; i < size ++i)
 { 
   apples newApple;
   newApple.weight = ...;
   newApple.color = ...;
   crate.push_back(newApple);
 }

这通常是通过创建一个“函子”class 来实现的,class 其对象可以像函数一样被调用。每个实例调用持有参考权重:

struct IsGreater {
    double w;
    IsGreater(double weight) : w{weight} {}
    bool operator()(const Apples& A) const {
         return A.weight > w;
    }
};

然后我们只需要创建一个 class 的实例来保存参考权重并将其传递给 count_if:

const int count = std::count_if(crate.begin(), crate.end(), IsGreater(toFind));

您可以避免使用 lambda 创建显式 class:

const int count = std::count_if(crate.begin(), crate.end(),
                               [=](const Apples& A) -> bool {
                                    return A.weight > toFind;
                               });

这里参考值toFind被值捕获

std::count_if 将一元谓词作为第三个参数。在这种情况下,一元谓词是一个接受一个对象的函数,如果对象匹配查找条件则返回 true,否则返回 false

由于您的标准取决于 toFind,使用 lambda 捕获似乎更简洁 toFind:

int cnt = count_if(crate.begin(), crate.end(), [toFind](const Apple& apple) {
  return it->weight > toFind;
});

如果你想要一个独立的功能,你可以使用:

bool isGreater(double toFind, const Apple& apple) {
   return it->weight > toFind;
}

...

int cnt = count_if(crate.begin(), crate.end(),
        std::bind(&isGreater, toFind, std::placeholders::_1));

注意,你不需要调用函数,你需要传递它:

int cnt = count_if(crate.begin(), crate,end(), isGreater())
//                                                      ^^ remove parentheses