簡體   English   中英

將C轉換為C ++和動態內存分配

[英]Converting C to C++ and Dynamic Memory Allocation

因此,我最近的任務是將用C語言編寫的程序轉換為C ++,以完成編程課程的入門課程。 該程序是一個基本的數據庫程序,用戶可以在其中創建帶有學生ID,文本名稱,課程ID,文本名稱和成績的成績簿。 用戶將能夠與菜單進行交互並執行許多操作。 最重要的是,程序可以在需要時重新分配更多的內存,並且它將自動執行此操作。 所以現在,我正在嘗試將此程序轉換為C ++。

我們大約在兩個半星期前開始在課堂上討論C ++,因此我對這門語言還很陌生。 我為該程序提供了一個摘要,並且我做了什么,以便大家都能更好地理解我的問題。 我已經包括了Course課程,只有兩個功能(第一個添加課程ID和文本名稱,第二個顯示課程的完整列表)。 我希望邊界從25開始,如果用戶希望在該邊界之后添加更多課程,則程序將分配更多內存並將舊條目復制到新空間中。 我不確定我是否仍然不了解構造函數,或者什么也不了解,但是每當用戶輸入第26課時,它都不會被保存。 而且,如果在發生這種情況時嘗試打印課程,則會出現分段錯誤。

如果有人能發現我做錯了,我將不勝感激。 如果有什么我不清楚的地方,請告訴我,我會盡快回復。 感謝你們花時間看我的程序。

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>

using namespace std;

const int MAX_COURSES=25;

//Class
class Course
{
    //Two private member variables
    private:
          string courseText;
          int courseID;

    public:
    //Constructor
      Course(void);

    //Member functions
      static void addCourse(Course* courses, int *courseCounter, int *timesReallocatedCoursesCounter);
      static void printCourses(Course* courses, int *courseCounter, int *timesReallocatedCoursesCounter);

};

//Class implementation
//Constructor
Course::Course(void)
{
    //Just providing initial value to the two object variables
    courseText;
    courseID=-1;
}

//This function isn't a part of any class and will print the grade book menu.
void printMenu()
{
    cout << endl;
    cout << "GRADE BOOK MENU" << endl;
    cout << "1. Add a new course" << endl;
    cout << "2. Add a new student" << endl;
    cout << "3. Add a student to a course" << endl;
    cout << "4. Add grades for a student in a course" << endl;
    cout << "5. Print a list of all grades for a student in a course" << endl;
    cout << "6. Print a list of all students in a course" << endl;
    cout << "7. Compute the average for a student in a course" << endl;
    cout << "8. Print a list of all courses" << endl;
    cout << "9. Print a list of all students" << endl;
    cout << "10.    Compute the average for a course" << endl;
    cout << "11.    Store grade book (to a disk file" << endl;
    cout << "12.    Load grade book (from a disk file" << endl;
    cout << "13.    Quit the program" << endl;
    cout << "14. Check individual student 2D grade matrix" << endl;
    cout << endl;
}


