Sorting a two dimensional struct array [closed] - c++

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am attempting to sort a two dimensional struct array(ie. a struct array where each struct contains a struct array). My code sorts the parent struct and the struct inside the parent correctly. However, when the parent struct is swapped into its correct position the struct array inside it is reset to its original order.
NOTE: The student name must contain a first and last name(or the program will crash). Also the grade must be a capital "A", "B", "C", "D" or "F". I have to use a sorting algorithm that I write (i chose bubble sort). I can't use vectors or sort() functions etc.(This is homework)
Current Output:
Enter student name: Bob Chatter
Enter class title: Chem
Enter units for Chem: 3
Enter grade for Chem: A
Enter class title: Bio
Enter units for Bio: 3
Enter grade for Bio: B
Enter class title: Algebra
Enter units for Algebra: 4
Enter grade for Algebra: A
Enter class title:
Enter student name: Frank Brandon
Enter class title: Music
Enter units for Music: 3
Enter grade for Music: A
Enter class title:
Enter student name: Brad Anderson
Enter class title: CoSci
Enter units for CoSci: 3
Enter grade for CoSci: A
Enter class title:
Enter student name:
Student's name: Bob Chatter
Chem,A
Bio,B
Algebra,A
GPA: 3.70
Student's name: Frank Brandon
Music,A
GPA: 4.00
Student's name: Brad Anderson
CoSci,A
GPA: 4.00
Student's name: Brad Anderson
CoSci,A
GPA: 4.00
Student's name: Frank Brandon
Music,A
GPA: 4.00
Student's name: Bob Chatter
Chem,A
Bio,B
Algebra,A
GPA: 3.70
Press any key to continue . . .
Bob Chatters classes are not sorted, when I debug they are sorted correctly until the students are sorted by last name, at which point the sorting of the Classes reset.
#include <iostream>
#include <string>
#include <stdio.h>
#include <string.h>
#include <iomanip>
using namespace std;
struct Class
{
string title;
int units;
char grade;
};
struct Student
{
string name;
double gpa;
Class classes[500];
};
int const SIZE = 50;
void initStudent(Student[], int);
void readStudent(Student[], int, int&);
void gpaCalculate(Student&);
void print(Student[], int);
void stringToCharArray (string, char[]);
string returnLastName(string);
void sort_name(Student[], int);
void bubbleUpLastName(Student[],int, int);
void bubbleUpClass(Student[],int, int);
void swapStu(Student&, Student&);
void swapStusClass(Class&, Class&);
int main()
{
int numberOfStudents = 0;
Student students[SIZE];
initStudent(students, SIZE);
readStudent(students, SIZE, numberOfStudents);
for(int i = 0; students[i].name != "";i++)
gpaCalculate(students[i]);
print(students, numberOfStudents);
sort_name(students, numberOfStudents);
print(students, numberOfStudents);
system("pause");
return 0;
}
void initStudent(Student st[], int s)
{
for(int i = 0; i < s; i++)
{
st[i].gpa = 0.0;
}
}
void readStudent(Student st[], int s, int& nStus)
{
for(int i = 0; i < s; i++)
{
string tmpName;
cout << "Enter student name: ";
getline(cin, tmpName);
if(tmpName == "")
break;
st[i].name = tmpName;
nStus++;
for(int j = 0; j < 500; j++)
{
string tmpTitle;
cout << "Enter class title: ";
getline(cin, tmpTitle);
if (tmpTitle == "")
break;
st[i].classes[j].title = tmpTitle;
cout << "Enter units for " << st[i].classes[j].title << ": " ;
cin >> st[i].classes[j].units;
cout << "Enter grade for " << st[i].classes[j].title << ": " ;
cin >> st[i].classes[j].grade;
cin.ignore();
}
}
}
void gpaCalculate (Student& s)
{
double unitsByPoints = 0;
double totalUnits = 0;
for (int i = 0; s.classes[i].title != ""; i++)
{
int grade = 0;
char ltrGrade = s.classes[i].grade;
switch (ltrGrade)
{
case 'A':
grade = 4;
break;
case 'B':
grade = 3;
break;
case 'C':
grade = 2;
break;
case 'D':
grade = 1;
break;
case 'F':
grade = 0;
break;
}
unitsByPoints += s.classes[i].units*grade;
totalUnits += s.classes[i].units;
}
s.gpa = unitsByPoints/totalUnits;
}
void print(Student st[], int size)
{
for (int i = 0; i < size; i++)
{
cout << "Student's name: " << st[i].name << endl;
for (int j = 0; st[i].classes[j].title != ""; j++)
{
cout << st[i].classes[j].title << "," << st[i].classes[j].grade << endl;
}
cout << fixed << setprecision(2) << "GPA: " << st[i].gpa << endl;
}
}
// Returns the last name of the student passed in
string returnLastName(string s)
{
int i = 0;
while (s[i] != ' ')
{
i++;
}
return s.substr(i + 1, s.length() - (i + 1));
}
//sorts the students according to name and their classes according to their title
void sort_name(Student st[], int numValues)
{
int stuCurrent = 0;
int numClasses = 0;
while (stuCurrent < numValues - 1)
{
int classCurrent = 0;
for(int i = 0; st[stuCurrent].classes[i].title != ""; i++)
{
numClasses = i;
}
while (classCurrent < numClasses)
{
bubbleUpClass(st,classCurrent,stuCurrent);
classCurrent++;
}
bubbleUpLastName(st, stuCurrent, numValues-1);
stuCurrent++;
}
}
// Moves the student with the last name that should be first alphabeticaly into the first position of the Student array
void bubbleUpLastName(Student st[],int startIndex, int numValues)
{
for (int index = numValues; index > startIndex; index--)
{
if ((returnLastName(st[index-1].name).compare(returnLastName(st[index].name)) > 0))
{
swapStu(st[index], st[index-1]);
}
}
}
// Moves the Class that should be first alphabeticaly (according to title) into the first position of the Class array
void bubbleUpClass (Student st[],int startIndex, int stuIndex)
{
int numValues = 0;
for(int i = 0; st[stuIndex].classes[i].title != ""; i++)
numValues = i;
for(int index = numValues; index > startIndex; index--)
{
if(st[stuIndex].classes[index - 1].title.compare(st[stuIndex].classes[index].title))
{
swapStusClass(st[stuIndex].classes[index], (st[stuIndex].classes[index - 1]));
}
}
}
void swapStu(Student& s1, Student& s2)
{
Student tmp;
tmp = s1;
s1 = s2;
s2 = tmp;
}
void swapStusClass(Class& c1, Class& c2)
{
Class tmp;
tmp = c1;
c1 = c2;
c2 = tmp;
}
/*
Define a structure called Class (with uppercase C) with the following data:
title, units and grade.
Define a structure called Student with the following data:
name (full name), gpa, and classes which is an array of Class structures (all the classes the student has taken so far).
Write an initialize function that receives an array of Student structures and its size and sets the gpa of all to 0.0.
In main, create 50 Students and call the above function to initialize the gpa for all 50 Students to 0.0.
Then, pass the array of student structures and its size to a read function that will read student data from the user and store the entered data in the array of student structures. The user will enter student name followed by the class title, units and grade received for each class he or she has taken. When finished entering class information for a student, the user will just press Enter (an empty string) and to end entering more students, he or she will do the same for the student name.
Example:
Enter student name: Maria Gomez
Enter class title: English 101
Enter units for English 101: 3
Enter grade for English 101: A
Enter class title: Math 201
Enter units for Math 201: 4
Enter grade for Math 201: B
Enter class title: [User enters RETURN to indicate no more classes]
Enter student name: Kevin Duran
Enter class title: Poly Sci 101
Enter units for Poly Sci 101: 3
Enter grade for Poly Sci 101: A
Enter class title: Math 201
Enter units for Math 201: 4
Enter grade for Math 201: B
Enter class title: [User enters RETURN to indicate no more classes]
Enter student name: [User enters RETURN to indicate no more students]
Once all Studnets have been entered, pass each element of the array of Student structures (element by element) to a gpa function which will compute and return the gpa for each Student using the classes array within each Student structure which contains the units and grade for each class taken by the student. Store the gpa returned by the above function in the gpa member of the Student structures. GPA is calculated by multiplying the number of units for each class by the points received for that class, and then adding all these products together and dividing it by total number of units. The points received for a class is based on the grade: for A, it's 4; for B, it's 3; for C, it's 2; for D it's 1; and for F it's 0. For example, if a student has take 3 classes with 3, 4, and 3 units and has received A, B, and C for these classes, respectively, then, the GPA will be 3 x 4 + 4 x 3 + 3 x 2 / 10 = 3.0.
Print all students showing name, followed by all classes taken, the grade received and the gpa using a display function which receives the array and its size as parameters.
Then, using a sort_name function, sort the student structures based on their last names and for each student, sort the classes he or she is taking based on class title. Display the sorted list of students using the display function by calling it from main.
For example:
Kevn Duran
Poly Sci 101, A
Math 150, B
GPA: 3.0
Maria Gomez:
English 101, A
Math 201, C
GPA: 2.9
Robert Small
Comp Science 801, C
Comp Science 802, D
GPA: 1.9
Tom Wang
Comp Science 808, A
Comp Science 839, B
GPA: 3.5
Then, sort the students based on their GPA's using a sort_gpa function and print the list again using the display function.
Then, ask what to search for - name or gpa. If name is selected, read a student name from the user and, using a binary search function that takes the array, its size and the name to search for, finds the student and displays all of his or her information (name, gpa, units and list of classes taken).
Example:
Enter a student name: Robert Small
Robert Small:
Comp Science 801, C
Comp Science 802, B
GPA: 2.5
If GPA is selected, read a GPA and using another binary search find the student with the given GPA by passing the students array, its size and the GPA to search for. Display the name of the student with the specified GPA in main.
Example:
Enter GPA to search for: 2.5
Robert Small was found with the GPA of 2.5
If the name or GPA is not found, tell the user it was not found; e.g.: There was no student with a GPA of 2.5; or Robert Small was not found.
Then, pass the array of student atructures and the size to a stats function which will return the average of the GPA's of all students and through two reference parameters will output the student structures that have the minimum and maximum GPA's. Print the average GPA, as well as the names of the students who have the minimum and maximum GPA in main, like so:
Average GPA = 3.17
Robert Small has the minimum GPA of 2.5.
Tom Wang has the maximum GPA of 3.5.
Finally, read a maximum and minimum GPA from the user and pass the array of student structures and its size, as well as two other arrays of student structures of the same size to a function which will store all students with a GPA of above the minimum in the highGPA array and all those with a GPA below the maximum in the lowGPA array. Display the students stored in these two arrays by passing them each from main to the display function. In other words, the highlow function receives two uninitalized arrays of student structures and populates them based on the GPA criteria passed to it (minimum GPA and maximum GPA). Then, upon return to main, main passes each of these arrays to the display function to display them. For example, if the user enters 2.0 for the maximum GPA, the lowGPA array gets filled out with all those students who have a GPA of less than 2.0. Likewise, if the minimum GPA is 3.5, the highlow function populates the highGPA array with those students who have a GPA of 3.5 or higher.
Example:
Enter maximum GPA: 2.0
Enter minimum GPA: 3.5
Students with a GPA of lower than 2.0:
Robert Small 1.9
Students with a GPA of 3.5 or higher:
Tom Wang 3.5
When writing the highlow function, take advantage of the fact that the array elements are sorted based on the GPA, so to find all the students with a GPA of equal to or higher than the minimum GPA, it doesn't make sense to start from the first element in the array. Instead you can start from the midpoint. If the midpoint is lower than the minimum GPA, you can increment the index until the midpoint is no longer smaller and then all the GPA's from that point on will be larger and part of the high GPA's. For low GPA's of course, you'd want to start from the beginning of the array and compare and store each that's lower than the maximum until they are no longer lower.
Functions you must write for this assignment (in addition to main):
initialize, read, display, sort_name, sort_gpa, search-name, search_gpa, stats, highlow.
Upload your cpp and exe files using the Browse and Upload buttons below and click Finish once both have been uploaded to the site.*/
What is causing the struct array inside the parent struct to be reset?

