将 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
我最近阅读了 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