程序意外退出

Posted

技术标签:

【中文标题】程序意外退出【英文标题】:Program exits unexpectedly 【发布时间】:2021-07-27 06:30:07 【问题描述】:

我正在尝试制作一个从文件中获取所有数据的程序,然后用户可以决定向文件中添加更多课程、删除特定课程或在文件中搜索特定课程。我确信还有比我所要求的更多的问题。

在 createNode 函数中,用户应该输入有关课程的所有信息,但在用户输入课程名称后程序关闭。我对编码比较陌生,我曾尝试查找此问题的解决方案,但找不到任何东西。

#include<iostream>
#include<string>
#include<fstream>
#include<cstdlib>
using namespace std;

enum week Mon,Tue,Wed,Thu,Fri;

struct courseInfo

    string courseName, CourseID, times[5], building, roomNum;
    week day[5];
course;

struct NodeType

    courseInfo *data;
    NodeType *next;
;

//Function that displays all the courses that are in the file including the courses that are added by the user
//Pre:  User inputs the correct file name for the file that has their course information
//Post: Outputs all of the classes in the file for the user to see
void displayAllCourses(string fileName);

//Function that takes a user input course ID and displays that course info
//Pre:  The user inputs a valid course ID
//Post: The class the user searched for is displayed
void searchCourse(string fileName);

//Function that allows the user to add another class to the file
//Pre:  user adds the information in the way they are prompted
//Post:
void addCourse(string fileName);

// Create and return a new node.
// Pre: None
// Post: Returns a pointer to NodeType with all of the data filled in by user
NodeType *CreateNode();

// Add a given node to a list in a sorted position.
// Pre: listPtr set to a valid list, or nullptr
//      newNodePtr assigned to a valid node with valid component value
// Post: listPtr is updated with nodePtr included in the sorted position
void AddNode(string fileName, NodeType *&listPtr, NodeType *newNodePtr);

int main()

    NodeType *headPtr;      // Always points to the first node in the list
    NodeType *lastPtr;      // Always points to the last node in the list
    NodeType *currPtr;      // Working pointer. Points to whatever node it needs to
    NodeType *newNodePtr;   // Points to a newly created node
    string fileName;        //Variable for the name of the file the user would like to open
    cout << "Please enter the name of the file you would like to open: " << endl;//Prompts the user for the name of the file they would like to open
    getline(cin, fileName);        //User inputs the file name they want to open
    char answer;
    while(1)                //Loop That repeats until the user inputs that they want to exit
    
        //prompt the user for what action they would like to do
        cout<<"Type D to display all your courses"<<endl;
        cout<<"Type S to search for a specific course"<<endl;
        cout<<"Type A to add another course"<<endl;
        cout<<"Type E to exit the program"<<endl;
        cout<<"What would you like to do: ";
        cin >> answer;
        cout<<endl;

        //Compares the users choice to the case and executes the code for that case
        switch(answer)
        
            case 'D':
            displayAllCourses(fileName);    //Function call to display all the courses in the file
            break;
            case 'S':
            
                searchCourse(fileName);     //Function call to search for a user defined course by ID
                break;
            
            case 'A':
                CreateNode();
                //AddNode(fileName, headPtr, newNodePtr);            //Function call to add another course to the file
                break;
            default:
            exit(0);
        
    


NodeType *CreateNode()
    NodeType *newNodePtr;   // Pointer for new node
    newNodePtr = new NodeType;
    string day;
    cout << "Please enter the Course name: " << endl;
    cin >> newNodePtr->data->courseName;

    cout << "Please enter Course ID: " << endl;
    cin >> newNodePtr->data->CourseID;

    cout << "Please enter the day of the course: " << endl;
    cin >> day;

    cout << "Please enter the time time of the course: " << endl;
    getline(cin, newNodePtr->data->times[0]);
    cout << "Please enter the building name: " << endl;
    getline(cin, newNodePtr->data->building);
    cout << "Please enter the room number: " << endl;
    getline(cin, newNodePtr->data->roomNum);


    if(day=="Monday")
        newNodePtr->data->day[0] = Mon;

        else if(day=="Tuesday")
            newNodePtr->data->day[0] = Tue;

        else if(day=="Wednesday")
            newNodePtr->data->day[0] = Wed;

        else if(day=="Thursday")
            newNodePtr->data->day[0] = Thu;

        else if(day=="Friday")
            newNodePtr->data->day[0] = Fri;

    newNodePtr->next = nullptr;

    return newNodePtr;


void AddNode(string fileName, NodeType *&listPtr, NodeType *newNodePtr)
    NodeType *currPtr = listPtr;    // Points to current node in list
    NodeType *prevPtr = nullptr;    // Points to node before the currPtr

    // 1 - Find position in list to add newNodePtr
    // Loop while not at end of list and new node value is greater than currPtr value to find sorted location
    while ((currPtr != nullptr) &&
           (newNodePtr->data->courseName.at(0) > currPtr->data->courseName.at(0)))
