Thread: Error passing an array of structs

  1. #1
    Registered User
    Join Date
    Nov 2008
    Posts
    6

    Error passing an array of structs

    The goal of this program is to create an array of structs that holds a dynamic array of students and allows you to put in their name, student ID, major, and GPA.

    The code i have right now just does a flat number of students, but I'm having issues with passing the struct into the function.


    Student.h
    Code:
    // Global constants
    const int STUDENT_NAME = 40;	// Max number of characters for a students name
    const int MAJOR_NAME = 40;		// Max number of characters for a students major
    const int STUDENT_YEAR = 20;	// Max number of characters for a students year
    
    // Declaration of our Student Structure
    struct Student
    {
    	char name[STUDENT_NAME];	// Stores full name of student
    	char major[MAJOR_NAME];		// Stores major of student
    	char year[STUDENT_YEAR];	// Stores year of student (Freshman, Sophomore, Junior, Senior)
    	int studentID;				// Unique number to identify each student
    	float GPA;					// Students Grade Point Average
    };
    
    // Declaration of our class
    class myRoster
    {
    	public:
    		void FillRoster(Student CourseRoster[], int classSize);
    		
    
    
    };
    Main.cpp

    Code:
    #include <iostream>
    
    #include "Student.h"
    
    using namespace std;
    
    // Constants used througout the program
    const int CLASS_SIZE = 6;	// Class/Roster size
    const int CLASS_TITLE = 41;	// Max size of a class name.  Extra space for the NULL character.
    const int CLASS_NUMBER = 9; // Max size of the class number name.  Extra space for the NULL character.
    
    int main()
    {
    	// Create my strut object
    	Student CourseRoster[CLASS_SIZE];
    
    	// Create my class object 
    	myRoster roster;
    
    	// Create variables to hold the class name and the course number.
    	char className[CLASS_TITLE];
    	char classNumber[CLASS_NUMBER];
    
    	// Get the course name and course number from the user.  The cin.ignore lines 
    	// ensure that we only take up to the maximum number of characters allowed by that 
    	// field so that we don't accidentally try to create a course name with 60 
    	// characters or a course number with 15 characters.
    	cout << "Enter the name of the course. > ";
    	cin.getline(className, CLASS_TITLE);
    	cin.ignore(cin.rdbuf()->in_avail(), '40');
    
    	cout << endl << "Enter the course number. > ";
    	cin.getline(classNumber, CLASS_NUMBER);
    	cin.ignore(cin.rdbuf()->in_avail(), '8');
    
    	// Call the FillRoster Function
    	roster.FillRoster(CourseRoster, CLASS_SIZE);
    
    	system("pause");
    	return 0;
    }
    Implementation.cpp
    Code:
    #include <iostream>
    
    #include "Student.h"
    
    using namespace std;
    
    
    // FillRoster will take each student in the class (in our case, 6) and
    // populate their name, their major, their student ID, and their GPA.
    void FillRoster (Student CourseRoster[], int classSize)
    {
    	// 
    	for (int i = 0; i < classSize; i++)
    	{
    		cout << endl << "Enter the students name. > ";
    		cin >> CourseRoster[i].name;
    
    		cout << endl << "Enter the students major. > ";
    		cin >> CourseRoster[i].major;
    
    		cout << endl << "Enter the students ID number. > ";
    		cin >> CourseRoster[i].studentID;
    		/* REMINDER - ENTER ADDITIONAL CODE TO DETERMINE IF THE STUDENT
    		ID IS A VALID STUDENT ID.  STUDENT ID MUST BE 5 CHARACTERS LONG,
    		AND NOT A NEGATIVE NUMBER.  STUDENT ID NUMBERS MUST BE BETWEEN 
    		10000 AND 99999. */
    
    		cout << endl << "Enter the students GPA. > ";
    		cin >> CourseRoster[i].GPA;
    		/* REMINDER - ENTER ADDITIONAL CODE TO DETERMINE IF THE GPA
    		ID IS A VALID OR NOT.  GPA MUST BE BETWEEN 0.0 and 4.0 IN
    		VALUE. */
    	}
    
    
    
    
    	return;
    }
    The program appears to error out on the roster.FillRoster(CourseRoster, CLASS_SIZE); line.

    I'm sure it's something fairly simple, but frankly, after looking at it and trying stuff for a couple hours, I need a new pair of eyes on it because I'm overlooking the issue.

    Thanks in advance to all!

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    You should get a linker error because this:

    Code:
    void FillRoster (Student CourseRoster[], int classSize)
    {...}
    is a free function whereas

    Code:
    void myRoster::FillRoster (Student CourseRoster[], int classSize)
    is nowhere implemented.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #3
    Registered User
    Join Date
    Apr 2006
    Posts
    137
    Also it may be better to use a pointer when passing a struct or class to a function.

    If you DO NOT edit the struct inside the function use it like this:
    Code:
    void myRoster::FillRoster(const Student& CourseRoster, int classSize){
       return CourseRoster[5]->value;
    }
    But since I know you will be filling a roster, you should use it like this:
    Code:
    Student CourseRoster[50];
    fillRoster(&CourseRoster);
    fillRoster(Student* CourseRoster, int classSize){
        CourseRoster[4]->value = classSize;
    }
    ★ Inferno provides Programming Tutorials in a variety of languages. Join our Programming Forums. ★

  4. #4
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Also it may be better to use a pointer when passing a struct or class to a function.
    He is using a pointer.

    Both of your examples are wrong.

    Please stop "helping" until you are sufficiently capable of providing help.

    You are just going to confuse people.

    Soma

  5. #5
    Registered User
    Join Date
    Apr 2006
    Posts
    137
    Code:
    #include <iostream>
    using namespace std;
    struct Student
    {
    	string name;
    };
    
    int fillRoster(Student *c){
      cout << c[0].name << endl;
      cout << c[2].name << endl;
      return 0;
    }
    
    int main(){
      Student s[50];
      s[0].name = "bob";
      s[1].name = "Gary";
      s[2].name = "Garfield";
      fillRoster(s);
    }
    Sorry, I was using it more like a single pointer. Should have tested the code.
    This will work.

    Phantomotap, just because you're jealous and don't know much about C++ doesn't give you the right to yell at other people for helping.

    Sometimes people make mistakes, and I apologize for that, but maybe you're a nazi robot who can't tolerate mistakes. Anyway just get a life and treat people better. A simple "that won't work, you should do this instead" would have been enough, but then again your abilities probably couldn't get you to fix it so maybe you're mad you couldn't compile the code.
    ★ Inferno provides Programming Tutorials in a variety of languages. Join our Programming Forums. ★

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Catalyst8487
    The goal of this program is to create an array of structs that holds a dynamic array of students and allows you to put in their name, student ID, major, and GPA.
    For your dynamic array of students, #include <vector> an use a std::vector<Student>. Along the same lines, replace your char arrays for name, major, year, className and classNumber with std::string objects.

    Quote Originally Posted by execute
    A simple "that won't work, you should do this instead" would have been enough, but then again your abilities probably couldn't get you to fix it so maybe you're mad you couldn't compile the code.
    I agree that it would have been better to point out your mistakes, but they were obvious enough to be detected without compiling the code.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Apr 2006
    Posts
    137
    I was using the code like as if it is:
    Student CourseRoster;
    Not
    Student CourseRoster[50];

    That's why it wasn't obvious to me, I added the array without thinking, but it was silly to think so.
    ★ Inferno provides Programming Tutorials in a variety of languages. Join our Programming Forums. ★

  8. #8
    Registered User
    Join Date
    Nov 2008
    Posts
    6
    Quote Originally Posted by anon View Post
    You should get a linker error because this:

    Code:
    void FillRoster (Student CourseRoster[], int classSize)
    {...}
    is a free function whereas

    Code:
    void myRoster::FillRoster (Student CourseRoster[], int classSize)
    is nowhere implemented.

    Man I feel like a total newb now. But I did say I needed another pair of eyes on it

    When I get back to my computer (on my girlfriends atm), I'll move forward with the program now that you've pointed out my obvious mistake.

  9. #9
    Registered User
    Join Date
    Nov 2008
    Posts
    6
    I hate to come back to this again, but I've got a bug that I can't find again. This time the program compiles and runs, but when going thru the FillRoster loop more than once, the program always skips asking for the 2nd, 3rd, 4th, etc... student name.

    Here is the (mostly) finished code:

    Student.h

    Code:
    const int STUDENT_ID = 5;
    
    // Declaration of our Student Structure
    struct Student
    {
    	char name[STUDENT_NAME];	// Stores full name of student
    	char major[STUDENT_MAJOR];	// Stores major of student
    	char year[STUDENT_YEAR];	// Stores year of student (Freshman, Sophomore, Junior, Senior)
    	int studentID;				// Unique number to identify each student
    	float GPA;					// Students Grade Point Average
    };
    
    // Declaration of our class
    class myRoster
    {
    	public:
    		void FillRoster (Student CourseRoster[], int classSize);
    		float AverageGPA (Student CourseRoster[], int classSize);
    		void OutputRoster (Student CourseRoster[], int classSize, char *pClassName, char *pClassNumber);
    		
    
    
    };
    Implementation.cpp

    Code:
    #include <iostream>
    #include <iomanip>
    
    #include "Student.h"
    
    using namespace std;
    
    
    // FillRoster will take each student in the class (in our case, 6) and
    // populate their name, their major, their student ID, and their GPA.
    void myRoster::FillRoster (Student CourseRoster[], int classSize)
    {
    	for (int i = 0; i < classSize; i++)
    	{
    		// Get Students Name
    		cout << endl << "Enter the students name. > ";
    		cin.getline(CourseRoster[i].name, STUDENT_NAME);
    		cin.ignore(cin.rdbuf()->in_avail(), '40');
    		
    		// Get Students Major
    		cout << endl << "Enter the students major. > ";
    		cin.getline(CourseRoster[i].major, STUDENT_MAJOR);
    		cin.ignore(cin.rdbuf()->in_avail(), '40');
    		
    		do
    		{
    			// Get Students Student ID. 
    			CourseRoster[i].studentID = 10000;
    			cout << endl << "Enter the students ID number (Between 10000 and 99999). > ";
    			cin >> CourseRoster[i].studentID;
    		}
    		while (CourseRoster[i].studentID < 10000 || CourseRoster[i].studentID > 99999);
    		
    		do
    		{
    			// Get Student GPA
    			cout << endl << "Enter the students GPA. > ";
    			cin >> CourseRoster[i].GPA;
    		}
    		while (CourseRoster[i].GPA < 0.0 || CourseRoster[i].GPA > 4.0);		
    	}
    	return;
    }
    
    
    float myRoster::AverageGPA (Student CourseRoster[], int classSize)
    {
    	// Declare variable to hold the average GPA
    	float avgGPA = 0.0;
    
    	for (int j = 0; j < classSize; j++)
    	{
    		avgGPA = avgGPA + CourseRoster[j].GPA;
    	}
    
    	avgGPA = avgGPA / classSize;
    
    	return avgGPA;
    }
    
    
    void myRoster::OutputRoster (Student CourseRoster[], int classSize, char *pClassName, char *pClassNumber)
    {
    	// Print out all the relevant information of the class and its students
    	cout << endl << endl << "Roster for " << pClassName << ", Course ID " << pClassNumber << " is as follows: ";
    	cout << endl << endl;
    	cout << "NAME \t\t STUDENT ID \t\t ACADEMIC MAJOR \t GPA" << endl << endl;
    	for (int k = 0; k < classSize; k++)
    	{
    		cout << CourseRoster[k].name << " \t\t " << CourseRoster[k].studentID << " \t\t\t "
    			<< CourseRoster[k].major << " \t\t\t " << CourseRoster[k].GPA << endl;
    	}
    
    
    	return;
    }
    Main.cpp

    Code:
    #include <iostream>
    #include <iomanip>
    
    #include "Student.h"
    
    using namespace std;
    
    // Constants used througout the program
    const int CLASS_SIZE = 2;	// Class/Roster size
    const int CLASS_TITLE = 41;	// Max size of a class name.  Extra space for the NULL character.
    const int CLASS_NUMBER = 9; // Max size of the class number name.  Extra space for the NULL character.
    
    int main()
    {
    	// Create my strut object
    	Student CourseRoster[CLASS_SIZE];
    
    	// Create my class object 
    	myRoster roster;
    
    	// Create variables needed by the program.  className holds the name of the class,
    	// classNumber holds the class abbreviation (CS115), avgGPA holds the average GPA
    	// of the students in the class.  pAvgGPA is a pointer to avgGPA.
    	char className[CLASS_TITLE];
    	char classNumber[CLASS_NUMBER];
    
    	char *pClassName = &className[0];
    	char *pClassNumber = &classNumber[0];
    	float *pAvgGPA = NULL;
    		
    	// Get the course name and course number from the user.  The cin.ignore lines 
    	// ensure that we only take up to the maximum number of characters allowed by that 
    	// field so that we don't accidentally try to create a course name with 60 
    	// characters or a course number with 15 characters.
    	cout << "Enter the name of the course. > ";
    	cin.getline(className, CLASS_TITLE);
    	cin.ignore(cin.rdbuf()->in_avail(), '40');
    
    	cout << endl << "Enter the course number. > ";
    	cin.getline(classNumber, CLASS_NUMBER);
    	cin.ignore(cin.rdbuf()->in_avail(), '8');
    
    	// Call the FillRoster Function
    	roster.FillRoster(CourseRoster, CLASS_SIZE);
    
    	// Calculate the Average GPA of the students
    	cout << "The average GPA for the students in " << className << "is " 
    		<< roster.AverageGPA(CourseRoster, CLASS_SIZE);
    
    	// Output the class information
    	roster.OutputRoster(CourseRoster, CLASS_SIZE, pClassName, pClassNumber);
    
    	system("pause");
    	return 0;
    }
    Output:

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Because you are mixing cin >> and cin.getline(), which leaves a newline in the input channel.

    Code:
    cin.ignore(cin.rdbuf()->in_avail(), '40');
    what is '40' supposed to represent - I doubt very much that you will EVER see a single character with that value, since even if you were to read unicode characters, that's not a valid value for a two-byte character.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Registered User
    Join Date
    Nov 2008
    Posts
    6
    Code:
    cin.ignore(cin.rdbuf()->in_avail(), '40');
    This was code given in our handout, only the '40' was replaced with 'n'. I was under the impression that this line of code was for the cin.getline function so that it only took the first 40 characters of the input in case a user tried to type more characters than the field was set to accept. I'm getting the feeling that my understanding of this line of code is way off.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. question about multidimensional arrays
    By richdb in forum C Programming
    Replies: 22
    Last Post: 02-26-2006, 09:51 AM
  2. Replies: 41
    Last Post: 07-04-2004, 03:23 PM
  3. Creating a pointer to an array of structs
    By Jonathan_ingram in forum C Programming
    Replies: 8
    Last Post: 12-31-2003, 08:49 AM
  4. array of structs initialization - PLZ help...
    By Vanya in forum C++ Programming
    Replies: 2
    Last Post: 12-11-2002, 08:10 PM
  5. Pointer to Array of Structs
    By Unregistered in forum C Programming
    Replies: 2
    Last Post: 03-06-2002, 08:34 AM