c++ 导航节点"Maze"神秘错误

c++ Navigating a "Maze" of Nodes mysterious error

本文关键字:错误 Maze 节点 c++ 导航      更新时间:2023-10-16

我有一个问题似乎无法解决。下面是我的所有代码,详细介绍了System和Node这两个类。我正在创建的是一个程序,它读取一个文件,创建一个节点的"迷宫"(地图室),然后从指定的开始节点导航到指定的结束节点。

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <array>
#include <map>
#include <stack>
#include <queue>
using namespace std;
class Node
{
   public:
      Node(string newName);
      Node();
      void setNodeName(string newName);
      string getNodeName();
      void attachNewNode(Node *newNode, int direction);
      Node *getAttachedNode(int direction);
      bool visited;
   private:
      string name;
      Node *attachedNodes[4];
};
Node::Node(string newName)
{
   name = newName;
   visited = false;
}
Node::Node()
{
   visited = false;
}
void Node::setNodeName(string newName)
{
   name = newName;
}
string Node::getNodeName()
{
   return name;
}
void Node::attachNewNode(Node *newNode, int direction)
{
   attachedNodes[direction] = newNode;
}
Node* Node::getAttachedNode(int direction)
{
   return attachedNodes[direction];
}

节点文件格式如下所示:

9
A1
C3
A1 A2 B1 * *
A2 * B2 A1 *
A3 * B3 * *
B1 * * * A1
B2 B3 C2 * A2
B3 * * B2 A3
C1 C2 * * *
C2 C3 * C1 B2
C3 * * C2 *

其中,9是要创建的节点数,A1是我们将开始导航的节点,C3是我们将尝试找到路径的节点,下面的行表示节点本身及其关联的指针。例如:

A1 A2 B1 * *

表示节点A1具有指向北方节点A2、东方节点B1、南方节点null和西方节点null的指针。

A2 * B2 A1 *

表示节点A2具有指向北方节点null、东方节点B2、南方节点A1和西方节点null的指针。

我使用的标题为"maze1.txt"的迷宫文件如下:

48 
A1 
H6 
A1 A2 B1 * * 
B1 B2 * * A1 
C1 C2 * * * 
D1 D2 E1 * * 
E1 * * * D1 
F1 F2 * * * 
G1 G2 H1 * * 
H1 * * * G1 
A2 A3 * A1 * 
B2 * C2 B1 * 
C2 * D2 C1 B2 
D2 D3 * D1 C2 
E2 E3 * * * 
F2 F3 G2 F1 * 
G2 * H2 G1 F2 
H2 H3 * * G2 
A3 * B3 A2 * 
B3 B4 * * A3 
C3 C4 D3 * * 
D3 * E3 D2 C3 
E3 * * E2 D3 
F3 F4 * F2 * 
G3 G4 * * * 
H3 H4 * H2 * 
A4 A5 B4 * * 
B4 B5 * B3 A4 
C4 * D4 C3 * 
D4 * E4 * C4 
E4 E5 F4 * D4 
F4 * G4 F3 E4 
G4 * * G3 F4 
H4 H5 * H3 * 
A5 A6 * A4 * 
B5 * C5 B4 * 
C5 C6 D5 * B5 
D5 * * * C5 
E5 E6 F5 E4 * 
F5 * * * E5 
G5 G6 H5 * * 
H5 * * H4 G5 
A6 * B6 A5 * 
B6 * * * A6 
C6 * * C5 * 
D6 * E6 * * 
E6 * F6 E5 D6 
F6 * * * E6 
G6 * H6 G5 * 
H6 * * * G6 

截至昨天,buildGraph()的代码工作正常,并正确地为我提供了节点和它们各自的字符串键的映射室。

