我在这里滥用了指针吗?虽然循环条件似乎无法正常工作

Am I misusing a pointer here? While loop conditions don't seem to be working properly

本文关键字:常工作 工作 条件 循环 在这里 指针      更新时间:2023-10-16

我正在做一个任务,要求我存储一个链表,其中包含保存任何对象类型数据的节点。目前,我正在构建对象类型设置为 Employee 的类(我将在下面发布)以简化该过程。在我完成所有函数后,我会将其转换为模板。

我的问题是我有一个"合并"函数,它接受两个排序列表,然后将它们合并到调用对象列表中(仍然排序)。我设置了调试语句"第一"第二"第三"和"第四",只是为了查看正在输入哪些循环,并且cmd提示符进入打印"第四"的无限循环。就好像两个列表最终都没有 = NULL 的节点,就好像它们永远不会跑完一样......这很令人困惑。这是有问题的函数:

//----------------------------------------------------------------------------
// merge
// merges two sorted lists into one sorted list
void List::merge(List* LA, List* LB)
{
   Node* mergedPtr = NULL; //pointer for merged list
   Node* laPtr = LA->head; //pointer for List A
   Node* lbPtr = LB->head; //pointer for List B
   makeEmpty();
   while(laPtr != NULL && lbPtr != NULL)
   {
      if(*laPtr->data <= *lbPtr->data)
      {
         if(head == NULL) //special base case
         {
            head = laPtr;
            mergedPtr = head;
            cout << "first";
         }
         else
         {
            mergedPtr->next = laPtr;
            mergedPtr = mergedPtr->next;
            cout << "second";
         }
         laPtr = laPtr->next; //advance pointer for List A
      }
      else if(*laPtr->data > *lbPtr->data)
      {
         if(head == NULL) //special base case
         {
            head = lbPtr;
            mergedPtr = head;
            cout << "third";
         }
         else
         {
            mergedPtr->next = lbPtr;
            mergedPtr = mergedPtr->next;f
            cout << "fourth";
         }
         lbPtr = lbPtr->next; //advance pointer for List B
      }
      mergedPtr = mergedPtr->next; //advance pointer for merged list
   }
   /*if(laPtr != NULL)
   {
      while(laPtr != NULL)
      {
         mergedPtr->next = laPtr;
         laPtr = laPtr->next;
      }
   }
   else if(lbPtr != NULL)
   {
      while(lbPtr != NULL)
      {
         mergedPtr->next = lbPtr;
         lbPtr = lbPtr->next;
      }
   }*/
}

我已经重写了几次并尝试了不同的方法来解决问题,但它似乎总是有同样的问题。似乎表明其中一个列表是无限的,但在我的测试类中(我将在下面发布)一个列表有两个项目,另一个有 4 个......它从中读取的 infile 只有 4 个条目:

鸭唐纳德 2 35000鸭达菲4 12000鼠标米奇 1 100000高飞 7 250

在测试类中,我添加一个条目,然后将其删除。然后我使用不同的列表来测试我的makeEmpty()函数。然后是另一个用于合并但没有结果的列表,因为它在合并函数中的无限循环中捕获。如有必要,下面是测试类:

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////  listdriver.cpp  //////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Driver for simple linked list
#include "list.h"
// to compile under unix/linux:  g++ nodedata.cpp list.cpp listdriver.cpp
int main() {
   Employee* ptr; 
   List mylist;
   // create file object and open the datafile
   ifstream infile("listdata.txt");
   if (!infile) {
      cout << "File could not be opened." << endl;
      return 1;
   }
   // build list from data file 
   mylist.buildList(infile);                 
   cout << "Original list: " << endl << mylist << endl;
   // insert another node where data is pre-determined
   ptr = new Employee("Lee","Law");
   mylist.insert(ptr); 
   cout << " List after insert: " << endl << mylist << endl;
   Employee* temp;
   List testEmpty;
   temp = new Employee("Zebra", "Zee");
   testEmpty.insert(temp);
   temp = new Employee("Jackson", "Jack");
   testEmpty.insert(temp);
   cout << endl << " testEmpty after inserting 2 new employees: " << endl << testEmpty << endl;
   List mergeTest;
   cout << "testtesttest" << endl;
   mergeTest.merge(&testEmpty, &mylist);
   cout << endl << " mergeTest after calling merge(testEmpty, mylist): " << endl << mergeTest << endl;
}

这是员工对象,尽管我认为它与问题无关:

