0

Parsing a file and need to add students to a struct vector using an array for student names specific to that course line.

In my course.h file:

struct Course {
    std::string name;
    int enrollment;
    int maxEnrollment;

    std::string* students; ///< array of student names

    Course(std::string courseName, int maxEnrollmentPermitted);

    bool enroll(std::string studentName);

    void print(std::ostream& output);
};

In my course.cpp file:

bool Course::enroll(std::string studentName) {
    this->students = new std::string[studentName];
    if (this->enrollment < this->maxEnrollment) {
        this->enrollment++;
        return true;
    }
    else {
        return false;

In my source file:

void processEnrollmentRequests(istream& enrollmentRequestsFile, vector<Course>& courses) {
    // Read the requests, one at a time, serving each one
    string courseName;
    enrollmentRequestsFile >> courseName;

    while (enrollmentRequestsFile) {
        enrollmentRequestsFile >> ws;
        string studentName;
        getline(enrollmentRequestsFile, studentName);

        int pos = search(courses, courseName);
        if (pos >= 0) {
            // Found a matching course
            bool enrolled = courses[pos].enroll(studentName);
            if (enrolled) {
                cout << studentName << " has enrolled in " << courseName << endl;
            }
            else {
                // course is full
                cout << studentName << " cannot enroll in " << courseName << endl;
            }
        }
        else {
            // course does not exist
            cout << studentName << " cannot enroll in " << courseName << endl;
        }
        enrollmentRequestsFile >> courseName;
    }
}
        }
    }

I cant seem to add the gathered studentName to the array using this->students = new std::string[studentName]. Getting an error that says must have integral or enumeration type.

pstatix
  • 3,611
  • 4
  • 18
  • 40
  • 5
    Offish-topic: may I suggest another `std::vector` here: `std::string* students;`-> `std::vector students;` – user4581301 Mar 30 '17 at 21:34
  • 1
    When you do `new std::string[...]` the contents of `[...]` should be a number, the size of the array to allocate. It makes no sense to write `new std::string[studentName]` – Barmar Mar 30 '17 at 21:36
  • 2
    `vector` -- You used this, so why didn't you simply use `std::vector` instead of all of the pointer manipulation? – PaulMcKenzie Mar 30 '17 at 21:39
  • We have to use pointers and arrays unfortunately. Otherwise I would concur. – pstatix Mar 30 '17 at 21:55
  • @pstatix -- So why are you using `vector`? Doesn't that go against your rule of using only pointers and arrays? What is it about `std::string` that makes teachers give weird assignments like this? You can use `vector`, but not `vector`. Strange. – PaulMcKenzie Mar 30 '17 at 22:03
  • @PaulMcKenzie in the course.cpp we have to use pointers and arrays. The scope of the work is to build pointer and array knowledge. However, after making the changes suggested by Xiaoy I get a stackdump. – pstatix Mar 30 '17 at 22:05
  • 1
    @pstatix -- Are you reading the code you wrote? You are already using `vector`. Do you know what `vector` is? It is a class that represents a *dynamic array*, thus you're going against your own rules. You need to pointer-up that `Course` also, just like you're pointering-up that `std::string`. – PaulMcKenzie Mar 30 '17 at 22:07
  • @PaulMcKenzie Where in my **course.cpp** do you see a `vector`? Course is a `struct` and the only piece of my **course.cpp** I show is the `bool` function that doesn't have any `vector` in it. – pstatix Mar 30 '17 at 22:09
  • @pstatix -- `void processEnrollmentRequests(istream& enrollmentRequestsFile, vector& courses)` -- Do you see it now? – PaulMcKenzie Mar 30 '17 at 22:10
  • @PaulMcKenzie I'm not gonna waste time arguing with you. But to prove you out of our own point. The section you just quoted is from the section above labeled **In my source file**. The file is **enrollment.cpp** and my question resides in **course.cpp** which is **not** the **main source file**. Please re-read my question before attempting to comment further. – pstatix Mar 30 '17 at 22:12
  • I am reading what you posted: *In my source file:* -- Isn't that what you wrote? No one is going to delineate what you did or did not write -- we are reading what you posted, and in that post, you are using `vector`. My eyes don't lie. – PaulMcKenzie Mar 30 '17 at 22:14
  • @I've been telling you this whole time. WE CAN ONLY POINTERS AND ARRAYS IN **COURSE.CPP**. I AM ALLOWED TO USE IT IN THE **SOURCE FILE**. Your eyes do lie because you are not reading. They are two different files. One I can, one I cant. Problem exists in the one that I cant. Otherwise, I would've been done and already used a vector. – pstatix Mar 30 '17 at 22:16
  • If that is the case, that is one schizophrenic assignment. – PaulMcKenzie Mar 30 '17 at 22:20
  • @PaulMcKenzie I don't pick em. That's called being the student. And the answer given below will point you to what I had to use...without `vector`... – pstatix Mar 30 '17 at 22:22
  • Well, your code, whether you wrote it or not, has a bug, a serious one. You are using `vector` and `Course` fails to follow the "rule of 3" i.e. no copy constructor, assignment operator, or destructor. Thus using in any way `vector` leads to memory corruption since `vector` will be making copies. This is the state that teaching C++ has devolved to -- giving students buggy code. – PaulMcKenzie Mar 30 '17 at 22:25

