How to use find() to find a struct member in vector?
How to use find() to find a struct member in vector, Thanks!
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
const int name_max=30;
struct member
{
char name[name_max];
int age;
char sex[1];
};
member memb[6]={{"an", 6,'m'},{"ben", 60,'f'},{"carl", 26,'f'},{"dan", 36,'m'},{"el", 8,'m'},{"findy", 77,'f'}};
void main()
{
vector<member> vec(memb,memb+6);
vector<member>::iterator it=vec.begin();
for(;it!=vec.end();it++)
{
cout<<(*it).name<<"\t"<<(*it).age<<"\t"<<(*it).sex<<"\n";
}
member mi={"findy", 77,'f'};
vector<member>::iterator flag=find(vec.begin(),vec.end(),mi.name); //wrong
// vector<member>::iterator flag=find(vec.begin(),vec.end(),mi); //wrong too
if(flag!=vec.end())
printf("find the member which name is findy");
else
printf("find() doesn't work, could tell me why?");
}
Any help will be apprieciated!
Re: How to use find() to find a struct member in vector?
First, please use code tags.
Second, you could use std::search.
Code:
const int name_max=30;
struct member
{
char name[name_max];
int age;
char sex[1];
};
bool MatchMember(member m1, member m2)
{
return strcmp(m1.name, m2.name) == 0 &&
m1.age == m2.age &&
m1.sex[0] == m2.sex[0];
}
int main(int argc, char* argv[])
{
member memb[6]={{"an", 6,'m'},{"ben", 60,'f'},{"carl", 26,'f'},{"dan", 36,'m'},{"el", 8,'m'},{"findy", 77,'f'}};
vector<member> vec(memb,memb+6);
for(vector<member>::const_iterator it=vec.begin(); it!=vec.end(); it++)
{
cout<<(*it).name<<"\t"<<(*it).age<<"\t"<< (*it).sex[0] << "\n";
}
member mi={"ben", 60,'f'};
vector<member> searchlist;
searchlist.push_back(mi);
vector<member>::iterator flag = std::search(vec.begin(),vec.end(),searchlist.begin(),searchlist.end(),MatchMember);
if(flag != vec.end())
{
cout << "member found" << endl;
}
else
{
cout << "member not found" << endl;
}
return 0;
}
Note that there are some differences in printing the vector. First, I used a const_iterator not an iterator, because the vector will only be displayed not changed. Second, sex is declared as an array of char (with 1 element), thus it's considered a null terminated string when you print it like (*it).sex so it will display everything encountered in memory until the first 0. You need to use (*it).sex[0] to print just a char.
Re: How to use find() to find a struct member in vector?
Next time, please use code tags.
(You can edit that post too... BTW)
Your vector is a container of structs, not a container of character arrays. Hence, this is not correct:
Quote:
Originally Posted by forester
vector<member>::iterator flag=find(vec.begin(),vec.end(),mi.name);
This line:
Quote:
Originally Posted by forester
vector<member>::iterator flag=find(vec.begin(),vec.end(),mi);
is closer to being correct as you pass the right parameters.
The find above will do a binary comparison, and hence it will not work.
(Reason: your structure contains character arrays a.k.a pointers)
Hence, the find above is syntactically correct, but, logically wrong.
I would recommend this change:
Code:
#include <string>
struct member
{
std::string name;
int age;
char sex;
};
The operators of the class std::string will ensure that the following yields correct results:
Code:
member mi={"findy", 77,'f'};
vector<member>::iterator flag = find(vec.begin(),vec.end(),mi);
if (flag != vec.end ())
// You found it!
Let me know if this makes the situation clear...
Re: How to use find() to find a struct member in vector?
You can also use find_if() ...
1) add the following struct to your code ...
Code:
struct NameEquals
{
bool operator () (const member & rhs) const
{
return (strcmp(name,rhs.name) == 0);
}
NameEquals(const char * n) : name(n) {}
private:
const char * name;
};
2) use as follows:
Code:
vector<member>::iterator flag=find_if(vec.begin(),vec.end(),NameEquals("findy"));
Re: How to use find() to find a struct member in vector?
You can also overload operator== thus:
Code:
struct member
{
char name[name_max];
int age;
char sex[1];
};
bool operator==(const member& lhs, const member& rhs )
{
// etc, as with implementations above
}
This, by the way, is assuming that "member" is some 3rd-party struct or part of some C code library therefore you don't wish to modify it.
If you are going to write the whole project in C++, you'll probably want to make some of the other amendments to make "member" a class and use std::string instead of string. You could also use an enum for sex thus:
Code:
struct member
{
enum gender{ male, female };
// etc.
};
You might wish to compare by name alone, if all names are unique. Or you might want to use some unique identifier (after all there could be more than one person called John Smith who is male and 20 years old).
Re: How to use find() to find a struct member in vector?
Quote:
Originally Posted by cilu
First, please use code tags.
Second, you could use std::search.
Code:
const int name_max=30;
struct member
{
char name[name_max];
int age;
char sex[1];
};
bool MatchMember(member m1, member m2)
{
return strcmp(m1.name, m2.name) == 0 &&
m1.age == m2.age &&
m1.sex[0] == m2.sex[0];
}
int main(int argc, char* argv[])
{
member memb[6]={{"an", 6,'m'},{"ben", 60,'f'},{"carl", 26,'f'},{"dan", 36,'m'},{"el", 8,'m'},{"findy", 77,'f'}};
vector<member> vec(memb,memb+6);
for(vector<member>::const_iterator it=vec.begin(); it!=vec.end(); it++)
{
cout<<(*it).name<<"\t"<<(*it).age<<"\t"<< (*it).sex[0] << "\n";
}
member mi={"ben", 60,'f'};
vector<member> searchlist;
searchlist.push_back(mi);
vector<member>::iterator flag = std::search(vec.begin(),vec.end(),searchlist.begin(),searchlist.end(),MatchMember);
if(flag != vec.end())
{
cout << "member found" << endl;
}
else
{
cout << "member not found" << endl;
}
return 0;
}
Note that there are some differences in printing the vector. First, I used a const_iterator not an iterator, because the vector will only be displayed not changed. Second, sex is declared as an array of char (with 1 element), thus it's considered a null terminated string when you print it like (*it).sex so it will display everything encountered in memory until the first 0. You need to use (*it).sex[0] to print just a char.
Why would you use std::search() when you only need to find one element? Wouldn't std::find() be more appropriate?
Re: How to use find() to find a struct member in vector?
Quote:
By Siddhartha
I would recommend this change:
#include <string>
struct member
{
std::string name;
int age;
char sex;
};
I tried to change the type of the name from char[name_max] to string, but after compiling, I got the error info as below, WHere is wrong?
G:\vec_find_f.cpp(17) : error C2440: 'initializing' : cannot convert from 'char [3]' to 'struct member'
No constructor could take the source type, or constructor overload resolution was ambiguous
G:\vec_find_f.cpp(17) : error C2440: 'initializing' : cannot convert from 'const int' to 'struct member'
No constructor could take the source type, or constructor overload resolution was ambiguous
G:\vec_find_f.cpp(17) : error C2440: 'initializing' : cannot convert from 'const char' to 'struct member'
No constructor could take the source type, or constructor overload resolution was ambiguous
Re: How to use find() to find a struct member in vector?
Quote:
Originally Posted by forester
I tried to change the type of the name from char[name_max] to string, but after compiling, I got the error info as below, WHere is wrong?
G:\vec_find_f.cpp(17) : error C2440: 'initializing' : cannot convert from 'char [3]' to 'struct member'
No constructor could take the source type, or constructor overload resolution was ambiguous
G:\vec_find_f.cpp(17) : error C2440: 'initializing' : cannot convert from 'const int' to 'struct member'
No constructor could take the source type, or constructor overload resolution was ambiguous
G:\vec_find_f.cpp(17) : error C2440: 'initializing' : cannot convert from 'const char' to 'struct member'
No constructor could take the source type, or constructor overload resolution was ambiguous
The error you have posted does not belong to the lines of code above (struct member definition).
It perhaps belongs to your usage of the struct. It shows the line number at fault: 17 - post that.
Re: How to use find() to find a struct member in vector?
Quote:
by cilu
bool MatchMember(member m1, member m2)
{
return strcmp(m1.name, m2.name) == 0 &&
m1.age == m2.age &&
m1.sex[0] == m2.sex[0];
}
and my code is below:
member mi={"findy", 77,'f'};
vector<member>::iterator flag=find(vec.begin(),vec.end(),MatchMember);
BUT after compiling, I got error info as below, saying m1.age == m2.age &&m1.sex[0] == m2.sex[0]; requires array or pointer type, where is wrong?
G:\vec_find_f.cppCompiling...
vec_find_f.cpp(20) : error C2109: subscript requires array or pointer type
G:\vec_find_f.cpp(20) : error C2109: subscript requires array or pointer type
Re: How to use find() to find a struct member in vector?
Quote:
Originally Posted by Siddhartha
The error you have posted does not belong to the lines of code above (struct member definition).
It perhaps belongs to your usage of the struct. It shows the line number at fault: 17 - post that.
Thank you Siddhartha for quick reply, here is the whole code.
Code:
#include <vector>
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
//const int name_max=30;
struct member
{
// char name[name_max];
string name;
int age;
char sex;
};
member memb[6]={{"an", 6,'m'},{"ben", 60,'f'},{"carl", 26,'f'},{"dan", 36,'m'},{"el", 8,'m'},{"findy", 77,'f'}};
void main()
{
vector<member> vec(memb,memb+6);
vector<member>::iterator it=vec.begin();
int i=0;
for(;it!=vec.end();it++,i++)
{
cout<<(*it).name<<"\t"<<(*it).age<<"\t"<<(*it).sex<<"\n";
}
member mi={"findy", 77,'f'};
vector<member>::iterator flag=find(vec.begin(),vec.end(),mi);
if(flag!=vec.end())
printf("Find IT");
else
printf("find() doesn't work");
}
Re: How to use find() to find a struct member in vector?
Quote:
Originally Posted by forester
Thank you Siddhartha for quick reply, here is the whole code.
It is int main(), not void main().
Code:
bool MatchMember(member m1, member m2)
{
return strcmp(m1.name, m2.name) == 0 &&
The class you're using is now std::string. Why are you comparing it using 'C' functions?
Code:
m1.sex[0] == m2.sex[0];
Where have you declared "sex" as being an array?
Here are the corrections:
Code:
bool MatchMember(const member& m1, const member& m2)
{
return (m1.name == m2.name &&
m1.sex == m2.sex &&
m1.age == m2.age);
}
Regards,
Paul McKenzie
Re: How to use find() to find a struct member in vector?
Code:
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
struct member
{
std::string name;
int age;
char sex;
member() {}
member( const std::string name_, int age_, char sex_ )
: name( name_), age( age_), sex( sex_ )
{
}
};
bool operator==( const member & lhs, const member& rhs )
{
return (lhs.name == rhs.name) && (lhs.age==rhs.age) &&
(lhs.sex == rhs.sex);
}
std::ostream & operator<<( std::ostream & os, const member & mem )
{
os << mem.name << '\t' << mem.age << '\t' << mem.sex;
return os;
}
int main()
{
std::vector<member> vec(memb,memb+6);
std::copy( ostream_iterator< member >(cout, "\n"), vec.begin(), vec.end() );
member mi("findy", 77,'f' );
vector<member>::const_iterator flag=find(vec.begin(),vec.end(),mi);
if(flag!=vec.end())
{
std::cout << "Found member " << mi << std::endl;
}
else
{
std::cout << "Could not find member " << mi << std::endl;
}
return 0;
}
I can also show you how you can do a version that matches age only, without changing operator==.
Re: How to use find() to find a struct member in vector?
I use the recommended by cilu, though there is a member mi={"findy", 77,'f'}; indeed,
but the std::search() returns no such a member, the code is below, I couldn't found where is wrong,
Thanks for help!
Code:
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
const int name_max=30;
struct member
{
char name[name_max];
int age;
char sex;
};
bool MatchMember(member m1, member m2)
{
return strcmp(m1.name,m2.name)&&m1.age==m2.age&&m1.sex==m2.sex;
}
member memb[6]={{"an", 6,'m'},{"ben", 60,'f'},{"carl", 26,'f'},{"dan", 36,'m'},{"el", 8,'m'},{"findy", 77,'f'}};
int main()
{
vector<member> vec(memb,memb+6);
/* for(int i=0;i<6;i++)
{
vec.push_back(memb[i]);
}
*/ vector<member>::const_iterator it=vec.begin();
int i=0;
for(;it!=vec.end();it++,i++)
{
cout<<(*it).name<<"\t"<<(*it).age<<"\t"<<(*it).sex<<"\n";
}
member mi={"findy", 77,'f'};
vector<member> searchlist;
searchlist.push_back(mi);
vector<member>::iterator flag=search(vec.begin(),vec.end(),searchlist.begin(),searchlist.end(), MatchMember);
if(flag!=vec.end())
printf("member found.\n");
else
printf("find() doesn't work, where is wrong?\n");
return 0;
}
Re: How to use find() to find a struct member in vector?
Quote:
Originally Posted by forester
but the std::search() returns no such a member, the code is below, I couldn't found where is wrong,
One does not use std::search to locate one element.
std::find is the way to go - and I wonder why you are not using it, in spite of Paul having made corrections for you...
Re: How to use find() to find a struct member in vector?
Quote:
Originally Posted by forester
I use the recommended by cilu, though there is a member mi={"findy", 77,'f'}; indeed,
but the std::search() returns no such a member, the code is below, I couldn't found where is wrong,
I remember that when I wrote that code I've tested it and worked ok...