When comparing Class::title you forgot to add comparison to compare value:
Your line:
if(st[stuIndex].classes[index - 1].title.compare(st[stuIndex].classes[index].title))
Should be:
if(0 < st[stuIndex].classes[index - 1].title.compare(st[stuIndex].classes[index].title))
I say you forgot - because you have this explicit comparison in your function to sort students.
Now explanation of your result: at first, just by chance - the classes for some student are sorted, but after that position of your student changes (this is bubble sort) and next sorting is done on these classes - so because actually you don't sort classes, but just changes its positions, you can have their original sequence in next step.
As a bonus I advice not to use compare for sorting - just use operator <:
if(st[stuIndex].classes[index - 1].title < st[stuIndex].classes[index].title)
much simpler, isn't it?

Related

c++ User input validation in sorted array

Hello i have a assinment that im making a weater program where we ask the user to enter info
first enter how many citys to use
then enter city name and degrees
then i will print out the list in order starting with the coldest city
and last i need to add a search funkar to search by degrees to find a location with that degrees
this one i havent started with
but my MAIN problem is that i need to validate that the user input is between -60 and 60 when enter the city and degrees... i just dont get it to work with anything... can someone please help out?`
cout<<"Enter Name of City and degrees \n\n";
for(i=0;i<n;i++){
cout<<"---------\n";
cin>>s_array[i].name;
cin>>s_array[i].degrees;
this is the code where user put in city and degree EX Rio 50
i just dont know how to validate it to be between -60 and 60`
What you're looking for, is simple data validation.
Assuming you have a struct City:
// used to hold the data
struct City {
string name;
double degrees;
};
and in your main(), you have initialised an array of these structs:
bool temperatureValid(const City);
int main() {
const int32_t totalCities = 12;
City cities[totalCities];
for (int32_t i = 0; i < totalCities; i++) {
// add data to structs
cout << "Enter city name: ";
cin >> cities[i].name; // you might want to validate this, too
cout << "Enter temperature: ";
cin >> cities[i].degrees;
cout << cities[i].name << " has a temperature of " << cities[i].degrees << "°" << endl;
if (temperatureValid(cities[i])) {
// cool... or not
} else {
cerr << "Invalid temperature range!" << endl;
--i; // make sure we can do this one again
continue;
}
}
return 0;
}
bool temperatureValid(const City city) {
return city.degrees >= -60 && city.degrees <= 60;
}
First of all, you should create a class. I understand from your code you must use class. If you don't have to it is easier than this. Then you should create an object.
Basic logic below here. You should create a class well.
class Weather //create class
Weather city // create object
cout<<"Please enter a city name:"<<endl;
cin>>city.name;
cout<<"Please enter a city degree:"<<endl;
cin>>city.degrees;