//        cout << currPtr->component << " ";        // Echo node be traversed for debugging purposes
        prevPtr = currPtr;
        currPtr = currPtr->next;
    
    cout << endl;


    // 2 - Insert node
    if ((prevPtr == nullptr) && (currPtr == nullptr))  // Pointers never moved, so first/only node
        listPtr = newNodePtr;                           // Set listPtr to new (only) node
    

    else if (prevPtr == nullptr)                       // prevPtr never moved, so need to add to beginning of list
        newNodePtr->next = listPtr;                     // Point newNodePtr->next to current beginning of list
        listPtr = newNodePtr;                           // Make newNodePtr new first node in list
    

    else if (currPtr == nullptr)
        prevPtr->next = newNodePtr;                     // prevPtr already pointing at last node, so add newPointer as new last node
    

    else 
        newNodePtr->next = currPtr;                     // Point newNodePtr->next to currPtr
        prevPtr->next = newNodePtr;                     // Update prevPtr->next to insert newNodePTr in list
    
    fstream file;
    file.open(fileName += ".txt", fstream::app);    //Adds the new course the the course list in the file
    if(!file)
    
        cout<<"Unable to open file!";
        exit(1);
    

    cout<<newNodePtr<<endl;
    file<<newNodePtr;
    file.close();


void displayAllCourses(string fileName)

    ifstream file;
    file.open(fileName += ".txt");              //Opens the user specified file
    if(!file)
    
        cout<<"Unable to open file!";           //Tells the user that the file could not open
        exit(1);
    

    int counter=1;
    string fileInfo;                            //String to hold the file information
    while(getline(file, fileInfo))              //Loop to display everything in the file
    
        cout<<counter<<": "<<fileInfo<<endl;
        counter++;
    
    cout<<endl;
    file.close();


void searchCourse(string fileName)

    string courseName;                          //Variable to hold the ID that the user wants to search for

    cout<<"Enter the course name: " << endl;            //Prompt the user for the ID of the course
    cin>>courseName;                            //User inputs the ID for the course

    ifstream file;
    file.open(fileName += ".txt");              //Open user specified file
    if(!file)
    
        cout<<"Unable to open file!";
        exit(1);
    

    string line;

    while( getline(file, line ))
    
        size_t pos = line.find(courseName);
        if ( pos != string::npos)
            cout << line << endl;
    
    cout<<endl;
    file.close();

【问题讨论】:

我的建议是使用类似于 Visual Studio 中的调试器来查找崩溃的地方。 标题注释:如果程序按预期退出,你还会问问题吗?由于答案几乎肯定是“No[,]”,因此标题不包含任何信息。一个好的标题将使问题更容易找到并帮助未来有类似问题的提问者。 【参考方案1】:

CreateNode() 中,当您调用new NodeType 时,您正在创建一个新的NodeType 对象,但NodeType 没有实现构造函数,因此它的datanext 成员保留未初始化。您稍后将nullptr 分配给newNodePtr-&gt;next,但您从未分配newNodePtr-&gt;data 指向任何地方。因此,当您尝试将用户的输入读入newNodePtr-&gt;data-&gt;courseName 时,newNodePtr-&gt;data 并未指向有效的courseInfo 对象,因此您会遇到未定义的行为,这会使您的进程崩溃。

你需要为newNodePtr-&gt;data构造一个courseInfo对象指向,例如:

NodeType *newNodePtr;
newNodePtr = new NodeType;
newNodePtr->data = new courseInfo; // <-- add this!

但是,您应该将该初始化移动到 NodeType 的构造函数中,例如:

struct NodeType

    courseInfo *data;
    NodeType *next;

    NodeType() : data(new courseInfo), next(nullptr) 
;

更好的选择是将data 成员更改为实际的courseInfo 对象而不是courseInfo* 指针,例如:

struct NodeType

    courseInfo data;
    NodeType *next = nullptr;
;

【讨论】:

非常感谢您,我按照您的建议做了,而且效果很好。即使解决方案如此简单,我也坚持了很长时间。 @SwiftTurtle 链表对于初学者来说并不容易理解。我们收到很多与 SO 上的链表相关的问题。你真的应该改用std::list&lt;courseInfo&gt;。当然不要在现代编码中手动使用new/delete。最好根本不使用指针,或者至少使用std::unique_ptr/std::shared_ptr 来管理它们(虽然,在链接列表中使用unique_ptr 是not a good idea 没有a workaround)。

以上是关于程序意外退出的主要内容,如果未能解决你的问题,请参考以下文章

应用程序意外退出时防止数据损坏

node.js:程序要么意外退出,要么只是挂起

如何解决 J2ME 中的“应用程序因内存不足而意外退出”错误

Qt - 意外的 GDB 退出

当我调用 setAdapter() 到 recycleView 时,我的 Android 应用程序意外退出

Xcode 5 在我尝试下载身份后立即意外退出