2 Answers2

1

new SomeThing[size] is used to declare array. It makes no sense to use a string as the size.

Assuming the size of students is limited to maxEnrollment, you can use this:

if (this->enrollment < this->maxEnrollment) {
    this->students[this->enrollment++] = studentName;
    return true;
}
else {
    return false;
Xiaoy312
  • 14,292
  • 1
  • 32
  • 44
0

For the sake of completeness, the allocation of students is not the only problem. Given that the code you posted also uses std::vector<Course>, and Course does not follow the rule of 3, using it in a std::vector is highly likely to cause memory corruption, leaks, etc.

Given that you state that students must remain a pointer, the complete fix is to write Course in this manner:

#include <string>
#include <algorithm>

struct Course {
    std::string name;
    int enrollment;
    int maxEnrollment;
    std::string* students; ///< array of student names
    Course(std::string courseName, int maxEnrollmentPermitted);
    bool enroll(std::string studentName);
    void print(std::ostream& output);
    Course(const Course& rhs);
    Course& operator =(const Course& rhs);
    ~Course();
};

Course::Course(const Course& rhs) : name(rhs.name),  
                                    enrollment(rhs.enrollment),  
                                    maxEnrollment(rhs.maxEnrollment),
                                    students(new std::string[rhs.maxEnrollment])
{
   for (int i = 0; i < maxEnrollment; ++i)
      students[i] = rhs.students[i];
}

Course& Course::operator= (const Course& rhs)
{
   Course temp(rhs);
   std::swap(temp.students, students);
   std::swap(temp.maxEnrollment, maxEnrollment);
   std::swap(temp.enrollment, enrollment);
   std::swap(temp.name, name);
   return *this;
}

Course::~Course() { delete [] students; }

Course::Course(std::string courseName, int maxEnrollmentPermitted) : 
               name(courseName), 
               enrollment(0),
               maxEnrollment(maxEnrollmentPermitted), 
               students(new std::string[maxEnrollmentPermitted])    
{}

Why all of this code? Well, in the code you posted in your question, you are using a std::vector<Course>. The Course class as written could not be safely used in a vector, due to Course having incorrect copy semantics. Thus your error you're getting may have a lot to do with code you stated wasn't yours (the vector<Course>).

The adjustments to Course above now makes Course safe to be used in a vector since the copy semantics (copy constructor, assignment operator, and destructor) have now been implemented to handle the dynamically allocated students member.

Note that absolutely none of this code would be necessary if students were simply a std::vector<std::string> instead of std::string *.

For more reading:

What is the rule of 3?

What is the copy / swap idiom?

Community
  • 1
  • 1
PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
  • I am not to alter the **main source file**. Only the **course.cpp**. Thanks for the reads though. – pstatix Mar 30 '17 at 23:03
  • Well, you may never get to actually rid yourself of the error until these changes are implemented. You were given a broken class and expect it to work without issues when placed in a vector. The teacher is doing you a disservice by providing such a mess. – PaulMcKenzie Mar 31 '17 at 03:36