Ошибка сегментации бинарного дерева поиска

#c #binary-search-tree

#c #binary-search-tree

Вопрос:

Я создаю бинарное дерево поиска для бизнеса по прокату фильмов (теоретически). Мне нужно вывести «Фильм не найден», если введено название, которого нет в прокате фильмов. Я не уверен, как это сделать, не получая ошибку сегментации каждый раз. Я не уверен, что еще попробовать — для меня этот код имеет смысл. Я только новичок — пожалуйста, будьте проще со мной. Любая помощь будет принята с благодарностью! (Вы можете найти мою функцию if, которая пытается вывести «Фильм не найден» между тремя косыми чертами (///) ближе к концу моего кода.

 void MovieTree::rentMovie(std::string title)
{ 
     MovieNode *foundMovie = root; 
     //MovieNode *parent = NULL; 
if (root == NULL) 
{ 
    cout << "Movie not found." << endl;
    return; 
}
else 
{ 
    foundMovie = root; 
    while (foundMovie != NULL) 
    { 
        if (foundMovie == NULL) //tree is empty 
        { 
            cout << "Movie not found." << endl; 
        } 

        else 
        { 
            if (foundMovie->title.compare(title) > 0) //uses ASCII to determine where titles are 
            { 
                foundMovie->parent = foundMovie; 
                foundMovie = foundMovie ->leftChild; 
                //cout << "printed left" << endl; //debugging
                if (foundMovie->title.compare(title) == 0 amp;amp; foundMovie->quantity > 0) 
                { 
                    foundMovie->quantity--;
                    cout << "Movie has been rented." << endl;
                    //Title entered matches title found 
                    cout << "Movie Info:" << endl;
                    cout << "===========" << endl; 
                    cout << "Ranking:" << foundMovie->ranking << endl; 
                    cout << "Title:" << foundMovie->title << endl; 
                    cout << "Year:" << foundMovie->year << endl; 
                    cout << "Quantity:" << foundMovie->quantity << endl;
                    break;
                }

                else if (foundMovie->quantity ==0)
                {
                    //If movie is out of stock 
                    cout << "Movie out of stock." << endl; 
                    break;
                }
            } 
            else //check rightChild 
            { 
                foundMovie->parent = foundMovie; 
                foundMovie = foundMovie->rightChild; 
                //cout << "printed right" << endl; //debugging
                if (foundMovie->title.compare(title) == 0 amp;amp; foundMovie->quantity > 0) //title entered matches title found 
                { 
                    foundMovie->quantity--;
                    cout << "Movie has been rented." << endl;
                    cout << "Movie Info:" << endl;
                    cout << "===========" << endl; 
                    cout << "Ranking:" << foundMovie->ranking << endl; 
                    cout << "Title:" << foundMovie->title << endl; 
                    cout << "Year:" << foundMovie->year << endl; 
                    cout << "Quantity:" << foundMovie->quantity << endl;
                    break;
                }
                else if (foundMovie->quantity ==0) 
                { 
                    //movie is found but out of stock 
                    cout << "Movie out of stock." << endl;
                    break; 
                } 
            }
        }
    }
    ///
    if (foundMovie->title == title) 
    {
        cout << "found the movie" << endl; 
    } 
    else 
    { 
        cout << "Movie not found." << endl; 
    }
    ///
}
  

}

Комментарии:

1. ericlippert.com/2014/03/05/how-to-debug-small-programs

2. foundMovie->parent = foundMovie; это не очень хорошая идея; это создает циклическую зависимость.

3. Еще одна рекомендация: отделите логику фильма от логики дерева. Это позволяет вам отдельно протестировать дерево и фильм и легко определить, в чем ошибка. Одновременное тестирование обоих ставит вас в неприятное положение, когда вы можете фактически исправить ошибку в одном и не осознавать этого из-за ошибки в другом.

4. Поскольку вы указали, что вы новичок, вот пошаговый рефакторинг вашего кода: pastebin.com/4tP5VzKK

Ответ №1:

Некоторые замечания / ошибки в вашем коде

  • Вы не можете удалить больше полезных условий: это снижает читаемость вашего кода.

     while (foundMovie != NULL) 
    { 
        if (foundMovie == NULL) // false by construction!!!
        ...
    }
      
  • foundMovie->parent = foundMovie; должно исчезнуть. Это создает циклическую зависимость!

  • Ваш последний оператор if (foundMovie->title == title) может создать ошибку сегментации, поскольку foundMovie в этот момент может быть NULL.

Вот возможное переписывание:

 void MovieTree::rentMovie(std::string title)
{ 
   MovieNode *foundMovie = root; 
   if (root == NULL) 
   { 
       cout << "Movie not found." << endl;
       return; 
   }

   foundMovie = root; 
   while (foundMovie != NULL) 
   { 
       int compareTitle = foundMovie->title.compare(title); //uses ASCII to determine where titles are 
       if (compareTitle > 0)
       { 
           foundMovie = foundMovie ->leftChild; 
       } 
       else if (compareTitle < 0) //check rightChild 
       { 
           foundMovie = foundMovie->rightChild; 
       }
       else { // compareTitle == 0
           if (foundMovie->quantity > 0) 
           { 
               foundMovie->quantity--;
               cout << "Movie has been rented." << endl;
               //Title entered matches title found 
               cout << "Movie Info:" << endl;
               cout << "===========" << endl; 
               cout << "Ranking:" << foundMovie->ranking << endl; 
               cout << "Title:" << foundMovie->title << endl; 
               cout << "Year:" << foundMovie->year << endl; 
               cout << "Quantity:" << foundMovie->quantity << endl;
               break;
           }
           else if (foundMovie->quantity ==0)
           {
               //If movie is out of stock 
               cout << "Movie out of stock." << endl; 
               break;
           }
        }
    }

    // be sure that foundMovie->title == title is equivalent to foundMovie->title.compare(title) == 0
    if (foundMovie amp;amp; foundMovie->title == title) 
    {
        cout << "found the movie" << endl; 
    } 
    else 
    { 
        cout << "Movie not found." << endl; 
    }
 }
  

Комментарии:

1. Большое вам спасибо. Я не был уверен, как еще это сделать — я ценю ваше мнение.