"linked-list" 控制台应用程序在出现问题时冻结,但仍然不会显示错误,所以我无法查明问题所在
The "linked-list" console application froze when something went wrong, but still wouldn't show errors, so I can't pinpoint the problem
对于上下文,我创建了一个基本的“电子邮件模拟器”,您可以使用它向自己发送电子邮件、阅读电子邮件和删除电子邮件。我必须在此方法中使用堆栈 linked 列表样式方法,这就是标准。
到目前为止,我发现问题出在 displayInbox 函数上,但我不确定到底出了什么问题,因为据我所知,它似乎是合乎逻辑的。但是我无法确定,因为它不提供错误代码或触发本地 Windows 调试器,它只是冻结。
要触发与我相同的错误,只需撰写 2 封电子邮件,然后检查收件箱。如果您在两者之间检查收件箱并不重要。
我以前能做到,但现在我做不到。
我正在使用 VS2019 作为参考。
我不是很有经验所以它可能非常臃肿,所以它很大。但是我尽力把一个从 600 多行缩短到 280 行左右,但你仍然可以使错误发生。这是完整程序的 pastebin link 以防万一
https://pastebin.com/Hp3uP0B9
#include <iostream>
#include <string>
#include <stdlib.h>
#include <windows.h>
using namespace std;
struct Email //just a basic struct
{
string data;
int index{}; //every new email will have a different index, used to traverse and pinpoint the correct email.
Email* prev{}, * next{}; //just previous and next nodes
};
Email* myTemplate() //used to initialise a struct (alternative of constructor)
{
Email* temp = new Email;
temp->data = "[=11=]";
temp->index = 0;
temp->next = NULL;
temp->prev = NULL;
return temp;
};
struct UI //another basic struct, but using constructors
{
UI* prev, * next; //previous and next nodes
string text[2]; //stores the selected text and unselected text
bool selected; //bool to know when to trigger selected text
int menuFunc; //used to determine which function to call, can also be used to represent Email's index when passing in values
UI()
{
prev = NULL;
next = NULL;
text[0] = "[=11=]";
text[1] = "[=11=]";
selected = false;
menuFunc = -1;
}
UI(UI* myPrev, UI* myNext, int myMFunc, string myText)
{
prev = myPrev;
next = myNext;
menuFunc = myMFunc;
text[0] = myText;
text[1] = "<<" + text[0] + ">>";
selected = false;
}
};
int mainMenu()
{
int temp;
cout << "type 1 to compose email, type 2 to display inbox, type 99 to quit\n: ";
cin >> temp;
if (temp == 1||temp == 2||temp == 99)
{
return temp;
}
else
{
return mainMenu();
}
}
int getKeyInt() //just a function to get relevant key codes
{
if (GetAsyncKeyState(VK_UP))
{
return VK_UP;
}
else if (GetAsyncKeyState(VK_DOWN))
{
return VK_DOWN;
}
else if (GetAsyncKeyState(VK_RETURN))
{
return VK_RETURN;
}
else if (GetAsyncKeyState(VK_ESCAPE))
{
return VK_ESCAPE;
}
else
{
return -1;
}
}
void displayInbox(UI* myNavi, UI* myHead, UI* myTail, Email*& eNavi, Email*& eHead, Email*& eTail) //displays the inbox of the mail
{
bool modified = false;
bool tempRunFlag = true;
int tempKeyPress;
UI* refreshCache = myHead; // to log the navigator's location upon reprinting the screen, points to head before the loop begins
myNavi = myHead; //points the navigator to the newest node in the list
eNavi = eTail; //email navigator switches address to the newest node in the email linked list
if (eNavi->data != "[=11=]") //to check if newest mail has values, just in case
{
myNavi->menuFunc = eNavi->index; //assigns the email index to the "menuFunc" to be passed when calling deleteMail() and displayMail()
myNavi->text[0] = eNavi->data; //sets the UI text of navigator
myNavi->text[1] = "<<" + myNavi->text[0] + ">>";
myHead = myNavi;//setting myHead to point to navigator's current address
myHead->selected = true; //this will trigger the selected text's output later
refreshCache = myHead;// assigns refreshCache to myHead
myTail = myHead; //if it's only 1 mail in the list, then this will prevent UI from traversing into NULL, if not, below will change the values
if (eNavi->prev != NULL)//if email navigator has a earlier mail to point to, false if there's only 1 element in the list, which is already done above
{
while (eNavi != NULL)//if email navigator is not pointing to the earliest mail, or if theres only 1 element
{
if (eNavi != eHead) //double checking if email navigator hasn't reached the earliest mail yet, if it is, then no need to go even earlier
{
eNavi = eNavi->prev; //email navigator approaches eHead by 1 node
}
myNavi->next = new UI(myNavi, NULL, eNavi->index, eNavi->data); //creates a new node to point to
myNavi = myNavi->next; // navigator switch to the next address that it created
myTail = myNavi; //assigns tail to newly created UI navigator node
}
}
}
else //if newest mail has no values, or no mail
{
myHead = new UI(NULL, NULL, 0, "nothing to see here");
myHead->selected = true;
refreshCache = myHead;
myTail = myHead;
}
while (tempRunFlag)
{
system("CLS");
cout <<
"\nNow browsing inbox..." << endl <<
"____________________________________________________________________________________________________" << endl <<
"MAIL DATA"<< endl;
myNavi = myHead; //UI navigator will be reassigned to point to first UI
while (myNavi != NULL)
{
cout << myNavi->text[(int)myNavi->selected] << endl;
myNavi = myNavi->next;
}
myNavi = refreshCache;//similar implementation in the prompt() function;
if (myNavi != NULL)
{
cout << "\nMenu Function code: " << myNavi->menuFunc << endl;//used for debugging, displays the menuFunc
}
cout <<
"\n\nReached end of inbox" << endl <<
"____________________________________________________________________________________________________" << endl <<
"[Use ARROW KEYS UP & DOWN to navigate, ESC to return to Main Menu]" << endl;
system("pause");
tempKeyPress = getKeyInt();
switch (tempKeyPress)
{
case VK_UP:
if (myNavi != myHead)
{
myNavi->selected = false;
myNavi = myNavi->prev;
myNavi->selected = true;
refreshCache = myNavi;
}
break;
case VK_DOWN:
if (myNavi != myTail)
{
myNavi->selected = false;
myNavi = myNavi->next;
myNavi->selected = true;
refreshCache = myNavi;
}
break;
case VK_ESCAPE:
tempRunFlag = false;
break;
default:
break;
}
}
return;
}
void composeEmail(Email*& eHead, Email*& eTail) //prompting the user to get data
{
Email* draft = new Email;
system("CLS");
if (eHead->data != "[=11=]") ///used to get rid of a \n character in the buffer for no reason, I don't know why it's there, but whats weird is that it only happens once the email linked list already has 1 element inside of it
{
cin.ignore();
}
do
{
cout << "\nPlease type in data (16 character limit)" << endl; //just for no reason
getline(cin, draft->data);
} while (draft->data.length() > 16 || draft->data.length() <= 0);
while (draft->data.length() < 16)
{
draft->data += " ";
}
cout << "\n\nEmail is sent! Please check inbox." << endl;
draft->next = NULL;
if (eHead->data == "[=11=]") //if current head node is empty
{
draft->prev = NULL;
draft->index = eTail->index + 1;
eHead = draft;
eTail = eHead;
}
else //if head node already has a value
{
draft->prev = eTail;
draft->index = eTail->index + 1;
eTail->next = draft;
eTail = draft;
}
system("pause");
}
bool mainMenuExecute(int executionCode, UI* uiNaviIB, UI* uiHeadIB, UI* uiTailIB, Email*& eNavi, Email*& eHead, Email*& eTail)
{
if (executionCode == 1)
{
composeEmail(eHead, eTail);
return true;
}
else if (executionCode == 2)
{
displayInbox(uiNaviIB, uiHeadIB, uiTailIB, eNavi, eHead, eTail);
return true;
}
else if (executionCode == 99)
{
return false;
}
}
int main()
{
//Inbox UI
UI* uiHeadIB = new UI(NULL, NULL, 0, "nothing to see here"),
* uiTailIB = uiHeadIB,
* uiNaviIB = uiHeadIB;
uiNaviIB->selected = true;
//Actual mail stuff
Email* mHead = myTemplate(),
* mTail = mHead;
Email* mNavi = mHead;
bool simulate = true;
while (simulate)
{
system("CLS");
simulate = mainMenuExecute(mainMenu(), uiNaviIB, uiHeadIB, uiTailIB, mNavi, mHead, mTail);
}
}
希望有人能在我学到更多的同时提供建设性的批评,干杯。
我解决了这个问题,但是还有一个问题,不过那是另一种情况,至于我是如何解决它的,我在if(eNavi != eHead)之后放了一个else{break;},因为它导致了while 循环如果没有中断则无限循环。
对于上下文,我创建了一个基本的“电子邮件模拟器”,您可以使用它向自己发送电子邮件、阅读电子邮件和删除电子邮件。我必须在此方法中使用堆栈 linked 列表样式方法,这就是标准。
到目前为止,我发现问题出在 displayInbox 函数上,但我不确定到底出了什么问题,因为据我所知,它似乎是合乎逻辑的。但是我无法确定,因为它不提供错误代码或触发本地 Windows 调试器,它只是冻结。
要触发与我相同的错误,只需撰写 2 封电子邮件,然后检查收件箱。如果您在两者之间检查收件箱并不重要。 我以前能做到,但现在我做不到。 我正在使用 VS2019 作为参考。
我不是很有经验所以它可能非常臃肿,所以它很大。但是我尽力把一个从 600 多行缩短到 280 行左右,但你仍然可以使错误发生。这是完整程序的 pastebin link 以防万一 https://pastebin.com/Hp3uP0B9
#include <iostream>
#include <string>
#include <stdlib.h>
#include <windows.h>
using namespace std;
struct Email //just a basic struct
{
string data;
int index{}; //every new email will have a different index, used to traverse and pinpoint the correct email.
Email* prev{}, * next{}; //just previous and next nodes
};
Email* myTemplate() //used to initialise a struct (alternative of constructor)
{
Email* temp = new Email;
temp->data = "[=11=]";
temp->index = 0;
temp->next = NULL;
temp->prev = NULL;
return temp;
};
struct UI //another basic struct, but using constructors
{
UI* prev, * next; //previous and next nodes
string text[2]; //stores the selected text and unselected text
bool selected; //bool to know when to trigger selected text
int menuFunc; //used to determine which function to call, can also be used to represent Email's index when passing in values
UI()
{
prev = NULL;
next = NULL;
text[0] = "[=11=]";
text[1] = "[=11=]";
selected = false;
menuFunc = -1;
}
UI(UI* myPrev, UI* myNext, int myMFunc, string myText)
{
prev = myPrev;
next = myNext;
menuFunc = myMFunc;
text[0] = myText;
text[1] = "<<" + text[0] + ">>";
selected = false;
}
};
int mainMenu()
{
int temp;
cout << "type 1 to compose email, type 2 to display inbox, type 99 to quit\n: ";
cin >> temp;
if (temp == 1||temp == 2||temp == 99)
{
return temp;
}
else
{
return mainMenu();
}
}
int getKeyInt() //just a function to get relevant key codes
{
if (GetAsyncKeyState(VK_UP))
{
return VK_UP;
}
else if (GetAsyncKeyState(VK_DOWN))
{
return VK_DOWN;
}
else if (GetAsyncKeyState(VK_RETURN))
{
return VK_RETURN;
}
else if (GetAsyncKeyState(VK_ESCAPE))
{
return VK_ESCAPE;
}
else
{
return -1;
}
}
void displayInbox(UI* myNavi, UI* myHead, UI* myTail, Email*& eNavi, Email*& eHead, Email*& eTail) //displays the inbox of the mail
{
bool modified = false;
bool tempRunFlag = true;
int tempKeyPress;
UI* refreshCache = myHead; // to log the navigator's location upon reprinting the screen, points to head before the loop begins
myNavi = myHead; //points the navigator to the newest node in the list
eNavi = eTail; //email navigator switches address to the newest node in the email linked list
if (eNavi->data != "[=11=]") //to check if newest mail has values, just in case
{
myNavi->menuFunc = eNavi->index; //assigns the email index to the "menuFunc" to be passed when calling deleteMail() and displayMail()
myNavi->text[0] = eNavi->data; //sets the UI text of navigator
myNavi->text[1] = "<<" + myNavi->text[0] + ">>";
myHead = myNavi;//setting myHead to point to navigator's current address
myHead->selected = true; //this will trigger the selected text's output later
refreshCache = myHead;// assigns refreshCache to myHead
myTail = myHead; //if it's only 1 mail in the list, then this will prevent UI from traversing into NULL, if not, below will change the values
if (eNavi->prev != NULL)//if email navigator has a earlier mail to point to, false if there's only 1 element in the list, which is already done above
{
while (eNavi != NULL)//if email navigator is not pointing to the earliest mail, or if theres only 1 element
{
if (eNavi != eHead) //double checking if email navigator hasn't reached the earliest mail yet, if it is, then no need to go even earlier
{
eNavi = eNavi->prev; //email navigator approaches eHead by 1 node
}
myNavi->next = new UI(myNavi, NULL, eNavi->index, eNavi->data); //creates a new node to point to
myNavi = myNavi->next; // navigator switch to the next address that it created
myTail = myNavi; //assigns tail to newly created UI navigator node
}
}
}
else //if newest mail has no values, or no mail
{
myHead = new UI(NULL, NULL, 0, "nothing to see here");
myHead->selected = true;
refreshCache = myHead;
myTail = myHead;
}
while (tempRunFlag)
{
system("CLS");
cout <<
"\nNow browsing inbox..." << endl <<
"____________________________________________________________________________________________________" << endl <<
"MAIL DATA"<< endl;
myNavi = myHead; //UI navigator will be reassigned to point to first UI
while (myNavi != NULL)
{
cout << myNavi->text[(int)myNavi->selected] << endl;
myNavi = myNavi->next;
}
myNavi = refreshCache;//similar implementation in the prompt() function;
if (myNavi != NULL)
{
cout << "\nMenu Function code: " << myNavi->menuFunc << endl;//used for debugging, displays the menuFunc
}
cout <<
"\n\nReached end of inbox" << endl <<
"____________________________________________________________________________________________________" << endl <<
"[Use ARROW KEYS UP & DOWN to navigate, ESC to return to Main Menu]" << endl;
system("pause");
tempKeyPress = getKeyInt();
switch (tempKeyPress)
{
case VK_UP:
if (myNavi != myHead)
{
myNavi->selected = false;
myNavi = myNavi->prev;
myNavi->selected = true;
refreshCache = myNavi;
}
break;
case VK_DOWN:
if (myNavi != myTail)
{
myNavi->selected = false;
myNavi = myNavi->next;
myNavi->selected = true;
refreshCache = myNavi;
}
break;
case VK_ESCAPE:
tempRunFlag = false;
break;
default:
break;
}
}
return;
}
void composeEmail(Email*& eHead, Email*& eTail) //prompting the user to get data
{
Email* draft = new Email;
system("CLS");
if (eHead->data != "[=11=]") ///used to get rid of a \n character in the buffer for no reason, I don't know why it's there, but whats weird is that it only happens once the email linked list already has 1 element inside of it
{
cin.ignore();
}
do
{
cout << "\nPlease type in data (16 character limit)" << endl; //just for no reason
getline(cin, draft->data);
} while (draft->data.length() > 16 || draft->data.length() <= 0);
while (draft->data.length() < 16)
{
draft->data += " ";
}
cout << "\n\nEmail is sent! Please check inbox." << endl;
draft->next = NULL;
if (eHead->data == "[=11=]") //if current head node is empty
{
draft->prev = NULL;
draft->index = eTail->index + 1;
eHead = draft;
eTail = eHead;
}
else //if head node already has a value
{
draft->prev = eTail;
draft->index = eTail->index + 1;
eTail->next = draft;
eTail = draft;
}
system("pause");
}
bool mainMenuExecute(int executionCode, UI* uiNaviIB, UI* uiHeadIB, UI* uiTailIB, Email*& eNavi, Email*& eHead, Email*& eTail)
{
if (executionCode == 1)
{
composeEmail(eHead, eTail);
return true;
}
else if (executionCode == 2)
{
displayInbox(uiNaviIB, uiHeadIB, uiTailIB, eNavi, eHead, eTail);
return true;
}
else if (executionCode == 99)
{
return false;
}
}
int main()
{
//Inbox UI
UI* uiHeadIB = new UI(NULL, NULL, 0, "nothing to see here"),
* uiTailIB = uiHeadIB,
* uiNaviIB = uiHeadIB;
uiNaviIB->selected = true;
//Actual mail stuff
Email* mHead = myTemplate(),
* mTail = mHead;
Email* mNavi = mHead;
bool simulate = true;
while (simulate)
{
system("CLS");
simulate = mainMenuExecute(mainMenu(), uiNaviIB, uiHeadIB, uiTailIB, mNavi, mHead, mTail);
}
}
希望有人能在我学到更多的同时提供建设性的批评,干杯。
我解决了这个问题,但是还有一个问题,不过那是另一种情况,至于我是如何解决它的,我在if(eNavi != eHead)之后放了一个else{break;},因为它导致了while 循环如果没有中断则无限循环。