#include "employee.h"
// incomplete class and not fully documented
//--------------------------  constructor  -----------------------------------
Employee::Employee(string last, string first, int id, int sal) {
   idNumber = (id >= 0 && id <= MAXID? id : -1);
   salary = (sal >= 0 ? sal : -1);
   lastName = last;
   firstName = first;
}   
//--------------------------  destructor  ------------------------------------
// Needed so that memory for strings is properly deallocated
Employee::~Employee() { }
//---------------------- copy constructor  -----------------------------------
   Employee::Employee(const Employee& E) {
      lastName = E.lastName;
      firstName = E.firstName;
      idNumber = E.idNumber;
      salary = E.salary;
   }
//-------------------------- operator= ---------------------------------------
   Employee& Employee::operator=(const Employee& E) {
      if (&E != this) {
         idNumber = E.idNumber;
         salary = E.salary;
         lastName = E.lastName;
         firstName = E.firstName;
      }
      return *this;
   }
//-----------------------------  setData  ------------------------------------
// set data from file
bool Employee::setData(ifstream& inFile) {
   inFile >> lastName >> firstName >> idNumber >> salary;
   return idNumber  >= 0 && idNumber <= MAXID && salary >= 0; 
}
//-------------------------------  <  ----------------------------------------
// < defined by value of name
bool Employee::operator<(const Employee& E) const { 
   return lastName < E.lastName ||
          (lastName == E.lastName && firstName < E.firstName);
}

//-------------------------------  <= ----------------------------------------
// < defined by value of inamedNumber
bool Employee::operator<=(const Employee& E) const { 
   return *this < E || *this == E;
}
//-------------------------------  >  ----------------------------------------
// > defined by value of name
bool Employee::operator>(const Employee& E) const { 
   return lastName > E.lastName ||
          (lastName == E.lastName && firstName > E.firstName);
}
//-------------------------------  >= ----------------------------------------
// < defined by value of name
bool Employee::operator>=(const Employee& E) const { 
   return *this > E || *this == E;
}
//----------------- operator == (equality) ----------------
// if name of calling and passed object are equal,
//   return true, otherwise false
//
bool Employee::operator==(const Employee& E) const {
   return lastName == E.lastName && firstName == E.firstName;
}
//----------------- operator != (inequality) ----------------
// return opposite value of operator==
bool Employee::operator!=(const Employee& E) const {
   return !(*this == E);
}
//-------------------------------  <<  ---------------------------------------
// display Employee object
ostream& operator<<(ostream& output, const Employee& E) { 
   output << setw(4) << E.idNumber << setw(7) << E.salary << "  " 
          << E.lastName << " " << E.firstName << endl; 
   return output;
}

如果有人指出问题不在于合并,而在于其他地方,我不会太惊讶......这就是为什么我在下面发布其余的类代码(我希望会被要求)。问题是,虽然我没有看到与类中任何其他函数的任何联系。我使用的测试驱动程序插入和删除,但它的节点位于列表的中心,因此它不会搞砸最后存在的任何指向 NULL 的指针......下面列出了两个版本的合并函数。下面的一个被注释掉了,但不确定它在这个线程上的可见度。任何提示将不胜感激。我遇到了障碍:l

////////////////////////////////  list.cpp file  /////////////////////////////
#include "list.h"
//----------------------------------------------------------------------------
// Constructor 
List::List()
{
   head = NULL;
}
//----------------------------------------------------------------------------
// Copy Constructor 
/*List::List(const List &other)
{
}*/
//----------------------------------------------------------------------------
// Destructor 
// Can just call makeEmpty()
List::~List()
{
   makeEmpty();
}
//----------------------------------------------------------------------------
// retrieve
// retrieves an object from the list
bool List::retrieve(Employee* target, Employee* other)
{
   if (isEmpty())
   {
      other = NULL;
      return false;
   }
   else
   {
      Node* ptr = head;
      while(ptr != NULL && ptr->data != target)
      {
         ptr = ptr->next;
      }
      if(ptr == NULL)
      {
         return false;
      }
      other = ptr->data;
      return true;
   }
}
//----------------------------------------------------------------------------
// remove
// remove an object from the list
bool List::remove(Employee* target, Employee* other) 
{
   if (isEmpty()) 
   {
      other = NULL;
      return false;
   }
   else
   {
      Node* ptr = head;
      Node* lastPtr = NULL;
      while(ptr != NULL && ptr->data != target) 
      {
         lastPtr = ptr;
         ptr = ptr->next;
      }
      if(ptr == NULL) 
      {
         return false;
      }
      other = ptr->data;
      lastPtr->next = ptr->next; // skips over target for list pointers
      delete ptr; //deletes now obsolete node from the list and memory
      return true;
   }
}