//This method function will add a course to the course list
void Course::addCourse(Course* courses, int *courseCounter, int *timesReallocatedCoursesCounter)
{
    int userEnteredCourseID=0;
    Course* pointerCourses=NULL;
    pointerCourses = courses;
    do
    {   

    cout << endl;
    cout << "Please enter a course ID number using only integers." << endl;
    cout << "There is a limit of only 25 courses allowed in the grade book." << endl;
    cout << "To exit to grade book menu at any time, enter a negative integer or 0." << endl;
    cout << "A message will be returned to you and no course IDs will be added." << endl;   

    cin >> userEnteredCourseID;

    //Checking for a valid integer input.
    while(cin.fail())
    {
        cout << "Error! User entered something other than an integer." << endl;
        cin.clear();
        cin.ignore(256,'\n');
        cout << "Try entering a valid integer input this time..." << endl;
        cin >> userEnteredCourseID;
        }
    cout << "You have entered the integer " << userEnteredCourseID << endl;

    /*Checking if they entered a negative integer value.*/
    if(userEnteredCourseID<=0)
    {
        cout << endl;
        cout << "You have entered a negative integer or 0. Nothing has been added" << endl;
        cout << "to the course list and you will be returned to the menu." << endl;
    }

    /*A valid integer was entered.*/
    else
    {
        /*Now need to check if the course has been entered before. Should be noted, only
        course ID numbers will be checked, not text names. Two course IDs could exist for
        the same course; these ID numbers could represent different times for the same 
        course.*/

        int j;

        for(j=0; j<MAX_COURSES+(*timesReallocatedCoursesCounter); j++)
        {   
            /*Checks if user has entered that course ID before.*/
            if(courses[j].courseID==userEnteredCourseID)
            {
                cout << "You've already entered that course ID!" << endl;
                userEnteredCourseID=0;
                break;
            }

            /*If the current element doesn't equal the course ID entered, keep traversing the array.*/
            else if(courses[j].courseID!=userEnteredCourseID && j<=((MAX_COURSES + (*timesReallocatedCoursesCounter))-2))
            {
                continue;
            }

            /*Entire loop was traversed and there weren't any duplicate course IDs, so a new course will be added to array.*/   
            else
            {
                //Since the previous bounds for courses used to be 25, we'll leave that part of the code in.
                    //However, since we now want to allow for infinite inputs, if the user reaches 25
                    //courses, the program will reallocate memory and allow for more courses to be entered.
                    //Only memory space for one course will be allocated each time so space isn't wasted.
                    if(*courseCounter==(MAX_COURSES + (*timesReallocatedCoursesCounter)))
                    {
                            courses = new Course[MAX_COURSES + *timesReallocatedCoursesCounter + 1];

                    for(int m=0; m < MAX_COURSES + *timesReallocatedCoursesCounter; m++)
                    {
                        courses[m] = pointerCourses[m];
                    }

                    delete[] pointerCourses;
                            *timesReallocatedCoursesCounter+=1;
                    courses[*courseCounter].courseID=userEnteredCourseID;
                                    cout << "What would you like the new course to be called?" << endl;
                                    cin.ignore();
                                    getline(cin, courses[*courseCounter].courseText);
                                    cout << "Course " << userEnteredCourseID << " has successfully been registered with the name " << courses[*courseCounter].courseText << endl;
                                    *courseCounter+=1;
                                    cout << "Press enter to continue." << endl;
                                    cin.ignore();
                }

                else
                {

                    courses[*courseCounter].courseID=userEnteredCourseID;
                    cout << "What would you like the new course to be called?" << endl;
                    cin.ignore();
                    getline(cin, courses[*courseCounter].courseText);
                    cout << "Course " << userEnteredCourseID << " has successfully been registered with the name " << courses[*courseCounter].courseText << endl;
                    *courseCounter+=1;
                    cout << "Press enter to continue." << endl;
                    cin.ignore();
                }
            }
        }   
    }

    }while(userEnteredCourseID>0);

}

//This method function prints the courses that have been successfully entered by the user.
void Course::printCourses(Course* courses, int *courseCounter, int *timesReallocatedCoursesCounter)
{
    if(*courseCounter==0)
    {
        cout << endl;
        cout << "You haven't entered any course IDs successfully yet!" << endl;
    }

    else
    {
        int i;
        cout << endl;
        cout << *courseCounter << " course(s) successfully entered so far." << endl;
        cout << "The gradebook started with allowing only 25 courses to be entered." << endl;
        cout << "Due to the amount of courses entered by the user, memory has been reallocated" << endl;
        cout << *timesReallocatedCoursesCounter << " time(s) (in increments of 1) so entries could be made." << endl;
        cout << "This means, a maximum of " << MAX_COURSES+*timesReallocatedCoursesCounter << " courses can be entered before reallocation is needed." << endl;
        cout << "The list of the courses entered so far are:" << endl;
        for(i=0;i<*courseCounter;i++)
        {
            cout << endl;
            cout << courses[i].courseID << ": " << courses[i].courseText;
        }
        cout << endl;
    }
}

