我的任务是制作一个程序,按标题,流派,年份,评级,主演等搜索400多部电影(使用链接列表链接)。
虽然有一个问题,我们只允许一个搜索功能通过链表预先形成搜索。此外,在该搜索功能中,我们只允许一个循环 - 我假设在我的情况下将是... ...
while (moviePtr != NULL)
显然,如果是演员搜索或类型搜索,他们将会有许多不同的实例。在演员,流派,评级,年份,子流派和支持演员的情况下,它应该输出它的每个单个实例。 (例如,如果Kevin Bacon在x-men和笔记本中,它应该输出的不仅仅是其中一个(输出文件而不是屏幕)。)
我发现自己完全被我们获得的这些限制所困扰。 我的搜索功能如何处理不同的数据类型? (年份和评级必须声明为整数)。它将如何知道我正在寻找什么?如果我正在寻找演员,我也不希望它也能搜索演出。
非常感谢任何关于如何开始和开始的建议。
编辑: 嗨,所有的想法id更新你们在我做了什么。我有3种不同的搜索功能。一个用于数值(年份和评级),一个用于流派和演员,最后一个用于标题。
以下是这三个代码。 首先是标题搜索。
void TitleSearched(MovieNode*head,
string titleSearched,
ofstream& outFile)
{
MovieNode* moviePtr;
bool found;
moviePtr = head;
found = false;
while (moviePtr !=NULL & !found)
{
if (moviePtr-> title == titleSearched)
{
found = true;
}
else
{
moviePtr = moviePtr -> next;
}
}
if (found)
{
cout << endl << titleSearched << " has been found!\n";
TitleOutput (moviePtr,outFile);
}
else
{
cout << endl << titleSearched << " was not found.\n";
}
}
现在是年度/评级搜索。
int NumSearched(MovieNode* head, int numSearched)
{
int instances;
MovieNode* moviePtr;
ofstream outFile;
moviePtr = head;
instances = 0;
while (moviePtr !=NULL)
{
if (moviePtr-> year == numSearched)
{
instances = instances +1;
NumOutList(moviePtr,outFile,"year",numSearched,instances);
moviePtr = moviePtr -> next;
}
else if (moviePtr->rating == numSearched)
{
instances = instances +1;
NumOutList(moviePtr,outFile,"rating",numSearched,instances);
moviePtr = moviePtr -> next;
}
else
{
moviePtr = moviePtr ->next;
}
}
return instances;
}
最后是流派/演员搜索。
int ItemSearch (MovieNode* head,string itemSearched, ofstream& outFile)
{
int instances;
MovieNode* moviePtr;
moviePtr = head;
instances = 0;
while (moviePtr !=NULL)
{
if (moviePtr-> genre == itemSearched || moviePtr ->subGenre == itemSearched)
{
instances = instances +1;
OutList(moviePtr,outFile,"Genre",itemSearched,instances);
moviePtr = moviePtr -> next;
}
else if (moviePtr->leadActor == itemSearched || moviePtr->supportActor == itemSearched)
{
instances = instances +1;
OutList(moviePtr,outFile,"Actor",itemSearched,instances);
moviePtr = moviePtr -> next;
}
else
{
moviePtr = moviePtr ->next;
}
}
return instances;
}
我想提醒大家我的任务是什么。 1.将这三个搜索功能合二为一 2.搜索中只有一个while循环 3.在任何给定函数中只返回一个(但是,假设这在组合时将是一个无效函数)
我的主要问题是我的内容和字符串。我不被允许将评级或年份声明为字符串。只是整理这三个代码的代码格式给了我一个头痛
答案 0 :(得分:2)
您可以以接受谓词作为参数的方式编写搜索功能。谓词是某种“functionoid”(意思是,任何能够像函数一样被“调用”的东西 - 它可以是函数,或lambda,或函数对象。)
在C ++标准库中,谓词用于许多标准算法,所以你会看到代码(使用标准容器),如下所示:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
bool begins_with_s(std::string s)
{
return s.length() > 0 &&
std::toupper( s.at(0) ) == 'S';
}
bool contains_a_number(std::string s)
{
return std::find_if(s.begin(), s.end(), std::isdigit) != s.end();
}
int main()
{
std::string movies_array[] =
{
"King Kong",
"Singin in the Rain",
"Die Hard 2",
"Superman",
"Star Wars",
"Jaws 3"
};
std::vector<std::string> movies( std::begin(movies_array),
std::end(movies_array) );
// Use predicate - count if the movie name begins with "S"
std::cout << "Movies beginning with S: "
<< std::count_if(movies.begin(), movies.end(), begins_with_s)
<< std::endl;
// Use predicate - count if the movie name contains a number
std::cout << "Movies containing a number: "
<< std::count_if(movies.begin(), movies.end(), contains_a_number)
<< std::endl;
}
以这种方式实现C ++标准算法的方式是接受表示谓词的模板参数,沿着
行。template< typename PredicateType >
void my_function(PredicateType predicate)
{
Movie my_movie;
predicate(my_movie);
}
这是一种来自功能性编程学派的思考 - 将函数传递给函数(将函数视为“一等公民”)。
答案 1 :(得分:2)
您可以让搜索功能将“匹配”功能作为其参数之一,并在每部电影上调用此匹配功能以查看电影是否匹配。然后,您可以使用不同的匹配功能调用搜索功能。
这样的事情:
template <typename MatchFunction>
void search_movies(movie* moviePtr, MatchFunction match)
{
while (moviePtr != NULL)
{
if (match(*moviePtr))
{
// output movie
}
moviePtr = moviePtr->next;
}
}
然后您可以声明匹配函数:
bool matches_actor(movie& m, const std::string& actor)
{
return m.actor == actor;
}
并使用如下特定查询调用它:
search_movies(moviePtr, std::bind(matches_actor, _1, "Morgan Freeman"));
(std::bind
是来自<functional>
的C ++ 11函数;您可以等效地使用boost::bind
或std::bind2nd
)
或者,如果您更喜欢采用更C风格的做事方式,您可以这样做:
void search_movies(movie* moviePtr, bool (*match)(movie*, void*), void* match_arg)
{
while (moviePtr != NULL)
{
if (match(moviePtr, match_arg))
{
// output movie
}
moviePtr = moviePtr->next;
}
}
...
bool matches_actor(movie* m, void* actor)
{
return m.actor == *((std::string*)actor);
}
...
std::string actor = "Morgan Freeman";
search_movies(moviePtr, &matches_actor, (void*)(&actor));
答案 2 :(得分:2)
除了传递函子来检查匹配的选项外,还有其他选项。一个这样的选择是采取一组可选条件来检查(您可以使用boost::optional
或手工制作的方法,或使用指针。例如:
void print_matching( node* list, int * year, std::string * actor... ) {
// iterate over the list:
while (...) {
if ( ( !year || ptr->year == *year )
&& ( !actor || ptr->actor == *actor )
&& ...
)
{
// Film matches, print it
}
}
}
为了简化函数签名,您可以创建一个search_pattern
类型来封装您要测试的字段(例如使用不同的方法:bool来确定可选性):
struct pattern {
bool check_actor;
std::string actor;
bool check_year;
int year;
};
void print_matching( node* list, pattern const & p ) {
// iterate over the list:
while (...) {
if ( ( !p.check_year || ptr->year == p.year )
&& ( !p.check_actor || ptr->actor == p.actor )
&& ...
)
{
// Film matches, print it
}
}
}
在最后一种情况下,您实际上可以将测试移动到pattern
对象中,并具有一个函数:
bool pattern :: matches(movie cosnt&amp; m)const { 返回(!check_year || m.year == year) &amp;&amp;(!check_actor || m.actor == actor); } void print_matching(node * list,pattern const&amp; p){ //遍历列表: 而(...){ if(p.matches(list-&gt; data)) { //电影匹配,打印出来 } } }