Create a structure that contains a pointer to an array

I CAN NOT USE VECTORS FOR THE ASSIGNMENT
I have to create a structure that stores the following information: student name, id number, pointer to an array of test scores, average test score, letter grade.
The program should keep a list of test scores for a group of students. It should ask the user how many students are in the class and how many test scores there are.The number of test scores will be the same for every student. The program should dynamically allocate an array of structures. Each structures Tests member should point to a dynamically allocated array which will hold the test scores.
After the arrays have been dynamically allocated, the program should ask the user for the id number and all of the test scores for each student. The average score should be calculated and stored in the Average member of the structure. Display the student info.
I am having trouble when the user enters the test scores in the inputScores function. I can't figure out how to access the structure member right. Can you please look at my code and help me figure out what I'm doing wrong?
Here is my structure:
struct Grade
{
string name;
int idNum;
int* tests;
double average;
char grade;
};
Here are my functions:
//user enters number of students which is then used as the size of the dynamically allocated struct array
int inputStudents();
//user enters number of tests for each student which is then used as the size of the dynamically allocated array of test scores in the structure
int inputTests();
string inputName();
int inputID();
//user inputs scores for each student. this is a function i'm struggling with
int *inputScores(int *testScores, int numTests);
double calcAvg(int *testScores, int numTests);
char calcGrade(double);
void display(Grade*, int);
Here is my main:
int main()
{
Grade *studentList;
int size = inputStudents();
studentList = new Grade[size]; //dynamically create array of Grade struct
int numTests = inputTests(); //number of test scores stored in numTests
for (int i = 0; i < size; i++) //loop to store all student's info
{
studentList[i].name = inputName();
studentList[i].idNum = inputID();
studentList[i].tests = inputScores(studentList[i].tests, numTests, i);
studentList[i].average = calcAvg(studentList[i].tests, numTests);
studentList[i].grade = calcGrade(studentList[i].average);
}
display(studentList, size);
delete[] studentList;
return 0;
}
Here is the function i am struggling with. Every time I reference studentList a different error appears. My program won't even compile and I'm pretty sure this function is the reason why. Here I pass the tests structure member, rather than the entire structure. I also pass the number of tests and the counter from the loop in main that tells us which student the user is entering the test scores for.
int *inputScores(int *studentList, int numTests, int count)
{
cout << endl;
cout << "Enter the test scores:\n";
for (int i = 0; i < numTests; i++)
{
studentList[count].tests = new int[numTests]; //my error says the studentList must have a class type
cout << "Score " << (i + 1) << ": ";
cin >> studentList[count]->tests[i]; //my error says studentList must have a pointer type
cout << endl;
}
return studentList->tests; //my error says studentList must have a point-to-class type
}
You are passing a pointer to each student's test array to inputScores() but accessing it as a pointer to a student. You would have to change the inputScores() function as given below:
void inputScores(int *tests, int numTests, int count)
{
cout << endl;
cout << "Enter the test scores:\n";
for (int i = 0; i < numTests; i++)
{
cout << "Score " << (i + 1) << ": ";
cin >> tests[i];
cout << endl;
}
}
Also, I made one more modification. Its always better if the caller function allocates memory and pass a reference to the array. So we need to call the inputScores() function as given below
studentList[i].tests = new int[numTests];
inputScores(studentList[i].tests, numTests, i);
This is the output I received:
How many students are there?
3
How many tests does each student have?
2
Enter the student's name:
Joohn
Enter the student's ID number:
1
Enter the test scores:
Score 1: 12
Score 2: 13
Enter the student's name:
Jack
Enter the student's ID number:
2
Enter the test scores:
Score 1: 67
Score 2: 45
Enter the student's name:
Jill
Enter the student's ID number:
3
Enter the test scores:
Score 1: 56
Score 2: 89
--------------------------------------------------------
Here is all the info I have for each student:
Student #1:
Name: Joohn
ID Number: 1
Test Scores: Average Grade: 12
Letter Grade: F
Student #2:
Name: Jack
ID Number: 2
Test Scores: Average Grade: 56
Letter Grade: F
Student #3:
Name: Jill
ID Number: 3
Test Scores: Average Grade: 72
Letter Grade: C
--------------------------------------------------------
Your function inputScores is declared like this
int *inputScores(int *studentList, int numTests, int count)
which means studentList is a pointer to an int (which can be treated like an array). Later in the function, you attempt to do this:
studentList[count].tests = new int[numTests];
If studentList is an int* (or int array), then studentList[count] is just an int. You're trying to access the member variable tests of an int. But int is a primitive type.
When you called this function in main, you correctly passed an int*:
studentList[i].tests = inputScores(studentList[i].tests, numTests, i);
So treating the variable like it were actually an int * instead of a Grade * should solve the first of your problems. You should also change the name of the variable, since you're not really passing a studentList, it's more of a tests variable. That should help cut down on some of the confusion.
int *inputScores(int *tests, int numTests, int count)
After that, you'll realize that even through you're passing studentList[i].tests to your inputScores function, you'll have a memory leak and not be able to access the memory you thought you just filled. You DID fill memory, but when you tried to assign a new value to tests via tests = new int[numTests];, that only changed the local copy of tests.
To fix THAT problem, you need to pass tests by reference, like this:
int *inputScores(int*& tests, int numTests, int count)
That will allow any changes you make in your function to the int*, tests, to persist outside of the function.