class System
{
   public:
      System();
      void displayWelcome();
      void displayExit();
      void buildGraph(string filename);
      string getFileName();
      string getPath();
      map<string,Node> rooms;
      void printMap(map<string,Node> nodes);
      bool canMove(string currentNode);
      string move(string currentNode);
      Node startNode;
      Node endNode;
      Node empt;
   private:
      int numNodes;
};
System::System()
{
    empt.setNodeName("null");
}
void System::displayWelcome()
{
   cout << endl;
   cout << "========================================================" << endl;
   cout << "|      Welcome to the Automatic Maze Path Finder!      |" << endl;
   cout << "========================================================" << endl;
   cout << endl;
}
void System::displayExit()
{
   cout << "========================================================" << endl;
   cout << "|  Thank you for using the Automatic Maze Path Finder! |" << endl;
   cout << "========================================================" << endl;
   cout << endl;
}
void System::buildGraph(string filename)
{
   ifstream instream;
   instream.open(filename.c_str());
   string line;
   string data;
   int numLines = 1;
   int skipBlanks = 1;
   int numNodes;
   while(getline(instream, line))
   {
      if(line.empty() || line.length() < 2)
      {}
      else
      {
         istringstream iss(line);
         if(numLines == 1)
         {
            istringstream buffer(line);
            buffer >> numNodes;
            skipBlanks++;
         }
         if(numLines == 2)
         {
            startNode.setNodeName(line);
            skipBlanks++;
            //cout << "start node is: " << startNode.getNodeName() << endl;
         }
         if(numLines == 3)
         {
            endNode.setNodeName(line);
            skipBlanks++;
            //cout << "end node is: " << endNode.getNodeName() << endl;
         }
         if(numLines > 3 && skipBlanks > 3)
         {
            Node temp;
            string nodeName = line.substr(0,2);
            //cout << "Line number: " << numLines << "  nodeName: " << nodeName << endl;
            rooms[nodeName] = temp;
            rooms[nodeName].setNodeName(nodeName);
         }
         numLines++;
         iss.clear();
      }
   }   
   ifstream nextstream;
   nextstream.open(filename.c_str());
   numLines = 1;
   skipBlanks = 1;
   cout << endl;
   while(getline(nextstream, line))
   {
      if(line.empty() || line.length() < 2)
      {}
      else
      {
         istringstream iss(line);
         if(numLines == 1)
            skipBlanks++;
         if(numLines == 2)
            skipBlanks++;
         if(numLines == 3)
            skipBlanks++;
         if(numLines > 3 && skipBlanks > 3)
         {
            string thisNode = line.substr(0,2);
            int first = line.find(" ", 0);
            int second = line.find(" ", first + 1);
            int third = line.find(" ", second + 1);
            int fourth = line.find(" ", third + 1);
            string firstNode = line.substr(first+1,2);
            string secondNode = line.substr(second+1,2);
            string thirdNode = line.substr(third+1,2);
            string fourthNode = line.substr(fourth+1,2);
            cout << "Line contains: " << line << endl;
            cout << "Current Node: " << thisNode << endl;
            cout << "firstNode:  -" << firstNode << endl;
            cout << "secondNode: -" << secondNode << endl;
            cout << "thirdNode:  -" << thirdNode << endl;
            cout << "fourthNode: -" << fourthNode << endl << endl;
            for(map<string,Node>::iterator thing = rooms.begin(); thing != rooms.end(); thing++)
            {
               if(thing->second.getNodeName() == rooms[thisNode].getNodeName())
               {
                  if(firstNode != "* " && firstNode != " *" && firstNode != "*")
                     thing->second.attachNewNode(&rooms[firstNode],1);
                  else
                  {
                     thing->second.attachNewNode(&empt,1);
                  }
                  if(secondNode != "* " && secondNode != " *" && secondNode != "*")
                     thing->second.attachNewNode(&rooms[secondNode],2);
                  else
                  {
                     thing->second.attachNewNode(&empt,2);
                  }
                  if(thirdNode != "* " && thirdNode != " *" && thirdNode != "*")
                     thing->second.attachNewNode(&rooms[thirdNode],3);
                  else
                  {
                     thing->second.attachNewNode(&empt,3);
                  }
                  if(fourthNode != "* " && fourthNode != " *" && fourthNode != "*")
                     thing->second.attachNewNode(&rooms[fourthNode],4);
                  else
                  {
                     thing->second.attachNewNode(&empt,4);
                  }
               }
            }
         }
         numLines++;
         iss.clear();
      }
   }
   cout << "Exiting buildGraph()" << endl << endl;
}
string System::getFileName()
{
   string filename;
   cout << "Enter the name of the Maze configuration file: ";
   cin >> filename;
   cout << endl;
   return filename + ".txt";
}
string System::getPath()
{
   string path;
   stack<string> pathNodes;
   string currentNode = startNode.getNodeName();
   cout << "added startNode" << endl;
   pathNodes.push(startNode.getNodeName());
   while(currentNode != endNode.getNodeName())
   {
      if(canMove(currentNode))
      {
         currentNode = move(currentNode);
         pathNodes.push(rooms[currentNode].getNodeName());
      }
      else
      {
         while(!canMove(currentNode))
         {
            pathNodes.pop();
            currentNode = pathNodes.top();
         }
      }
   }
   for(int i = 0; i < pathNodes.size(); i++)
   {
      path += pathNodes.top() + " ";
      pathNodes.pop();
   }
   return path;
}
void System::printMap(map<string,Node> nodes)
{
   cout << endl << "The nodes in the current map are:" << endl;
   for(map<string,Node>::iterator it = nodes.begin(); it != nodes.end(); it++)
   {
      cout << "current node: " << it->second.getNodeName() << endl;
      if(it->second.getAttachedNode(1)->getNodeName().length() < 3)
         cout << it->second.getAttachedNode(1)->getNodeName() << endl;
      if(it->second.getAttachedNode(2)->getNodeName().length() < 3)
         cout << it->second.getAttachedNode(2)->getNodeName() << endl;
      if(it->second.getAttachedNode(3)->getNodeName().length() < 3)
         cout << it->second.getAttachedNode(3)->getNodeName() << endl;
      if(it->second.getAttachedNode(4)->getNodeName().length() <  3)
         cout << it->second.getAttachedNode(4)->getNodeName() << endl;
   }
   cout << endl;
   cout << "Exited for in printMap." << endl << endl;
}
bool System::canMove(string currentNode)
{
   if(!rooms[currentNode].getAttachedNode(1)->visited ||
      !rooms[currentNode].getAttachedNode(2)->visited ||
      !rooms[currentNode].getAttachedNode(3)->visited ||
      !rooms[currentNode].getAttachedNode(4)->visited)
         return true;
   return false;
}
string System::move(string currentNode)
{
   string newSpot;
   if(!rooms[currentNode].getAttachedNode(1)->visited)
      newSpot = rooms[currentNode].getAttachedNode(1)->getNodeName();
   if(!rooms[currentNode].getAttachedNode(2)->visited)
      newSpot = rooms[currentNode].getAttachedNode(2)->getNodeName();
   if(!rooms[currentNode].getAttachedNode(3)->visited)
      newSpot = rooms[currentNode].getAttachedNode(3)->getNodeName();
   if(!rooms[currentNode].getAttachedNode(4)->visited)
      newSpot = rooms[currentNode].getAttachedNode(4)->getNodeName();
   return newSpot;
}

