C++ 程序意外退出

C++ 程序意外退出,c++,struct,linked-list,C++,Struct,Linked List,我正在尝试制作一个程序,从文件中获取所有数据,然后用户可以决定向文件中添加更多课程、删除特定课程或搜索文件中的特定课程。我确信还有比我要求的更多的问题 在createNode函数中,用户应该输入有关课程的所有信息,但在用户输入课程名称后,程序关闭。我对编码比较陌生,我曾尝试寻找这个问题的解决方案,但找不到任何东西 #include<iostream> #include<string> #include<fstream> #include<cstdlib&

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

在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();
}
在CreateNode中,当您调用new NodeType时,您正在创建一个新的NodeType对象,但NodeType没有实现构造函数,因此其数据和下一个成员保持未初始化状态。稍后,您会将nullptr分配给newNodePtr->next,但从未将newNodePtr->data分配给任何位置的点。因此,当您尝试将用户的输入读入newNodePtr->data->courseName时,newNodePtr->data没有指向有效的courseInfo对象,因此您会遇到正在使进程崩溃的未定义行为

您需要为newNodePtr->data构建一个courseInfo对象以指向,例如:

NodeType*newNodePtr; newNodePtr=新节点类型;
newNodePtr->data=newcourseinfo;//我的建议是使用VisualStudio中的调试器来查找崩溃的位置。标题上有一条注释:如果程序预期退出,您还会问问题吗?因为答案几乎肯定是否定的,所以标题中没有任何信息。一个好的标题将使问题更容易找到,并帮助未来有类似问题的提问者。非常感谢我按照你的建议做了,并且成功了。即使在解决方案如此简单的时候,我也坚持了很长一段时间。@SwiftTurl链接列表对于初学者来说并不容易理解。我们得到了很多关于链表的问题。你真的应该用它来代替。当然,不要在现代编码中手动使用new/delete。最好不要使用指针,或者至少使用std::unique_ptr/std::shared_ptr来管理它们,但是在链表中使用unique_ptr是不可取的。