Increasing class pointer array

In my code, I want to add one student info into my class pointer array and the array size will increase each time a new student is added. Here is my code:
My header file:
class Student{
public:
int studentID;
char studentName[20];
int currentEnrollment;
Student();
void AddStudent(Student *tempStudent[], int countStudent, int sizeOfArray);}
My Class definition file:
void Student::AddStudent(Student *tempStudent[], int countStudent, int sizeOfArray)
{
for (int i = countStudent; i < sizeOfArray; i++)
{
cout << "Please enter student id (4 digits only): ";
cin >> tempStudent[i]->studentID;
cout << "Please enter student name: ";
cin >> tempStudent[i]->studentName;
}
}
My Main.cpp file
int *totalStudent = new int;
*totalStudent = 1;
int i, j, countStudent = 0;
int sizeOfArray = *totalStudent;
Student *newStudent[*totalStudent];
//Each time a new student is added, I will allocate a new memory for the array element, then add student Info using function.
for (i = countStudent; i < *totalStudent; i++)
{
newStudent[i] = new Student;
newStudent[i]->AddStudent(newStudent, countStudent, sizeOfArray);
countStudent++;
*totalStudent++;
}
When I run my code, I get an undefined reference error, so I do not know If I am able to increase my array or not. I intend to use C++ syntax so I use new and delete. Thank you for your help.
P.S: Here is my new code and it runs great, the only missing is the studentID for the first element in array.
In my main class:
int numStudent = 0;
int i, j, countStudent = 1;
Student *newStudent = new Student[countStudent];
AddStudent(newStudent, countStudent, numStudent);
My Student.h
class Student{
public:
int studentID;
char studentName[20];
int currentEnrollment;
};
Student AddStudent(Student *newStudent, int &countStudent, int &numStudent);
and My Student.cpp
Student AddStudent(Student *newStudent, int &countStudent, int &numStudent)
{
Student tempStudent;
cout << "Please enter student id (4 digits only): ";
cin >> tempStudent.studentID;
cout << "Please enter student name: ";
cin >> tempStudent.studentName;
newStudent[numStudent] = tempStudent;
numStudent++;
if (numStudent == countStudent)
{
Student *newStudentSize = new Student[countStudent + 1];
for (int i = 0; i < numStudent; i++)
{
newStudentSize[i] = newStudent[i];
}
delete []newStudent;
return *newStudentSize;
countStudent += 1;
}
}
Running this code will give me the following result:
StudentID: 11
StudentName: Dat
StudentID: 23
StudentName: Michael
Printing:
StudentID: 0
StudentName: Dat
StudentID: 23
StudentName: Michael
While it doesn't make sense to increase the array for each new student (it's inefficient) here's one way you can do it (I didn't even try to make your code compile because it has a number of issues and is unnecessarily complicated). Note that tempStudent (in the code snippet below) doesn't even have to be created using new. This solution stores Student objects in the students array (although it's easy to modify it to store Student object pointers instead). That said, usually, you'll just want to create an array of large enough size to accomodate all students (just set studentCount to some appropriate number and not 1 like in the example below).
class Student{
public:
int studentID;
char studentName[20];
int currentEnrollment;
Student(){};
};
int main(){
int studentCount=1;
Student * students = new Student[studentCount];
int numStudents=0;
bool done=false;
char finished='N';
while (!done){
//Student *tempStudent = new Student();
//create a Student on the stack
Student tempStudent;
cout << "Please enter student id (4 digits only): ";
//No input checking is done here
cin >> tempStudent.studentID;
No input checking is done here
cout << "Please enter student name: ";
cin >> tempStudent.studentName;
students[numStudents] = tempStudent;
numStudents++;
cout << "Stop entering students: Y or N";
cin >> finished;
done = finished=='Y' or finished=='y' ? true : false;
if(numStudents==studentCount){
students = ReallocateStudents(students, studentCount, studentCount*2);
studentCount *= 2;
}
}//end while
//print the students info
for(int i=0;i<numStudents;i++){
Student st = students[i];
cout << st.studentID << " " << st.studentName << std::endl;
}
//deallocate the students array or if you place this in the main like you did, the program will exit immediately so there's no need to deallocate
return 0;
}
Student * ReallocateStudents(Student* st, int oldSize, int newSize){
Student * newStudents = new Student[newSize];
//copy the existing values from the old array to the new one
for(int i=0;i<oldSize;i++){
newStudents[i] = st[i];
}
delete [] st; //delete the old array
return newStudents;
}
UPDATE:
Since you don't want to do everthing in the main(), just create a free AddStudents function and do everything there. Alternatively, you can create a
static function inside the Student class. It makes no sense to create AddStudent as a member of Student because that would require you to use an instance of Student to add a new instance, which makes for poor design (not to mention technical issues etc).
int main(){
// some code here
Students * allStudents = AddStudents();
//print students
}//end main
Students * AddStudents(){
int studentCount=1;
Student * students = new Student[studentCount];
int numStudents=0;
bool done=false;
char finished='N';
while (!done){
//create a Student on the stack
Student tempStudent;
cout << "Please enter student id (4 digits only): ";
//No input checking is done here
cin >> tempStudent.studentID;
No input checking is done here
cout << "Please enter student name: ";
cin >> tempStudent.studentName;
students[numStudents] = tempStudent;
numStudents++;
cout << "Stop entering students: Y or N";
cin >> finished;
done = finished=='Y' or finished=='y' ? true : false;
if(numStudents==studentCount){
students = ReallocateStudents(students, studentCount,
studentCount*2);
studentCount *= 2;
}
}//end while
return students;
}
This is simple and easy to both understand and maintain so I suggest using this approach.
addStudent does not do anything with the Student object it belongs to. So there is no need to put it in the 'Student' class. (Or you could rather rewrite it so it does something with the student object it belongs to). And it currently does not "add" anything, so the name is confusing.
What is technically wrong with it depends on what you want it to do. Currently it initializes student objects expected to already exist and pointed to by an array, from a specific array index, to the end of the array. That could well be a useful function, if that is what you want it to do. But you then must call it correctly with an array of pointers that point to valid Student objects, which you currently do not.
Currently in main you have a loop that initializes pointers in an array. And each time you initialize a pointer, you call AddStudent(..). The problem is that 'AddStudent()' tries to initialize ALL the student pointed to by your array.
This has two major problems (In addition to all the other problems with your loop).
Each time you create a new student, all your existing students will be
initialized again with new input from std::cin. (So for n students, you will
try to do n*n initializations)
While the loop in main is running, not all pointers in your array points
to existing Student objects. This may result in important data being
overwritten, a program crash or something totally different and unexpected.
You should sit back and reevaluate how you want to do things. Trying to fix single bugs in your existing code, one after another, will just create more bugs.
Just a hint to get you started:
class Student
{
public:
int studentID;
char studentName[20];
int currentEnrollment;
Student();
void init_from_cin();
};
And in your class definition file:
void Student::init_from_cin()
{
cout << "Please enter student id (4 digits only): ";
cin >> studentID;
cout << "Please enter student name: ";
cin >> studentName;
}
If you create a new Student like this:
Student *new_student = new Student;
new_student->init_from_cin();
Then after calling init_from_cin(), the Student object pointed to by new_student should be initialized.
How to create and initialize multiple Student objects in a loop, is left as exercise for the reader. But when you do it, you should understand what your lower and upper bounds of your loop are supposed to be. And you should also understand why moving the upper bound further away while your loop is running is a bad idea.
And never forget that sane programming languages start array indexing with 0.

