c++ - 将 C 转换为 C++ 和动态内存分配

标签 c++ c

因此,我最近的任务是将我用 C 编写的程序转换为 C++,以便在编程入门类(class)中完成作业。该程序是一个基本的数据库程序,用户可以在其中创建包含学生 ID、文字名称、类(class) ID、文字名称和成绩的成绩簿。用户将能够与菜单交互并执行许多操作。最重要的是,该程序可以在需要时重新分配更多内存,并且会自动执行此操作。所以现在,我正在尝试将此程序转换为 C++。

大约两周半前我们开始在类里面讨论 C++,所以我对这门语言还很陌生。我已经给出了该程序的片段以及我所做的事情,以便你们都可以更好地理解我的问题。我已经包括了类(class)的类(class)和只有两个功能(第一个添加类(class) ID 和文本名称,第二个打印类(class)的完整列表)。我希望边界从 25 开始,如果用户想输入超过这个边界的更多类(class),程序将分配更多内存并将旧条目复制到新空间。我不确定我是否仍然不了解构造函数或什么,但是每当用户输入第 26 门类(class)时,它就不会被保存。如果我在发生这种情况时尝试打印类(class),则会出现段错误。

如果有人能发现我做错了什么,我将不胜感激。如果有什么我没有说清楚的,请告诉我,我会尽快回复。谢谢大家花时间看我的节目。

#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;
}

最佳答案

but whenever the user inputs the 26th

可能是因为这个:

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

您为 25 个学生分配了房间,而不是 26 个。但是,如果您只使用数组,就会出现此问题:

Course courses[MAX_COURSES];

对于数组,您可能 崩溃了,但问题是一样的——内存覆盖。因此,要么决定将用户限制为 25 名学生,要么允许任意数量的学生。如果是后者,则需要使用动态数组。

The most important thing was that the program could reallocate more memory when needed and it would do this automatically. So now, I'm trying to convert this program to C++.

如果您使用动态数组,学习使用 std::vector 而不是使用 new[]/delete[] 会更有优势。这就是使用 C++ 完成动态数组的方式。如果您坚持使用 new[]/delete[] 尝试调整大小,我只能告诉您“祝您好运”。我敢打赌,如果您选择 new[]/delete[] 路径,您会遇到更多问题。

vector 方法看起来像这样:

#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);
}

只需一行代码即可将类(class)添加到 vector 中。 vector 只不过是动态数组的包装器。它基本上执行 new[]/delete[],但有一个巨大的优势 - 它正确地使用了这些操作。你永远不需要亲自动手做这项工作并犯错误。 vector 知道什么时候分配,什么时候销毁等。您需要做的就是调用函数 resize()、push_back() 等。

关于c++ - 将 C 转换为 C++ 和动态内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23317793/

相关文章:

c++ - iostream 迭代器如何工作?

C++如何表达一个数学术语

c - 多个进程写入同一个文件(C)

ios - 从 swift viewcontroller 调用 .c 文件中的 swift 函数

c - 为什么xilinx使用指针将数据存储为数组?

c - 没有名为 main.c 的源文件。 gdb断点设置

c++ - 如何在 windows/msvs 上的同一个 cmake 项目中构建可执行文件和共享库

c++ - 在Windows中通过串口写入二进制数据

c++ - 带 CUDA 的 CMake : ccbin enclosed with unnecessary quotation marks (\")

c - 为一个用 C 语言记录我的工作时间和工资的程序编写简单的基本代码