Search code examples
c++for-loopnullptr

Trying to loop check for Nullptr C++


I am trying to figure out how to alternatively check if the pointer in the array is currently NULL and loop through. At the moment if the content in that part of the array is deleted it will throw an error when looping.

This array is initialized:

Student *classRosterArray[5] = { nullptr, nullptr, nullptr, nullptr, nullptr };

The loop

void Roster::add(string studentID, string firstName, string lastName, string email, int age, int daysInCourse1, int daysInCourse2, int daysInCourse3, Degree degreeProgram)
{
    int courseDaysin[3] = { daysInCourse1, daysInCourse2, daysInCourse3 };

    for (int i = 0; i < sizeof(classRosterArray) / sizeof(classRosterArray[i]); i++) {
        if (classRosterArray[i] == nullptr) {
            if (degreeProgram == NETWORKING) {
                classRosterArray[i] = new NetworkStudent(age, courseDaysin, studentID, email, firstName, lastName, degreeProgram);
            }
            else if (degreeProgram == SECURITY) {
                classRosterArray[i] = new SecurityStudent(age, courseDaysin, studentID, email, firstName, lastName, degreeProgram);
            }
            else if (degreeProgram == SOFTWARE) {
                classRosterArray[i] = new SoftwareStudent(age, courseDaysin, studentID, email, firstName, lastName, degreeProgram);
            }
            else {
                classRosterArray[i] = new Student(age, courseDaysin, studentID, email, firstName, lastName, degreeProgram);
            }

            break;//stop 
        }
    }
}

When Deleted:

void Roster::remove(string studentID)
{
    bool studentRemoved = false;
    for (int i = 0; i < sizeof(classRosterArray) / sizeof(classRosterArray[i]); i++) {
        if (classRosterArray[i] != nullptr && classRosterArray[i]->fetchStudentId() == studentID) {
            classRosterArray[i] = nullptr;
            studentRemoved = true;
            break;
        }
    }

    if (studentRemoved == false) {
        cout << "ERROR: Student ID '" << studentID << "' was not found.";
    }
}

Edited to add following code snippets with the previously suggested modifications how should I go about changing the following now that I am using the Map rather than my original array. Thanks for the help so far guys!

void Roster::printAll()
{
    for (int i = 0; i < sizeof(classRosterArray) / sizeof(classRosterArray[i]); i++) {
        classRosterArray[i]->print();
    }
}

void Roster::printByDegreeProgram(int degreeProgram)
{
    for (int i = 0; i < sizeof(classRosterArray) / sizeof(classRosterArray[i]); i++) {
        if (classRosterArray[i]->fetchDegreeProgram() == degreeProgram) {
            classRosterArray[i]->print();
        }
    }
}

void Roster::printDaysInCourse(string studentID)
{
    float avg = 0;
    int max = 3;
    for (int i = 0; i < sizeof(classRosterArray) / sizeof(classRosterArray[i]); i++) {
        if (classRosterArray[i] != nullptr && classRosterArray[i]->fetchStudentId() == studentID) {
            int *daysInCourse = classRosterArray[i]->fetchDaysInCourse();
            for (int x = 0; x < max; x++) {
                avg += daysInCourse[x];
            }

            cout << "Student " << classRosterArray[i]->fetchStudentId() << "'s average number of days in each course is." << (avg / max) << "\n";
            break;
        }
    }
}

void Roster::printInvalidEmails()
{
    for (int i = 0; i < sizeof(classRosterArray) / sizeof(classRosterArray[i]); i++) {
        string email = classRosterArray[email]->fetchEmail();
        bool isValid = false;

        size_t found = email.find("@");
        if (found != string::npos) {
            found = email.find(".");
            if (found != string::npos) {
                found = email.find(" ");
                if (found == string::npos) {
                    isValid = true;
                }
            }
        }

        if (!isValid) {
            cout << email << " is not a valid email address \n";
        }
    }
}

Solution

  • Problems with your code:

    • You are using plain C arrays, they are harder to use and easier to break
    • In your delete method you are not using "delete" to remove the object you have created with "new", so you are leaking every removed student.
    • If you have more than 5 students your add method fails without any error report
    • In a real program when you have a huge number of students iterate all of them for every "add" or "remove" operation is a big performance hit.

    This is how it should be written in modern C++:

    map<string, shared_ptr<Student> > classRosterArray;
    
    void Roster::add(string studentID, string firstName, string lastName, string email, int age, int daysInCourse1, int daysInCourse2, int daysInCourse3, Degree degreeProgram)
    {
      int courseDaysin[3] = { daysInCourse1, daysInCourse2, daysInCourse3 };
      switch (degreeProgram) {
         case NETWORKING:
             classRosterArray[studentID] = std::shared_ptr<Student>(new NetworkStudent(age, courseDaysin, studentID, email, firstName, lastName, degreeProgram));
             break;
         case SECURITY:
             classRosterArray[studentID] = shared_ptr<Student>(new SecurityStudent(age, courseDaysin, studentID, email, firstName, lastName, degreeProgram));
             break;
             /* [...] */
         default:
             classRosterArray[studentID] = shared_ptr<Student>(new Student(age, courseDaysin, studentID, email, firstName, lastName, degreeProgram));
      }
    }
    
    void Roster::remove(string studentID)
    {
        auto it = classRosterArray.find(studentID);
        if (it != classRosterArray.end())
            classRosterArray.erase(it);
        else
            cout << "ERROR: Student ID '" << studentID << "' was not found.";
    }