3

我的任务是制作一个程序,按标题、类型、年份、评级、男主角等搜索 400 多部电影(使用链接列表链接在一起)。

但是有一个问题,我们只允许一个搜索函数通过链表进行搜索。此外,在该搜索功能中,我们只允许使用一个 while 循环——我假设在我的情况下将类似于......

  while (moviePtr != NULL)

显然,如果是演员搜索或类型搜索,它们将有许多不同的实例。对于演员、流派、评级、年份、子流派和配角,它应该输出找到的每一个实例。(例如,如果 Kevin Bacon 在 x-men 和 notebook 中,它应该输出两者而不仅仅是其中一个(输出文件而不是屏幕))。

我发现自己完全被我们给予的这些限制所困扰。我的搜索功能将如何处理不同的数据类型?(年份和等级必须声明为整数)。它怎么会知道我到底在寻找什么?如果我正在搜索演员,我不希望它也搜索标题。

任何关于如何开始和开始的建议都非常感谢。

编辑:大家好,我想更新你们我所做的事情。我有 3 种不同的搜索功能。一个用于数值(年份和评级),1 用于类型和演员,最后一个用于标题。

这是所有三个的代码。首先是标题搜索。

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. 在任何给定函数中只有一个 return (但是,id 假设这将是一个组合时的 void 函数)

我相信我的主要问题是我的整数和字符串。我不允许将等级或年份声明为字符串。只是将这三者结合起来的代码格式让我很头疼

4

3 回答 3

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封装您要测试的字段的类型(使用不同方法的示例:布尔值来确定可选性):

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 模式::matches(电影成本& m) const { return (!check_year || m.year == year) &&(!check_actor || m.actor == actor); } void print_matching( node* list, pattern const & p ) { // 遍历列表:while (...) { if ( p.matches( list->data ) ) { // 电影匹配,打印 } } }

于 2012-04-20T20:36:13.240 回答
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);
}

这是函数式编程思想中的一种技术——将函数传递给函数(将函数视为“一等公民”)。

于 2012-04-20T19:55:16.270 回答
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是来自 的 C++11 函数<functional>;您可以等效地使用boost::bindor 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));
于 2012-04-20T19:57:28.210 回答