我一直在做这个家庭作业,我觉得我已经尝试过任何我能做的事,但这真是令人沮丧。基本上这个程序应该模拟监视计算机实验室的人的管理控制台。主菜单有3个选项,除了"注销"以外,我已经完成了所有选项。功能
这个程序的一个大问题是实验室应该是数组,并且位于特定计算机站的ID号应该存储在链表中。我最挣扎的部分是链表。
当我运行程序时,模拟登录,然后尝试注销我的程序崩溃。所以我尝试使用Visual Studio对其进行调试,它告诉我在第121行有一个未处理的异常(在下面的注释位于注销函数中)。我试过多次联系我的老师,但他没有回应。如果有人能指出我正确的方向,那就太好了。
编辑:我注意到删除功能可能会导致问题。虽然它似乎删除了列表中的节点,但是当我查看调试器时,似乎在一个节点中存在一些垃圾数据。我删除节点时应该进行某种初始化吗?就像删除节点时将变量设置为NULL或nullptr一样?
编辑2:我缩短了代码。以下是我得到的例外情况: 抛出未处理的异常:读访问冲突。 iter 是nullptr。
#include <iostream>
using namespace std;
struct User
{
int IDNumber;
int stationNumber;
User *link;
};
typedef User* NodePtr;
const int COMPUTER_LABS = 4;
const int COMPUTERLAB_SIZES[] = { 5, 6, 4, 3 }; number of labs
void head_insert(NodePtr& head, int IDNum, int stationNum)
{
NodePtr temp_ptr;
temp_ptr = new User;
temp_ptr->IDNumber = IDNum;
temp_ptr->stationNumber = stationNum;
temp_ptr->link = head;
head = temp_ptr;
}
void remove(NodePtr& head, int position)
{
if (head == NULL)
return;
NodePtr temp = head;
if (position == 0)
{
head = temp->link;
delete temp;
return;
}
for (int i = 0; temp != NULL && i<position - 1; i++)
temp = temp->link;
if (temp == NULL || temp->link == NULL)
return;
NodePtr next = temp->link->link;
delete temp->link;
temp->link = next;
}
//This function will take in our multidimensional array and prompt the user for data on simulating a login
//At the end, the spot will be assigned a number
void login(NodePtr labs[])
{
int IDNum, labNum, stationNum;
cout << "Enter the 5 digit ID number of the user logging in: " << endl;
cin >> IDNum;
cout << "Enter the lab number the user is logging in from (1-4): " << endl;
cin >> labNum;
cout << "Enter computer station number the user is logging in to (1-6): " << endl;
cin >> stationNum;
if (labs[labNum - 1]->link == NULL && labs[labNum - 1]->stationNumber == NULL)
{
labs[labNum - 1]->stationNumber = stationNum;
labs[labNum - 1]->IDNumber = IDNum;
}
else
head_insert(labs[labNum - 1], IDNum, stationNum);
}
void showLabs(NodePtr labs[])
{
for (int i = 0; i < COMPUTER_LABS; i++)
{
cout << i + 1 << ": ";
for (int j = 0; j<COMPUTERLAB_SIZES[i]; j++)
{
for (NodePtr iter = labs[i]; iter != NULL; iter = iter->link)
{
if (iter->stationNumber == (j + 1))
{
cout << j + 1 << ": " << (iter->IDNumber) << " ";
break;
}
else if ((iter->link) == NULL && (iter->stationNumber) != (j + 1))
cout << j + 1 << ": empty ";
}
}
cout << endl;
}
}
//This function will simulate a logoff by looking for the ID number that was typed in
//It will then clear that computer station and log the user off
void logoff(NodePtr labs[])
{
int IDNumber;
bool isBreak = false;
cout << "Enter 5 digit ID number of the user to find: " << endl;
cin >> IDNumber;
for (int i = 0; i < COMPUTER_LABS; i++)
{
int j = 0;
for (NodePtr iter = labs[i]; iter != NULL; iter = iter->link, j++) //This is where it says exception unhandled
{
if (iter->IDNumber == IDNumber)
remove(iter, j);
}
}
cout << "User " << IDNumber << " is logged off." << endl << endl;
}
int main()
{
NodePtr computerLabs[COMPUTER_LABS];
for (int i = 0; i < COMPUTER_LABS; i++)//Initialize nodes in array so that we don't get any undefined behavior from not initializing
{
computerLabs[i] = new User;
computerLabs[i]->stationNumber = NULL;
computerLabs[i]->IDNumber = NULL;
computerLabs[i]->link = NULL;
}
int userChoice; //This is for making a choice at the main menu
do
{
cout << "LAB STATUS" << endl;
cout << "Lab # Computer Stations" << endl;
showLabs(computerLabs); //Show the current computer labs and their statuses
cout << endl << "MAIN MENU" << endl;
cout << "0) Quit" << endl;
cout << "1) Simulate login" << endl;
cout << "2) Simulate logoff" << endl;
cin >> userChoice; // ask user for choice
if (userChoice == 1)
login(computerLabs);
else if (userChoice == 2)
logoff(computerLabs);
} while (userChoice != 0);
return 0;
}
答案 0 :(得分:3)
这段代码几乎完全错误。要修复代码,请首先不要求用户输入。使用预定值使程序更容易调试。获得基础知识后,您可以添加用户输入。
不要使用声明typedef User* NodePtr
它没有任何问题,但它隐藏了指针,它可能会让你感到困惑。
链接列表最初应为空,如下所示:
for(int i = 0; i < COMPUTER_LABS; i++)
computerLabs[i] = NULL;
删除节点时,如果节点为head
,则需要不同的条件。这是一个简单的版本:
#include <iostream>
using namespace std;
struct User
{
int id;
User *next;
};
const int COMPUTER_LABS = 4;
void login(User *labs[], int lab, int id)
{
User *p = new User;
p->id = id;
p->next = labs[lab];
labs[lab] = p;
}
void logoff(User *labs[], int lab, int id)
{
User *prev = nullptr;
User* walk = labs[lab];
while(walk)
{
if(walk->id == id)
{
User *next = walk->next;
delete walk;
if(prev)
prev->next = next;
else
labs[lab] = next;
break;
}
prev = walk;
walk = walk->next;
}
}
void showLabs(User *labs[])
{
for(int i = 0; i < COMPUTER_LABS; i++)
{
cout << "Lab number " << i << ": ";
User* walk = labs[i];
while(walk)
{
cout << "id: " << walk->id << ", ";
walk = walk->next;
}
cout << endl;
}
}
int main()
{
User *labs[COMPUTER_LABS];
for(int i = 0; i < COMPUTER_LABS; i++)
{
//linked list is initially empty, this is "head"
labs[i] = NULL;
}
login(labs, 0, 100);
login(labs, 0, 101);
login(labs, 1, 200);
login(labs, 1, 201);
showLabs(labs);
logoff(labs, 0, 100);
showLabs(labs);
return 0;
}
答案 1 :(得分:2)
每次使用删除时,都应将指针设置为NULL。
delete temp->link
添加
temp->link = NULL
刚刚过去。删除已删除的指针是一种合理的预防措施。 删除释放已分配的内存,但不一定清除指针或将其设置为NULL。您可以在调试器中检查它。在指针上设置手表。当它被分配和使用时,您会看到所有字段。删除后,字段将是无意义的,因为它指向未分配的内存。