//----------------------------------------------------------------------------
// isEmpty 
// check to see if List is empty
bool List::isEmpty() const 
{
   return head == NULL;
}
//----------------------------------------------------------------------------
// makeEmpty 
// empty out the list, deallocate all memory for all Nodes and each Object
void List::makeEmpty()
{
   Node* tempPtr;
   while(head != NULL)
   {
      tempPtr = head;
      delete head->data;
      head = tempPtr->next;
      delete tempPtr;
   }   
}
//----------------------------------------------------------------------------
// insert 
// insert an item into list; operator< of the NodeData class
// has the responsibility for the sorting criteria
bool List::insert(Employee* dataptr) 
{                    
   Node* ptr = new Node;
   if (ptr == NULL) return false;                 // out of memory, bail
   ptr->data = dataptr;                           // link the node to data
   // if the list is empty or if the node should be inserted before 
   // the first node of the list
   if (isEmpty() || *ptr->data < *head->data) 
   {
      ptr->next = head;                           
      head = ptr;
   }
   // then check the rest of the list until we find where it belongs 
   else {
      Node* current = head->next;          // to walk list
      Node* previous = head;               // to walk list, lags behind
      // walk until end of the list or found position to insert
      while (current != NULL && *current->data < *ptr->data) 
      {
            previous = current;                  // walk to next node
            current = current->next;
      }
      // insert new node, link it in
      ptr->next = current; 
      previous->next = ptr; 
   }
   return true;
}
//----------------------------------------------------------------------------
// merge
// merges two sorted lists into one sorted list
void List::merge(List* LA, List* LB)
{
   Node* mergedPtr = NULL; //pointer for merged list
   Node* laPtr = LA->head; //pointer for List A
   Node* lbPtr = LB->head; //pointer for List B
   makeEmpty();
   while(laPtr != NULL && lbPtr != NULL)
   {
      if(*laPtr->data <= *lbPtr->data)
      {
         if(head == NULL) //special base case
         {
            head = laPtr;
            mergedPtr = head;
            cout << "first";
         }
         else
         {
            mergedPtr->next = laPtr;
            mergedPtr = mergedPtr->next;
            cout << "second";
         }
         laPtr = laPtr->next; //advance pointer for List A
      }
      else if(*laPtr->data > *lbPtr->data)
      {
         if(head == NULL) //special base case
         {
            head = lbPtr;
            mergedPtr = head;
            cout << "third";
         }
         else
         {
            mergedPtr->next = lbPtr;
            mergedPtr = mergedPtr->next;f
            cout << "fourth";
         }
         lbPtr = lbPtr->next; //advance pointer for List B
      }
      mergedPtr = mergedPtr->next; //advance pointer for merged list
   }
   /*if(laPtr != NULL)
   {
      while(laPtr != NULL)
      {
         mergedPtr->next = laPtr;
         laPtr = laPtr->next;
      }
   }
   else if(lbPtr != NULL)
   {
      while(lbPtr != NULL)
      {
         mergedPtr->next = lbPtr;
         lbPtr = lbPtr->next;
      }
   }*/
}

