First of all, this is C++, so all those fixed-size arrays are just a buffer overflow in waiting - with structures so large, there's no performance benefit from doing it that way.
Thus, I'd start as follows. Whenever an unknown number of characters is desired, std::string
is used. Whenever an unknown number of elements of some other type is desired, std::vector
is used.
#include <string>
#include <vector>
struct Auxiliary {
std::string come_greet, leave_greet;
std::vector<std::string> aux_words; // if this is just one word, don't call it words!
bool operator==(const Auxiliary &o) const {
return &o == this ||
o.come_greet == come_greet &&
o.leave_greet == leave_greet &&
o.aux_words == aux_words;
}
};
struct Outer {
static Auxiliary not_found;
std::vector<Auxiliary> j; // j is a terrible name - choose something with meaning!
Auxiliary &find_answer(std::string Auxiliary::*field, const std::string &answer);
};
Then, the search is a method: it doesn't need to have the mm
argument since it knows the size of the j
vector, it doesn't need to be fed j
since it has direct access to it, and we can actually write C++, not C. The field
argument specifies which member of the Auxiliary
structure is meant to be searched, e.g. &Auxiliary::come_greet
. Also note the use of std::string::find
instead of strstr
. find_answer
returns a reference to an Auxiliary
, since returning references is cheap. It could also return a value (i.e. Auxiliary
, not Auxiliary&
), but that would copy the value, most likely unnecessarily.
Auxiliary Outer::not_found;
Auxiliary& Outer::find_answer(std::string Auxiliary::*field, const std::string &answer) {
for (auto &aux : j)
if ((aux.*field).find(answer) != std::string::npos)
return aux;
return not_found;
}
If you wouldn't need to modify Auxiliary
via the returned reference, the returned type should be const Auxiliary&
.
Finally, a little test that demonstrates the behavior:
#include <cassert>
int main() {
Outer outer;
outer.j = {
{"come0", "leave0", {"auxa_0", "auxb_0"}},
{"come1", "leave1", {"auxa_1"}}
};
assert(outer.find_answer(&Auxiliary::come_greet, "foo") == Outer::not_found);
assert(outer.find_answer(&Auxiliary::come_greet, "come0") == outer.j[0]);
assert(outer.find_answer(&Auxiliary::come_greet, "come1") == outer.j[1]);
assert(outer.find_answer(&Auxiliary::leave_greet, "leave0") == outer.j[0]);
assert(outer.find_answer(&Auxiliary::leave_greet, "leave1") == outer.j[1]);
}
This concludes the complete compileable example.