然而,今天在编译和执行主要:

main ()
{
   System system;
   system.displayWelcome();
   string file;
   while(1)
   {
      file = system.getFileName();
      if(file == "Quit.txt" || file == "quit.txt")
         break;

      system.buildGraph(file);
      cout << "Made it through buildGraph()" << endl;

      system.printMap(system.rooms);
      string path = system.getPath();
      cout << "The Start Node is: " << system.startNode.getNodeName() << endl;
      cout << "The Destination Node is: " << system.endNode.getNodeName() << endl;
      cout << "Finding a path from the Start to the Destination node ... " << endl;
      if(path.length() > 1)
      {
         cout << "Congratulations: Found path successfully." << endl;
         cout << "The path is: " << path << endl;
      }
      else
         cout << "Unsuccessful: No path can be found." << endl;
   }
   system.displayExit();
}

我收到以下输出。

========================================================
|      Welcome to the Automatic Maze Path Finder!      |
========================================================
Enter the name of the Maze configuration file: maze1

Line contains: A1 A2 B1 * * 
Current Node: A1
firstNode:  -A2
secondNode: -B1
thirdNode:  -* 
fourthNode: -* 
Line contains: B1 B2 * * A1 
Current Node: B1
firstNode:  -B2
secondNode: -* 
thirdNode:  -* 
fourthNode: -A1
Line contains: C1 C2 * * * 
Current Node: C1
firstNode:  -C2
secondNode: -* 
thirdNode:  -* 
fourthNode: -* 
Line contains: D1 D2 E1 * * 
Current Node: D1
firstNode:  -D2
secondNode: -E1
thirdNode:  -* 
fourthNode: -* 
Line contains: E1 * * * D1 
Current Node: E1
firstNode:  -* 
secondNode: -* 
thirdNode:  -* 
fourthNode: -D1
Line contains: F1 F2 * * * 
Current Node: F1
firstNode:  -F2
secondNode: -* 
thirdNode:  -* 
fourthNode: -* 
Line contains: G1 G2 H1 * * 
Current Node: G1
firstNode:  -G2
secondNode: -H1
thirdNode:  -* 
fourthNode: -* 
Line contains: H1 * * * G1 
Current Node: H1
firstNode:  -* 
secondNode: -* 
thirdNode:  -* 
fourthNode: -G1
Line contains: A2 A3 * A1 * 
Current Node: A2
firstNode:  -A3
secondNode: -* 
thirdNode:  -A1
fourthNode: -* 
Line contains: B2 * C2 B1 * 
Current Node: B2
firstNode:  -* 
secondNode: -C2
thirdNode:  -B1
fourthNode: -* 
Line contains: C2 * D2 C1 B2 
Current Node: C2
firstNode:  -* 
secondNode: -D2
thirdNode:  -C1
fourthNode: -B2
Line contains: D2 D3 * D1 C2 
Current Node: D2
firstNode:  -D3
secondNode: -* 
thirdNode:  -D1
fourthNode: -C2
Line contains: E2 E3 * * * 
Current Node: E2
firstNode:  -E3
secondNode: -* 
thirdNode:  -* 
fourthNode: -* 
Line contains: F2 F3 G2 F1 * 
Current Node: F2
firstNode:  -F3
secondNode: -G2
thirdNode:  -F1
fourthNode: -* 
Line contains: G2 * H2 G1 F2 
Current Node: G2
firstNode:  -* 
secondNode: -H2
thirdNode:  -G1
fourthNode: -F2
Line contains: H2 H3 * * G2 
Current Node: H2
firstNode:  -H3
secondNode: -* 
thirdNode:  -* 
fourthNode: -G2
Line contains: A3 * B3 A2 * 
Current Node: A3
firstNode:  -* 
secondNode: -B3
thirdNode:  -A2
fourthNode: -* 
Line contains: B3 B4 * * A3 
Current Node: B3
firstNode:  -B4
secondNode: -* 
thirdNode:  -* 
fourthNode: -A3
Line contains: C3 C4 D3 * * 
Current Node: C3
firstNode:  -C4
secondNode: -D3
thirdNode:  -* 
fourthNode: -* 
Line contains: D3 * E3 D2 C3 
Current Node: D3
firstNode:  -* 
secondNode: -E3
thirdNode:  -D2
fourthNode: -C3
Line contains: E3 * * E2 D3 
Current Node: E3
firstNode:  -* 
secondNode: -* 
thirdNode:  -E2
fourthNode: -D3
Line contains: F3 F4 * F2 * 
Current Node: F3
firstNode:  -F4
secondNode: -* 
thirdNode:  -F2
fourthNode: -* 
Line contains: G3 G4 * * * 
Current Node: G3
firstNode:  -G4
secondNode: -* 
thirdNode:  -* 
fourthNode: -* 
Line contains: H3 H4 * H2 * 
Current Node: H3
firstNode:  -H4
secondNode: -* 
thirdNode:  -H2
fourthNode: -* 
Line contains: A4 A5 B4 * * 
Current Node: A4
firstNode:  -A5
secondNode: -B4
thirdNode:  -* 
fourthNode: -* 
Line contains: B4 B5 * B3 A4 
Current Node: B4
firstNode:  -B5
secondNode: -* 
thirdNode:  -B3
fourthNode: -A4
Line contains: C4 * D4 C3 * 
Current Node: C4
firstNode:  -* 
secondNode: -D4
thirdNode:  -C3
fourthNode: -* 
Line contains: D4 * E4 * C4 
Current Node: D4
firstNode:  -* 
secondNode: -E4
thirdNode:  -* 
fourthNode: -C4
Line contains: E4 E5 F4 * D4 
Current Node: E4
firstNode:  -E5
secondNode: -F4
thirdNode:  -* 
fourthNode: -D4
Line contains: F4 * G4 F3 E4 
Current Node: F4
firstNode:  -* 
secondNode: -G4
thirdNode:  -F3
fourthNode: -E4
Line contains: G4 * * G3 F4 
Current Node: G4
firstNode:  -* 
secondNode: -* 
thirdNode:  -G3
fourthNode: -F4
Line contains: H4 H5 * H3 * 
Current Node: H4
firstNode:  -H5
secondNode: -* 
thirdNode:  -H3
fourthNode: -* 
Line contains: A5 A6 * A4 * 
Current Node: A5
firstNode:  -A6
secondNode: -* 
thirdNode:  -A4
fourthNode: -* 
Line contains: B5 * C5 B4 * 
Current Node: B5
firstNode:  -* 
secondNode: -C5
thirdNode:  -B4
fourthNode: -* 
Line contains: C5 C6 D5 * B5 
Current Node: C5
firstNode:  -C6
secondNode: -D5
thirdNode:  -* 
fourthNode: -B5
Line contains: D5 * * * C5 
Current Node: D5
firstNode:  -* 
secondNode: -* 
thirdNode:  -* 
fourthNode: -C5
Line contains: E5 E6 F5 E4 * 
Current Node: E5
firstNode:  -E6
secondNode: -F5
thirdNode:  -E4
fourthNode: -* 
Line contains: F5 * * * E5 
Current Node: F5
firstNode:  -* 
secondNode: -* 
thirdNode:  -* 
fourthNode: -E5
Line contains: G5 G6 H5 * * 
Current Node: G5
firstNode:  -G6
secondNode: -H5
thirdNode:  -* 
fourthNode: -* 
Line contains: H5 * * H4 G5 
Current Node: H5
firstNode:  -* 
secondNode: -* 
thirdNode:  -H4
fourthNode: -G5
Line contains: A6 * B6 A5 * 
Current Node: A6
firstNode:  -* 
secondNode: -B6
thirdNode:  -A5
fourthNode: -* 
Line contains: B6 * * * A6 
Current Node: B6
firstNode:  -* 
secondNode: -* 
thirdNode:  -* 
fourthNode: -A6
Line contains: C6 * * C5 * 
Current Node: C6
firstNode:  -* 
secondNode: -* 
thirdNode:  -C5
fourthNode: -* 
Line contains: D6 * E6 * * 
Current Node: D6
firstNode:  -* 
secondNode: -E6
thirdNode:  -* 
fourthNode: -* 
Line contains: E6 * F6 E5 D6 
Current Node: E6
firstNode:  -* 
secondNode: -F6
thirdNode:  -E5
fourthNode: -D6
Line contains: F6 * * * E6 
Current Node: F6
firstNode:  -* 
secondNode: -* 
thirdNode:  -* 
fourthNode: -E6
Line contains: G6 * H6 G5 * 
Current Node: G6
firstNode:  -* 
secondNode: -H6
thirdNode:  -G5
fourthNode: -* 
Line contains: H6 * * * G6 
Current Node: H6
firstNode:  -* 
secondNode: -* 
thirdNode:  -* 
fourthNode: -G6
Exiting buildGraph()
*** Error in `./lab03.out': free(): invalid size: 0x000000000106ca80 ***
Aborted (core dumped)

最后两行之前的所有内容都如预期,您可以看到这些行似乎被正确读取和处理。请注意,buildGraph()函数末尾的print语句成功打印,但main()中紧接着的下一个print语句没有打印。是什么原因导致了这个问题?我该如何着手解决这个问题?谢谢

您不能这样做:

{
    Node empt;
    empt.setNodeName("null");
    thing->second.attachNewNode(&empt,1);
}

empt是一个局部变量,它在块结束后被销毁,所以您有悬空指针。一种可能的解决方案是将未命名节点的容器保留在功能中的某个位置(具有适当的生存期)并添加它们:

{
    unnamedNodes.emplace_back( "null" );
    thing.second.attachNeNode( &unnamedNodes.back(), 1 );
}

并定义:

std::list<Node> unnamedNodes;

在你的课堂上。您可以使用std::vector,但必须确保不会发生重新分配(提前预留足够的大小)