//----------------------------------------------------------------------------
// merge
// merges two sorted lists into one sorted list
/*void List::merge(List LA, List LB)
{
   //merge sort - take first element from each list, compare, higher value goes first; continue until done sorting
   List* Temp = new List(); //define a new list to be merged into
   Node* LAA = LA.head;
   Node* LBB = LB.head;
   //special case: first copied element is set as head
   if(Temp->head == NULL)
   {
      Node* tempNode;
      cout << "code test: first" << endl;
      if(LAA->data <= LBB->data)
      {
         tempNode = LAA;
         Temp->head = tempNode;
         LAA = LAA->next;
      } 
      else
      {
         tempNode = LBB;
         Temp->head = tempNode;
         LBB = LBB->next;
      }
   }
   cout << "code test: second" << endl;
   //rest of lists
   Node* tempPtr;
   while(LAA != NULL && LBB != NULL)
   {
      tempPtr = Temp->head;
      if(LAA->data <= LBB->data)
      {
         tempPtr->next = LAA;
         LAA = LAA->next;
      }
      else
      {
         tempPtr->next = LBB;
         LBB = LBB->next;
      }
   }
   cout << "code test: third" << endl;
   //catches the remainder extra from either list (messy solution)
   if(LAA != NULL)
   {
      while(LAA != NULL)
      {
         tempPtr->next = LAA;
         LAA = LAA->next;
      }
   }
   if(LBB != NULL)
   {
      while(LBB != NULL)
      {
         tempPtr->next = LBB;
         LBB = LBB->next;
      }
   }
   cout << "code test: fourth" << endl;
}*/
//----------------------------------------------------------------------------
// intersect
// takes the common nodes from two lists and sorts them into a new list
void List::intersect(List* LA, List* LB)
{
   List* temp = new List();
   Node* tempPtr = NULL;
   Node* LAPtr = LA->head;
   Node* LBPtr = LB->head;
   while(LAPtr != NULL && LBPtr != NULL)
   {
      while(LAPtr->data < LBPtr->data)
      {
         LAPtr = LAPtr->next;
      }
      while(LAPtr->data > LBPtr->data)
      {
         LBPtr = LBPtr->next;
      }
      //base case when new list is empty
      if(LAPtr->data == LBPtr->data && temp->head == NULL)
      {
         temp->head = LAPtr;
         tempPtr = head;
         LAPtr = LAPtr->next;
         LBPtr =LBPtr->next;
      }
      //create new node copying the common node and add it to the end of the new list
      //advance the list pointers
      if(LAPtr->data == LBPtr->data)
      {
         Node* tempNode = new Node;
         tempNode->data = LAPtr->data;
         tempNode->next = NULL;
         tempPtr->next = tempNode;
         LAPtr = LAPtr->next;
         LBPtr =LBPtr->next;
      }
   }
}
//----------------------------------------------------------------------------
// buildList 
// continually insert new items into the list
void List::buildList(ifstream& infile) 
{
   Employee* ptr;
   bool successfulRead;                            // read good data
   bool success;                                   // successfully insert
   for (;;) 
   {
      ptr = new Employee;
      successfulRead = ptr->setData(infile);       // fill the NodeData object
      if (infile.eof()) 
      {
         delete ptr;
         break;
      }
      // insert good data into the list, otherwise ignore it
      if (successfulRead) 
      {
         success = insert(ptr);
      }
      else 
      {
         delete ptr;
      }
      if (!success) break;
   }
}
//----------------------------------------------------------------------------
// operator<<  
// output operator for class List, print data, 
// responsibility for output is left to object stored in the list
ostream& operator<<(ostream& output, const List& thelist) 
{
   List::Node* current = thelist.head;
   while (current != NULL) 
   { 
      output << *current->data;
      current = current->next;
   }
   return output;                      // enables output << x << y;
}
//----------------------------------------------------------------------------
// operator=  
// sets one list equal to another
List& List::operator=(const List &other)
{
   if(this == &other)
      return *this;
   Node* tempPtr;
   while(head != NULL) //copy of makeEmpty code; empties the list for new data to be entered
   {
      tempPtr = head;
      delete head->data;
      head = tempPtr->next;
      delete tempPtr;
   }
   tempPtr = other.head; //to navigate other list
   head = tempPtr;
   Node* disPtr; //to build this list
   disPtr = head;
   while(tempPtr->next != NULL)
   {
      Node* temp = new Node;
      disPtr->next = temp; //creates a copy of node
      disPtr->next->data = tempPtr->next->data;
      disPtr->next->next = tempPtr->next->next;
      disPtr = disPtr->next;
      tempPtr = tempPtr->next;
   }
   return *this;
}
//----------------------------------------------------------------------------
// operator==
// checks if two lists are the same
bool List::operator==(List* LB)
{
   Node* LAPtr = head;
   Node* LBPtr = LB->head;
   while(LAPtr != NULL && LBPtr != NULL)
   {
      if(LAPtr->data != LBPtr->data)
      {
         return false;
      }
      LAPtr = LAPtr->next;
      LBPtr = LBPtr->next;
      if(LAPtr->data == NULL && LBPtr->data != NULL)
      {
         return false;
      }
      if (LAPtr->data == NULL && LBPtr->data != NULL)
      {
         return false;
      }
   }
   return true;
}
//----------------------------------------------------------------------------
// operator!=
// checks if two lists are not the same
bool List::operator!=(List* LB)
{
   Node* LAPtr = head;
   Node* LBPtr = LB->head;
   while(LAPtr != NULL && LBPtr != NULL)
   {
      if(LAPtr->data == LBPtr->data)
      {
         return false;
      }
      LAPtr = LAPtr->next;
      LBPtr = LBPtr->next;
   }
   return true;
}

你正在打电话

    mergedPtr = mergedPtr->next;

两次。这将导致未定义的行为。此外,您应该使用 nullptr 而不是 NULL。