//Main program file.
int main(void)
{
    Course *courses;
    courses = new Course [MAX_COURSES];

    int userInput;
    int courseCounter = 0;
    int timesReallocatedCoursesCounter = 0;

    do
    {   
        /*Function that will re-print grade book menu.*/
        printMenu();    
        cout << "What would you like to do with the menu?" << endl;
        cin >> userInput;
            while(cin.fail())
        {
            cout << "Error! User entered something other than an integer." << endl;
            cin.clear();
            cin.ignore(256,'\n');
            cout << "Try entering a valid integer input this time..." << endl;
            cin >> userInput;
            }
        cout << "You have entered the integer " << userInput << endl;

        if(userInput==1)
        {
            cout << "You want to add a new course." << endl;
            Course::addCourse(courses, &courseCounter, &timesReallocatedCoursesCounter);
        }

        else if(userInput==2)
        {
            cout << "You want to add a new student." << endl;
        }

        else if(userInput==3)
                {
                        cout << "You want to add a student to a course." << endl;
                }

        else if(userInput==4)
                {
                        cout << "You want to add a grade for a student in a course." << endl;
                }

        else if(userInput==5)
                {
                        cout << "You want to print the grades for a student in a course." << endl;
                }

        else if(userInput==6)
                {
                        cout << "You want to print a list of students in a course." << endl;
                }

        else if(userInput==7)
                {
                        cout << "You want to compute the average for a student in a course." << endl;
                }

        else if(userInput==8)
                {
                        cout << "You want to print a list of all courses." << endl;
            Course::printCourses(courses, &courseCounter, &timesReallocatedCoursesCounter);
                }

        else if(userInput==9)
                {
                        cout << "You want to print a list of all students." << endl;
                }

        else if(userInput==10)
                {
                        cout << "You want to compute the average for a course." << endl;
                }

        else if(userInput==11)
                {
                        cout << "You want to store the grade book you've been working on to a text file." << endl;
                }

        else if(userInput==12)
                {
                        cout << "You want to load a grade book you've worked on previously from a text file." << endl;
                }

        else if(userInput==13)
                {
                        cout << "You want to quit the program." << endl;
            cout << "Goodbye, and thank you for using this program!" << endl;
                }

        else if(userInput==14)
                {
                        cout << "An optional menu function that prints an individual student's 2D array." << endl;
            cout << "This array contains all the course IDs for which the student is enrolled on the top row." << endl;
            cout << "The rows below the course IDs correspond to grades made by the student in each course." << endl;
        }

        else
        {
            cout << "User entered an integer value that doesn't correspond to any menu option." << endl;
            cout << "Nothing will happen." << endl;
        }

    }while(userInput!=13);

    delete[] courses;

    return 0;
}

但只要用戶輸入26號

可能因為這個原因:

const int MAX_COURSES=25;
//...
Course *courses;
courses = new Course [MAX_COURSES]

您分配了25名學生的房間,而不是26名學生。但是,如果您僅使用數組,就會發生此問題:

Course courses[MAX_COURSES];

對於陣列,您可能已經崩潰了,但是問題是一樣的-內存被覆蓋。 因此,要么決定-將用戶限制為25個學生,要么允許任何數量的學生。 如果是后者,則需要使用動態數組。

最重要的是,程序可以在需要時重新分配更多的內存,並且它將自動執行此操作。 所以現在,我正在嘗試將此程序轉換為C ++。

如果您使用動態數組,那么學習使用std::vector而不是使用new[]/delete[]將會是有利的。 這就是使用C ++完成動態數組的方式。 如果您堅持使用new[]/delete[]來嘗試調整大小,那么我只能告訴您“好運”。 我敢打賭,如果選擇new[]/delete[]路徑,您還會遇到更多問題。

向量方法的外觀如下所示:

#include <vector>
//...
typedef std::vector<Course> CourseVector;
//...
void addCourse(CourseVector& v)
{
    Course tempCourse;
    // gather all the user information in tempCourse
    //...
    // now add the course to the array
    v.push_back(tempCourse);
}

僅需一行代碼即可將路線添加到矢量中。 向量只不過是動態數組的包裝器。 它基本上執行new [] / delete [],但有一個巨大的優勢- 正確使用這些操作 完成這項工作和犯錯誤,您無需動手。 該向量知道何時分配,何時銷毀等。您所需要做的就是調用函數resize(),push_back()等。

我認為您的問題是您正在按值傳遞courses指針。 也就是說,將在調用堆棧上創建courses的新副本,並且您正在對該副本進行操作。 執行addCourse()后,副本將丟失。 因此,對於您添加的前25個課程,由於courses指針的副本指向與“原始”相同的內存塊,因此程序正常運行。 當您嘗試通過分配更大的內存新塊來動態地增加courses的大小時,您對main()的原始指針沒有做任何事情。 這就是為什么我認為您在打印列表時會出現段錯誤。

一種可能的解決方案是讓addCourse()返回更大的數組,將其設置為main() courses ,然后釋放舊數組。

新的addCourse()函數的原型如下所示:

static Course* addCourse(Course* courses, int *courseCounter, int *timesReallocatedCoursesCounter);

在函數內部,使用新的Course指針分配更大的數組,然后將值一個一個地復制到新數組中。 然后,返回新數組。

並使用如下語句來調用它:

Course* newCourses = addCourse(...);
delete [] courses;
courses = newCourses;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM