C++如何使find_if不仅返回应用pred为true的第一个对象
C++ How to make find_if not only return the first object for which applying pred to it is true
这是为了允许用户输入他/她想要搜索的姓名、联系人和地址。我想做的是显示所有应用pred的对象,但我似乎无法使其工作。
static string searchName, searchContact, searchAddress;
bool search_User(User &u)
{
return (u.getName() == searchName && u.getContact() == searchContact && u.getAddress() == searchAddress);
}
void searchUser(vector<User> &u)
{
cout << "Name of user: ";
getline(cin, searchName);
cout << "Contact of tutor: ";
getline(cin, searchContact);
cout << "Adress of user: ";
getline(cin, searchAddress);
vector<User>::iterator i;
i = find_if(u.begin(), u.end(), search_User);
cout << i->getName() << i->getContact() << i->getAddress() << endl;
}
通常的解决方案是使用std::copy_if
:
std::vector<User> matches;
std::copy_if(v.begin(), v.end(), std::back_inserter(matches),
[Name, Contact, Address](User const& u)
{ return u.getName() == Name && u.getContact() == Contact && u.getAddress() == Address;});
或者只写一个经典的循环
for (User& u : users) {
if (search_User(u) {
std::cout << u; // Assumes you've implemented operator<<(ostream&, User)
}
}
伪代码:
for(iterator i = v.begin();
(i = find_if(i, v.end(), ...)) != v.end(); ++i )
{
print *i;
}
一种方法是使用std::copy_if
(从C++11开始)或std::remove_copy_if
,用not1
否定谓词——这是我在"为什么没有std::copy_if算法?"的答案中找到的copy_if
解决方法。
std::vector<User> result;
std::remove_copy_if(u.begin(), u.end(),
std::back_inserter(result),
std::not1(std::ptr_fun(search_User)));
另一种方法是使用std::partition
算法。
对范围[first,last)中的元素进行重新排序,使谓词p返回true的所有元素位于谓词p返回false的元素之前。
(http://en.cppreference.com/w/cpp/algorithm/partition)
std::vector<User>::const_iterator newend =
std::partition(u.begin(), u.end(), search_User);
(需要C++11)与MSchangers建议的略有不同的是,在找到匹配项时写入std::cout
:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
...
std::ostream& operator<<(std::ostream& a_out, const User& a_user)
{
std::cout << a_user.getName() << ", " << a_user.getContact() << ", " <<
a_user.getAddress();
return a_out;
}
...
std::copy_if(users.begin(),
users.end(),
std::ostream_iterator<const User>(std::cout, "n"),
[name, contact, address](const User& a_user)
{
return name == a_user.getName() &&
contact == a_user.getContact() &&
address == a_user.getAddress();
});
编辑:
要显示"用户未找到"消息,您可以按如下方式修改:
int count = 0;
std::copy_if(users.begin(),
users.end(),
std::ostream_iterator<const User>(std::cout, "n"),
[&count, name, contact, address](const User& a_user) -> bool
{
if (name == a_user.getName() &&
contact == a_user.getContact() &&
address == a_user.getAddress())
{
count++;
return true;
}
return false;
});
if (!count) std::cout << "User not foundn";
您可以通过递增find_if()的返回值并将其传递给后续调用来循环所有命中,例如:
// Switched to const_iterator, purely because the example code wasn't
// changing the elements found.
vector<User>::const_iterator i = find_if(u.begin(), u.end(), search_User);
while (i != u.end())
{
cout << i->getName() << i->getContact() << i->getAddress() << endl;
++i;
i = find_if(i, u.end(), search_User);
}
对于C++14,我的首选解决方案是使用std::copy_if
并返回所有匹配的向量,并传入保持分区所需的参数:
std::vector<User> findMatches( const std::vector<User> &v) {
std::vector<User> matches;
std::copy_if(v.begin(), v.end(), std::back_inserter(matches),
[Name, Contact, Address](User& u)
{
return(u.getName() == Name
&& u.getContact() == Contact
&& u.getAddress() == Address);
});
return matches;
}
@MSchangers目前发布的顶级解决方案在lambda中有一个错误,该错误缺少一个return语句。
https://godbolt.org/g/CQOXzv
http://cpp.sh/2j7q7
$ g++-5 -std=c++14 user.cpp -o test.bin
$ ./test.bin
要在命令行中编译,请将以下内容保存为user.cpp,然后运行:
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
class User {
public:
std::string Name;
std::string Contact;
std::string Address;
auto getName() {
return Name;
}
auto getContact() {
return Contact;
}
auto getAddress() {
return Address;
}
User() = default;
};
std::ostream & operator<<(std::ostream &stream, const User &u)
{
stream << u.Name << " " << u.Contact << " " << u.Address;
return stream;
}
std::vector<User> findmatches( std::vector<User> &v,
std::string Name,
std::string Contact,
std::string Address) {
std::vector<User> matches;
std::copy_if(v.begin(), v.end(), std::back_inserter(matches),
[Name, Contact, Address](User& u)
{
return(u.getName() == Name
&& u.getContact() == Contact
&& u.getAddress() == Address);
});
return matches;
}
int main () {
std::vector<User> v {};
v.push_back({"Tom Cruise","917-032-2342","200 Top Gun Lane, Miramar, CA 93212"});
v.push_back({"Chuck Norris","911-032-1111","300 Santa Monica Blvd, Hollywood, CA 93212"});
v.push_back({"Santa Clause","315-4323-3111","1 North Pole Circle, North Pole, Elf Division, Antarctica 00000"});
auto matches = findmatches(v, "Chuck Norris", "911-032-1111", "300 Santa Monica Blvd, Hollywood, CA 93212");
for ( auto i : matches ) {
std::cout << i << std::endl;
}
}
将静态变量转换为结构:
struct Search_conditions
{
string name, contact, address;
bool operator()(User& u) {...}
};
Search_conditions sc = {name, contact, address};
find_if(u.begin(), u.end(), sc);
相关文章:
- 试图在visual studio上用C++创建一个桌面应用程序
- FFmpeg:制作一个应用程序比直接使用ffmepg更好吗
- c++r值引用应用于函数指针
- 在C应用程序中运行C++(带有STL)函数
- 使用VerQueryValue检索应用程序的文件描述
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 使用调试/崩溃报告将应用程序部署到客户端
- C++控制台应用程序阻止退出
- 码头化的C++应用程序是否向后兼容早期的内核版本
- 将应用程序从32位移植到64位时出现问题
- 有没有任务栏API可以立即应用注册表更改
- 如何改变c++应用程序的视觉效果
- WM_CTLCOLORSTATIC从未在WIN32应用程序中触发
- PC中的程序和PHONE中的本机描述应用程序之间的数据连接
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- 示例外壳应用程序显示的 V8 "segmentation fault (core dumped)"错误
- phytec phyBOARD iMX-6在从闪存而不是SD卡运行qt5 opengles应用程序时表现不佳(FPS减半
- TMap::Emplace() 在应用现有密钥时会覆盖吗?
- 为什么导入Mixed native/CLR lib.dll的本机C++应用程序没有在Mixed lib.dll中的外部变
- C++如何使find_if不仅返回应用pred为true的第一个对象