Sorting Array's of Structs

I am working on an assignment for my C++ class (the assignment is pasted at the bottom of my test.cpp file). I implemented everything correctly up until the last requirement (using a sort_name function, sort the student structures based on their last names and for each student, sort the classes he or she is taking based on class title. Display the sorted list of students using the display function by calling it from main). I have attempted to implement my sort function by sorting just the students at first, but I keep getting errors and getting stuck(The current error is: Unhandled exception at 0x777a15de in 839a4 Vasilkovskiy.exe: 0xC00000FD: Stack overflow). Any help would be greatly appreciated.
NOTE: I understand that vectors are much more useful for sorting, but our professor does not want us to use them.
#include <iostream>
#include <string>
#include <stdio.h>
#include <string.h>
#include <iomanip>
using namespace std;
struct Class
{
string title;
int units;
char grade;
};
struct Student
{
string name;
double gpa;
Class classes[500];
};
int const SIZE = 50;
void initStudent(Student[], int);
void readStudent(Student[], int, int&);
void gpaCalculate(Student&);
void print(Student[], int);
void sort_name(Student[], int);
void swapStus(Student&, Student&);
void stringToCharArray(string, char[]);
int locactionOfFirstName(Student[], int, int);
int main()
{
int numberOfStudents = 0;
Student students[SIZE];
initStudent(students, SIZE);
readStudent(students, SIZE, numberOfStudents);
for(int i = 0; students[i].name != "";i++)
gpaCalculate(students[i]);
print(students, numberOfStudents);
sort_name(students, numberOfStudents);
system("pause");
return 0;
}
void initStudent(Student st[], int s)
{
for(int i = 0; i < s; i++)
{
st[i].gpa = 0.0;
}
}
void readStudent(Student st[], int s, int& nStus)
{
for(int i = 0; i < s; i++)
{
string tmpName;
cout << "Enter student name: ";
getline(cin, tmpName);
if(tmpName == "")
break;
st[i].name = tmpName;
nStus++;
for(int j = 0; j < 500; j++)
{
string tmpTitle;
cout << "Enter class title: ";
getline(cin, tmpTitle);
if (tmpTitle == "")
break;
st[i].classes[j].title = tmpTitle;
cout << "Enter units for " << st[i].classes[j].title << ": " ;
cin >> st[i].classes[j].units;
cout << "Enter grade for " << st[i].classes[j].title << ": " ;
cin >> st[i].classes[j].grade;
cin.ignore();
}
}
}
void gpaCalculate (Student& s)
{
double unitsByPoints = 0;
double totalUnits = 0;
for (int i = 0; s.classes[i].title != ""; i++)
{
int grade = 0;
char ltrGrade = s.classes[i].grade;
switch (ltrGrade)
{
case 'A':
grade = 4;
break;
case 'B':
grade = 3;
break;
case 'C':
grade = 2;
break;
case 'D':
grade = 1;
break;
case 'F':
grade = 0;
break;
}
unitsByPoints += s.classes[i].units*grade;
totalUnits += s.classes[i].units;
}
s.gpa = unitsByPoints/totalUnits;
}
void print(Student st[], int size)
{
for (int i = 0; i < size; i++)
{
cout << "Student's name: " << st[i].name << endl;
for (int j = 0; st[i].classes[j].title != ""; j++)
{
cout << st[i].classes[j].title << "," << st[i].classes[j].grade << endl;
}
cout << fixed << setprecision(2) << "GPA: " << st[i].gpa << endl;
}
}
//void sort_name(Student st[], int size)
//{
// for(int i = 0; i < size; i++)
// {
// int smallest = locactionOfFirstName(st, i, size);
// swapStus(st[i], st[smallest]);
// }
//
//}
void swapStus(Student& s1, Student& s2)
{
Student tempStu;
tempStu = s1;
s1 = s2;
s2 = tempStu;
}
void stringToCharArray(string s, char c[])
{
char tempCharArray[50];
for(int i = 0; s[i] != '\n'; i++)
{
tempCharArray[i] = s[i];
}
char * space = strstr(tempCharArray," ");
strcpy(c,space);
}
bool lastNameCompare(string l1, string l2)
{
char lName1[50];
char lName2[50];
stringToCharArray(l1, lName1);
stringToCharArray(l2, lName2);
return (strcmp(lName1, lName2) >=0);
}
int locactionOfFirstName(Student st[],int start, int size)
{
char lName1[50];
char lName2[50];
stringToCharArray(st[0].name, lName1);
int i;
for(i = start; i < size;)
{
stringToCharArray(st[i].name, lName2);
if(strcmp(lName1, lName2) >= 0 )
{
stringToCharArray(st[i].name, lName1);
}
}
return i;
}
void InsertItem(Student values[], int startIndex, int endIndex)
{
bool finished = false;
int current = endIndex;
bool moreToSearch = (current != startIndex);
while (moreToSearch && !finished)
{
if (lastNameCompare(values[current-1].name, values[current].name))
{
swapStus(values[current], values[current-1]);
current--;
moreToSearch = (current != startIndex);
}
else
finished = true;
}
}
void sort_name(Student values[], int numValues)
{
for (int count = 0; count < numValues; count++)
InsertItem(values, 0, count);
}
/*
Define a structure called Class (with uppercase C) with the following data:
title, units and grade.
Define a structure called Student with the following data:
name (full name), gpa, and classes which is an array of Class structures (all the classes the student has taken so far).
Write an initialize function that receives an array of Student structures and its size and sets the gpa of all to 0.0.
In main, create 50 Students and call the above function to initialize the gpa for all 50 Students to 0.0.
Then, pass the array of student structures and its size to a read function that will read student data from the user and store the entered data in the array of student structures. The user will enter student name followed by the class title, units and grade received for each class he or she has taken. When finished entering class information for a student, the user will just press Enter (an empty string) and to end entering more students, he or she will do the same for the student name.
Example:
Enter student name: Maria Gomez
Enter class title: English 101
Enter units for English 101: 3
Enter grade for English 101: A
Enter class title: Math 201
Enter units for Math 201: 4
Enter grade for Math 201: B
Enter class title: [User enters RETURN to indicate no more classes]
Enter student name: Kevin Duran
Enter class title: Poly Sci 101
Enter units for Poly Sci 101: 3
Enter grade for Poly Sci 101: A
Enter class title: Math 201
Enter units for Math 201: 4
Enter grade for Math 201: B
Enter class title: [User enters RETURN to indicate no more classes]
Enter student name: [User enters RETURN to indicate no more students]
Once all Studnets have been entered, pass each element of the array of Student structures (element by element) to a gpa function which will compute and return the gpa for each Student using the classes array within each Student structure which contains the units and grade for each class taken by the student. Store the gpa returned by the above function in the gpa member of the Student structures. GPA is calculated by multiplying the number of units for each class by the points received for that class, and then adding all these products together and dividing it by total number of units. The points received for a class is based on the grade: for A, it's 4; for B, it's 3; for C, it's 2; for D it's 1; and for F it's 0. For example, if a student has take 3 classes with 3, 4, and 3 units and has received A, B, and C for these classes, respectively, then, the GPA will be 3 x 4 + 4 x 3 + 3 x 2 / 10 = 3.0.
Print all students showing name, followed by all classes taken, the grade received and the gpa using a display function which receives the array and its size as parameters.
Then, using a sort_name function, sort the student structures based on their last names and for each student, sort the classes he or she is taking based on class title. Display the sorted list of students using the display function by calling it from main.
For example:
Kevn Duran
Poly Sci 101, A
Math 150, B
GPA: 3.0
Maria Gomez:
English 101, A
Math 201, C
GPA: 2.9
Robert Small
Comp Science 801, C
Comp Science 802, D
GPA: 1.9
Tom Wang
Comp Science 808, A
Comp Science 839, B
GPA: 3.5
Then, sort the students based on their GPA's using a sort_gpa function and print the list again using the display function.
Then, ask what to search for - name or gpa. If name is selected, read a student name from the user and, using a binary search function that takes the array, its size and the name to search for, finds the student and displays all of his or her information (name, gpa, units and list of classes taken).
Example:
Enter a student name: Robert Small
Robert Small:
Comp Science 801, C
Comp Science 802, B
GPA: 2.5
If GPA is selected, read a GPA and using another binary search find the student with the given GPA by passing the students array, its size and the GPA to search for. Display the name of the student with the specified GPA in main.
Example:
Enter GPA to search for: 2.5
Robert Small was found with the GPA of 2.5
If the name or GPA is not found, tell the user it was not found; e.g.: There was no student with a GPA of 2.5; or Robert Small was not found.
Then, pass the array of student atructures and the size to a stats function which will return the average of the GPA's of all students and through two reference parameters will output the student structures that have the minimum and maximum GPA's. Print the average GPA, as well as the names of the students who have the minimum and maximum GPA in main, like so:
Average GPA = 3.17
Robert Small has the minimum GPA of 2.5.
Tom Wang has the maximum GPA of 3.5.
Finally, read a maximum and minimum GPA from the user and pass the array of student structures and its size, as well as two other arrays of student structures of the same size to a function which will store all students with a GPA of above the minimum in the highGPA array and all those with a GPA below the maximum in the lowGPA array. Display the students stored in these two arrays by passing them each from main to the display function. In other words, the highlow function receives two uninitalized arrays of student structures and populates them based on the GPA criteria passed to it (minimum GPA and maximum GPA). Then, upon return to main, main passes each of these arrays to the display function to display them. For example, if the user enters 2.0 for the maximum GPA, the lowGPA array gets filled out with all those students who have a GPA of less than 2.0. Likewise, if the minimum GPA is 3.5, the highlow function populates the highGPA array with those students who have a GPA of 3.5 or higher.
Example:
Enter maximum GPA: 2.0
Enter minimum GPA: 3.5
Students with a GPA of lower than 2.0:
Robert Small 1.9
Students with a GPA of 3.5 or higher:
Tom Wang 3.5
When writing the highlow function, take advantage of the fact that the array elements are sorted based on the GPA, so to find all the students with a GPA of equal to or higher than the minimum GPA, it doesn't make sense to start from the first element in the array. Instead you can start from the midpoint. If the midpoint is lower than the minimum GPA, you can increment the index until the midpoint is no longer smaller and then all the GPA's from that point on will be larger and part of the high GPA's. For low GPA's of course, you'd want to start from the beginning of the array and compare and store each that's lower than the maximum until they are no longer lower.
Functions you must write for this assignment (in addition to main):
initialize, read, display, sort_name, sort_gpa, search-name, search_gpa, stats, highlow.
Upload your cpp and exe files using the Browse and Upload buttons below and click Finish once both have been uploaded to the site.*/
I debugged it for you.
The problem is in your stringToCharArray(string s, char c[]).
My index i arrived to 104 before getting "segmentation fault". Since all your strings have length 50 you are clearly going out of bounds.
Another problem is in srtstr that returns NULL, but this is related to the first problem.
A quick look to your sort_name and InsertItem didn't show up anything wrong, at least in the field of "segmentation error", since it's not so clear what you are trying to do, but at least you are performing the right index checks.

How to input values after for loop in C++?

I have to make a program which inputs 10 student's grades and displays their weighed and unweighted averages. I am new to C++ programming so I don't know much and my professor doesn't like it when people use things he hasn't taught.
Here's the code: It shows up as What are the four test scores of student 1,2, etc. How can I make it to be when it says "What are the four test scores of student 1", then I would be able to enter those in. And then on to student2, student3, etc?
Thank you for your time.
#include <iostream>
using namespace std;
const int numberofstudents = 10;
int main()
{
int student;
for(student=1; student<=numberofstudents; student++)
cout << "\nWhat are the four test scores of student number " << student << endl;
return 0;
}
I think you want to read four values for each students, if so , then understand this code:
#include <iostream>
using namespace std;
int main()
{
const int numberofstudents = 10;
double scores[numberofstudents][4];
for(int student=0; student<numberofstudents; student++)
{
cout << "\nWhat are the four test scores of student number " << (student+1) << endl;
int i = 0;
while ( i < 4 )
{
//scores is a two dimentional array
//scores first index is student number (starting with 0)
//and second index is ith score
cin >> scores[student][i]; //read score, one at a time!
i++;
}
}
//process scores...
}
Now since it's your homework, do the rest of your work yourself. All the best!