So I have this do-while loop which is supposed to repeat asking if you want to enter info for a student if you do press y and enter info via an input() function the data is then stored in a vector. If you press q, the program is supposed to print the info contained in the vector and exit the loop.
For some reason the loop fully executes for the first and second student you enter. Then instead of repeating the loop asking if you want to enter a third student it seems to just execute the input() function. It doesn't ask you 'Enter y to continue or q to quit' and any student info you enter here does not seemed to be stored. It does this intermittently changing between executing the full loop and just the input() function. I'm wondering if anyone knows why this is happening and what I can do to fix it.
Cheers
#include <iostream>
#include <iomanip>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
using namespace std;
const int NO_OF_TEST = 4;
struct studentType
{
string studentID;
string firstName;
string lastName;
string subjectName;
string courseGrade;
int arrayMarks[4];
double avgMarks;
};
studentType input();
double calculate_avg(int marks[],int NO_OF_TEST); // returns the average mark
string calculate_grade (double avgMark); // returns the grade
void main()
{
unsigned int n=0; // no. of student
vector<studentType> vec; // vector to store student info
studentType s;
char response;
do
{
cout << "\nEnter y to continue or q to quit... ";
cin >> response;
if (response == 'y')
{
n++;
for(size_t i=0; i<n; ++i)
{
s = input();
vec.push_back(s);
}
}
else if (response == 'q')
{
for (unsigned int y=0; y<n; y++)
{
cout << "\nFirst name: " << vec[y].firstName;
cout << "\nLast name: " << vec[y].lastName;
cout << "\nStudent ID: " << vec[y].studentID;
cout << "\nSubject name: " << vec[y].subjectName;
cout << "\nAverage mark: " << vec[y].avgMarks;
cout << "\nCourse grade: " << vec[y].courseGrade << endl << endl;
}
}
}
while(response!='q');
}
studentType input()
{
studentType newStudent;
cout << "\nPlease enter student information:\n";
cout << "\nFirst Name: ";
cin >> newStudent.firstName;
cout << "\nLast Name: ";
cin >> newStudent.lastName;
cout << "\nStudent ID: ";
cin >> newStudent.studentID;
cout << "\nSubject Name: ";
cin >> newStudent.subjectName;
for (int x=0; x<NO_OF_TEST; x++)
{ cout << "\nTest " << x+1 << " mark: ";
cin >> newStudent.arrayMarks[x];
}
newStudent.avgMarks = calculate_avg(newStudent.arrayMarks,NO_OF_TEST );
newStudent.courseGrade = calculate_grade (newStudent.avgMarks);
return newStudent;
}
double calculate_avg(int marks[], int NO_OF_TEST)
{
double sum=0;
for( int i=0; i<NO_OF_TEST; i++)
{
sum = sum+ marks[i];
}
return sum/NO_OF_TEST;
}
string calculate_grade (double avgMark)
{
string grade= "";
if (avgMark<50)
{
grade = "Fail";
}
else if (avgMark<65)
{
grade = "Pass";
}
else if (avgMark<75)
{
grade = "Credit";
}
else if (avgMark<85)
{
grade = "Distinction";
}
else
{
grade = "High Distinction";
}
return grade;
}
I think this code does it:
n++;
for(size_t i=0; i<n; ++i)
{
s = input();
vec.push_back(s);
}
It asks you for two students the second time, for three student the third time, etc.
So, make it
vec.push_back(input());
Related
I have this program that is barely started:
#include <iostream>
#include <iomanip>
#include <ctime>
#include <string>
using namespace std;
class Grade
{
public:
string studentID;
int userChoice = 0;
int size = 0;
double* grades = new double[size]{0};
};
void ProgramGreeting(Grade &student);
void ProgramMenu(Grade& student);
string GetID(Grade& student);
int GetChoice(Grade& student);
void GetScores(Grade& student);
int main()
{
Grade student;
ProgramGreeting(student);
ProgramMenu(student);
}
// Specification C1 - Program Greeting function
void ProgramGreeting(Grade &student)
{
cout << "--------------------------------------------" << endl;
cout << "Welcome to the GPA Analyzer! " << endl;
cout << "By: Kate Rainey " << endl;
cout << "Assignment Due Date: September 25th, 2022 " << endl;
cout << "--------------------------------------------" << endl;
GetID(student);
cout << "For Student ID # " << student.studentID << endl;
}
void ProgramMenu(Grade &student)
{
cout << "--------------------------------------------" << endl;
cout << setw(25) << "Main Menu" << endl;
cout << "1. Add Grade " << endl;
cout << "2. Display All Grades " << endl;
cout << "3. Process All Grades " << endl;
cout << "4. Quit Program." << endl;
cout << "--------------------------------------------" << endl;
GetChoice(student);
}
string GetID(Grade &student)
{
cout << "Enter the student's ID: ";
cin >> student.studentID;
if (student.studentID.length() != 8) {
cout << "Student ID's contain 8 characters ";
GetID(student);
}
return student.studentID;
}
int GetChoice(Grade &student)
{
cout << "Enter your selection: ";
cin >> student.userChoice;
if (student.userChoice == 1) {
GetScores(student);
}
else if (student.userChoice == 2)
{
}
else if (student.userChoice == 2)
{
}
else if (student.userChoice == 4)
{
exit(0);
}
else
{
cout << "Please enter 1, 2, 3 or 4" << endl;
GetChoice(student);
}
}
void GetScores(Grade &student)
{
int count = 0;
double score = 0;
cout << "How many test scores would you like to enter for ID# "
<< student.studentID << "? ";
cin >> student.size;
while (count != student.size) {
cout << "Enter a grade: ";
cin >> score;
for (int i = 0; i < student.size; i++) {
student.grades[i] = score;
}
count++;
}
for (int i = 0; i < student.size; i++) {
cout << student.grades[i] << " ";
}
}
I am trying to make sure my array is recording all test scores, but when I output the array in my GetScore function, each element in the array is the same or equal to the last score I entered. For example, if I choose 3 for size and then enter three values of 99.2 86.4 90.1, all three elements will read 90.1.
Why is this happening?
Your Grade class is allocating an array of 0 double elements (which is undefined behavior), and then your GetScores() function does not reallocate that array after asking the user how many scores they will enter, so you are writing the input values to invalid memory (which is also undefined behavior).
Even if you were managing the array's memory correctly (ie, by using std::vector instead of new[]), GetScores() is also running a for loop that writes the user's latest input value into every element of the array, instead of just writing it to the next available element. That is why your final output displays only the last value entered in every element. You need to get rid of that for loop completely.
Try something more like this instead (there are several other problems with your code, but I'll leave those as separate exercises for you to figure out):
class Grade
{
public:
...
int size = 0;
double* grades = nullptr;
};
...
void GetScores(Grade &student)
{
int size = 0;
double score = 0;
cout << "How many test scores would you like to enter for ID# " << student.studentID << "? ";
cin >> size;
if (student.size != size) {
delete[] student.grades;
student.grades = new double[size]{0};
student.size = size;
}
for(int i = 0; i < size; ++i) {
cout << "Enter a grade: ";
cin >> score;
student.grades[i] = score;
}
for (int i = 0; i < size; ++i) {
cout << student.grades[i] << " ";
}
}
Alternatively:
#include <vector>
...
class Grade
{
public:
...
vector<double> grades;
};
...
void GetScores(Grade &student)
{
size_t size = 0;
double score = 0;
cout << "How many test scores would you like to enter for ID# " << student.studentID << "? ";
cin >> size;
student.grades.resize(size);
for (size_t i = 0; i < size; ++i) {
cout << "Enter a grade: ";
cin >> score;
student.grades[i] = score;
}
/* alternatively:
student.grades.clear();
for (size_t i = 0; i < size; ++i) {
cout << "Enter a grade: ";
cin >> score;
student.grades.push_back(score);
}
*/
for (size_t i = 0; i < size; ++i) {
cout << student.grades[i] << " ";
}
}
I removed my for loop from my while loop.
void GetScores(Grade &student)
{
int count = 0;
double score = 0;
cout << "How many test scores would you like to enter for ID# "
<< student.studentID << "? ";
cin >> student.size;
while (count != student.size) {
cout << "Enter a grade: ";
cin >> score;
student.grades[count] = score;
count++;
}
for (int j = 0; j < student.size; j++) {
cout << student.grades[j] << " ";
}
}
Program:
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
//Structure
struct Student{
string name;
int pMark;
int eMark;
double avg;
string result;
};
//Functions
Student info(int arrSize, Student arrStudent[10]);
void display(int arrSize, Student arrStudents[10]);
//Main program
int main() {
Student arrStudents[10];
int arrSize;
cout << "How many Students are there(max 10): ";
cin >> arrSize;
info(arrSize, arrStudents);
display(arrSize, arrStudents);
return 0;
}
//Student Function
Student info(int arrSize, Student arrStudent[10]){
int counter = 0;
while(counter < arrSize){
cout << "\nStudent " << (counter + 1) << " info:";
cout << "\nEnter the name: ";
cin >> arrStudent[counter].name;
cout << "Enter the participation mark: ";
cin >> arrStudent[counter].pMark;
cout << "Enter the exam mark: ";
cin >> arrStudent[counter].eMark;
arrStudent[counter].avg = (arrStudent[counter].pMark + arrStudent[counter].eMark) / 2.00;
if (arrStudent[counter].avg >= 50) {
arrStudent[counter].result = "Pass";
}
else {
arrStudent[counter].result = "Fail";
}
counter++;
}
return arrStudent;//(Return Array)?
}
//Display Function
void display(int arrSize, Student arrStudents[10]) {
cout << endl << "Name\t\t Average\t\t Result" << endl;
for (int counter = 0; counter < arrSize; counter++) {
cout << arrStudents[counter].name << "\t\t"
<< fixed << setprecision(2)
<< arrStudents[counter].avg << "\t\t\t"
<< arrStudents[counter].result << endl;
}
}
I tried using the function as such, but I'm not sure if it's correct?
//Student Function
Student info(int arrSize, Student arrStudent[10]){
int counter = 0;
while (counter < arrSize) {
cout << "\nStudent " << (counter + 1) << " info:";
cout << "\nEnter the name: ";
cin >> arrStudent[counter].name;
cout << "Enter the participation mark: ";
cin >> arrStudent[counter].pMark;
cout << "Enter the exam mark: ";
cin >> arrStudent[counter].eMark;
arrStudent[counter].avg = (arrStudent[counter].pMark + arrStudent[counter].eMark) / 2.00;
if (arrStudent[counter].avg >= 50) {
arrStudent[counter].result = "Pass";
}
else {
arrStudent[counter].result = "Fail";
}
counter++;
}
return arrStudent[arrSize];
}
I'm new to coding(In University) so we still need to learn about vectors, pointers and references. That's why I haven't tried any other methods. I would highly appreciate the solutions if it is possible to solve it by avoiding those methods.
You are passing values of array by value, you should pass them by referance, thus you should use pointer,
Example function:
Student info(int arrSize, int *arrStudent)
I have the following code
for (int i = 0; i < courses; i++)
{
cout << "Please Enter Letter Grade: ";
cin >> grade1;
cout << "Please Enter Course Weighting: ";
cin >> weight1;
}
Now, lets say the loop runs 3 times and the values entered by the user for grade1 and weight1 are different each time. I want to store these different values so I can do some calculations with them. How would I proceed to do so?
Here is how use an array:
int grade[courses]; // this is an array with size of courses
double weight[courses];
for (int i = 0; i < courses; i++) {
cout << "Please Enter Letter Grade: ";
cin >> grade[i];
cout << "Please Enter Course Weighting: ";
cin >> weight[i];
}
Array is collection of data of the same type stored sequentially in computer memory. Syntax for array is as follow:
<type> <name>[<size>];
for example
int numberOfStudents[100];
is int array with maximum of 100 elements.
Hope This Helps
group grade and weight into a struct and store them in a vector.
code: (doesnt handle all potential errors)
#include <iostream>
#include <vector>
struct grade_weight
{
int grade;
int weight;
};
int main()
{
int courses = 5;
std::vector<grade_weight> result;
// potential optimization if you want
//result.reserve(courses);
for (int i = 0; i < courses; i++)
{
int grade, weight;
std::cout << "Please Enter Letter Grade: ";
std::cin >> grade;
std::cout << "Please Enter Course Weighting: ";
std::cin >> weight;
result.push_back({grade, weight});
}
std::cout << "you input\n";
for(auto& gw: result)
{
std::cout << "grade: " << gw.grade << ", weight: " << gw.weight << '\n';
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
the program works fine and executes all options, but in the 3rd and 4th option, in 3rd when i search for a student the program doesn't go beyond the data input part while in 4th when i search for data and print it, it gives garbage values in the variables with int datatype while doesn't display string or char type variables. any help would be much appreciated. EDIT: sorry for the inconvenience, I've now separated the functions form the main code. Hope its its more understandable now.
#include<iostream>
#include<string>
using namespace std;
int ncr;
int me,n=0,u,y,l;
char opt1,opt2,opt3,opt4;
struct student
{
string Name;
int DoB;
int Age;
string Address;
string Course[5];
char grade[5];
};
void add();
void remove();
void update();
void search();
int main()
{ int opt;
student s[n];
while(1)
{
cout<<" select what you want to do \n\n 1. Add new record \n2. Remove record\n3. Update Record\n4. Search for particular student\n" ;
cin>>opt;
if(opt==1)
{add();}
else if(opt==2)
{remove();}
else if(opt==3)
{update();}
else if(opt==4)
{search();}
}
}
.
void add(){
n++;
student s[n];
do
{ cout<<"enter name of student ";
cin>>s[n-1].Name;
cout<<"enter DoB of student ";
cin>>s[n-1].DoB;
cout<<"enter age of student ";
cin>>s[n-1].Age;
cout<<"enter address of student ";
cin>>s[n-1].Address;
cout<<"enter courses and grades (max 5) \n";
for(int x=0;x<5;x++){
cout<<"course:";
cin>>s[n-1].Course[x];
cout<<"grade:";
cin>> s[n-1].grade[x];}
cout<<"Roll No. : "<<n<<"\nName :"<<s[n-1].Name<<"\nDoB :"<<s[n-1].DoB<<"\nAge :"<<s[n-1].Age<<"\nAddress :"<<s[n-1].Address;
for(int x=0;x<5;x++){
cout<<"\n"<<s[n-1].Course[x];
cout<<" grade : "<< s[n-1].grade[x]<<"\n";}
cout<<"repeat for another student 'y' or 'n' ?";
cin>>opt1;
}
while(opt1=='y'|| opt1=='Y');
}
.
void remove(){student s[n];
do
{
cout<<"enter student roll no to remove data";cin>>l;
for(int i=l;i<n;i++)
{ s[l-1].Name=s[l].Name;
s[l-1].DoB= s[l].DoB;
s[l-1].Age=s[l].Age;
s[l-1].Address=s[l].Address;
for(int j=0;j<5;j++){
s[l-1].Course[j]=s[l].Course[j];
s[l-1].grade[j]=s[l].grade[j];}
}
cout<<"Record Removed\n";
n--;
cout<<"repeat ? 'y' or 'n' ";
cin>>opt2;
}
while(opt2 == 'y' || opt2 == 'Y');}
.
void update(){
student s[n];
do
{
cout<<"enter the roll no of student you want to update data";
cin>>u;
cout<<"Roll No. : "<<u;
cout<<"\nName : ";
cout<<s[u-1].Name;
cout<<"\nDoB : ";
cout<<s[u-1].DoB;
cout<<"\nAge : ";
cout<<s[u-1].Age;
cout<<"\nAddress :";
cout<<s[u-1].Address;
cout<<"\nCourses and Grades\n";
for(int r=0;r<5;r++)
{
cout<<s[u-1].Course[r];
cout<<"\t"<< s[u-1].grade[r]<<endl;
}
cout<<"enter name of student ";
cin>>s[u-1].Name;
cout<<"enter DoB of student ";
cin>>s[u-1].DoB;
cout<<"enter age of student ";
cin>>s[u-1].Age;
cout<<"enter address of student ";
cin>>s[u-1].Address;
cout<<"enter courses and grades (max 5) \n";
for(int x=0;x<5;x++){
cout<<"course:";
cin>>s[u-1].Course[x];
cout<<"grade:";
cin>> s[u-1].grade[x];}
cout<<"Roll No. : "<<u;
cout<<"\nName : ";
cout<<s[u-1].Name;
cout<<"\nDoB : ";
cout<<s[u-1].DoB;
cout<<"\nAge : ";
cout<<s[u-1].Age;
cout<<"\nAddress :";
cout<<s[u-1].Address;
cout<<"\nCourses and Grades\n";
for(int r=0;r<5;r++)
{ cout<<s[u-1].Course[r];
cout<<"\t"<< s[u-1].grade[r]<<endl; }
cout<<"repeat ? 'y' or 'n' ";
cin>>opt3;
}
while(opt3 == 'y' || opt3 == 'Y');
}
.
void search(){
student s[n];
do
{
cout<<"enter the roll no of student you want to search data of";
cin>>y;
cout<<"Roll No. : "<<n<<"\nName :"<<s[y-1].Name<<"\nDoB :"<<s[y-1].DoB<<"\nAge :"<<s[y-1].Age<<"\nAddress :"<<s[y-1].Address<<"\nCourses and Grades\n";
for(int r=0;r<5;r++)
{
cout<<s[y-1].Course[r];
cout<<"\t"<< s[y-1].grade[r]<<endl;
}
cout<<"repeat ? 'y' or 'n' ";
cin>>opt4;
}
while(opt4 == 'y' || opt4 == 'Y');}
This should look a bit more like a code intended for humans to read :)
#include<iostream>
#include<string>
using namespace std;
int ncr;
int me,n=0,u,y,l;
char opt1,opt2,opt3,opt4;
struct student
{
string Name;
int DoB;
int Age;
string Address;
string Course[5];
char grade[5];
};
void add();
void remove();
void update();
void search();
int main()
{
int opt;
student s[n];
while(1)
{
cout << " select what you want to do \n\n 1. Add new record \n2. Remove record\n3. Update Record\n4. Search for particular student\n" ;
cin >> opt;
if(opt==1)
{
add();
}
else if(opt==2)
{
remove();
}
else if(opt==3)
{
update();
}
else if(opt==4)
{
search();
}
}
}
void add()
{
n++;
student s[n];
do
{
cout << "enter name of student ";
cin >> s[n-1].Name;
cout << "enter DoB of student ";
cin >> s[n-1].DoB;
cout << "enter age of student ";
cin >> s[n-1].Age;
cout << "enter address of student ";
cin >> s[n-1].Address;
cout << "enter courses and grades (max 5) \n";
for(int x=0;x<5;x++)
{
cout<<"course:";
cin>>s[n-1].Course[x];
cout<<"grade:";
cin>> s[n-1].grade[x];
}
cout << "Roll No. : " << n << "\nName :" << s[n-1].Name << "\nDoB :" << s[n-1].DoB << "\nAge :" << s[n-1].Age << "\nAddress :" << s[n-1].Address;
for( int x = 0; x < 5; x++ )
{
cout << "\n"<<s[n-1].Course[x];
cout << " grade : "<< s[n-1].grade[x]<<"\n";}
cout << "repeat for another student 'y' or 'n' ?";
cin >> opt1;
}
while(opt1=='y'|| opt1=='Y');
}
void remove()
{
student s[n];
do
{
cout << "enter student roll no to remove data";
cin >> l;
for( int i=l; i < n; i++ )
{
s[l-1].Name=s[l].Name;
s[l-1].DoB= s[l].DoB;
s[l-1].Age=s[l].Age;
s[l-1].Address=s[l].Address;
for(int j=0;j<5;j++)
{
s[l-1].Course[j]=s[l].Course[j];
s[l-1].grade[j]=s[l].grade[j];
}
}
cout<<"Record Removed\n";
n--;
cout << "repeat ? 'y' or 'n' ";
cin >> opt2;
}
while(opt2 == 'y' || opt2 == 'Y');
}
void update()
{
student s[n];
do
{
cout << "enter the roll no of student you want to update data";
cin >> u;
cout << "Roll No. : " << u;
cout << "\nName : ";
cout << s[u-1].Name;
cout << "\nDoB : ";
cout << s[u-1].DoB;
cout << "\nAge : ";
cout << s[u-1].Age;
cout << "\nAddress :";
cout << s[u-1].Address;
cout << "\nCourses and Grades\n";
for( int r=0; r < 5; r++ )
{
cout << s[u-1].Course[r];
cout << "\t"<< s[u-1].grade[r] << endl;
}
cout << "enter name of student ";
cin >> s[u-1].Name;
cout << "enter DoB of student ";
cin >> s[u-1].DoB;
cout << "enter age of student ";
cin >> s[u-1].Age;
cout << "enter address of student ";
cin >> s[u-1].Address;
cout << "enter courses and grades (max 5) \n";
for(int x=0; x < 5; x++ )
{
cout<<"course:";
cin>>s[u-1].Course[x];
cout<<"grade:";
cin>> s[u-1].grade[x];
}
cout << "Roll No. : " << u;
cout << "\nName : ";
cout << s[u-1].Name;
cout << "\nDoB : ";
cout << s[u-1].DoB;
cout << "\nAge : ";
cout << s[u-1].Age;
cout << "\nAddress :";
cout << s[u-1].Address;
cout << "\nCourses and Grades\n";
for( int r = 0; r < 5; r++)
{
cout << s[u-1].Course[r];
cout << "\t"<< s[u-1].grade[r]<<endl;
}
cout << "repeat ? 'y' or 'n' ";
cin >> opt3;
}
while(opt3 == 'y' || opt3 == 'Y');
}
void search()
{
student s[n];
do
{
cout << "enter the roll no of student you want to search data of";
cin >> y;
cout << "Roll No. : " << n << "\nName :" << s[y-1].Name << "\nDoB :" << s[y-1].DoB << "\nAge :" << s[y-1].Age << "\nAddress :" << s[y-1].Address << "\nCourses and Grades\n";
for( int r=0; r < 5; r++ )
{
cout << s[y-1].Course[r];
cout << "\t" << s[y-1].grade[r]<<endl;
}
cout << "repeat ? 'y' or 'n' ";
cin >> opt4;
}
while( opt4 == 'y' || opt4 == 'Y' );
}
The problem you're having is with the scope of your programme.
In the main() function you declare an array, which presumably should be holding all the records. However for every option (function add/remove/update/search) you declare a new one. These arrays are local to those functions and are being "forgotten" after the function is finished.
In order to fix that, you have to pass the original array (the one from main()) to those functions.
The next problem, which is more severe is the fact, that you can't change the size of an array in the runtime! The elements you were accessing in the 3rd option were some random bytes in the memory and this can cause a lot of trouble.
Either create an array with e.g. 100 fields ( student s[100]; ), or even better try using std::vector, which can size you can adjust according to the number of records.
Third thing, remember that formatting code is extremely important. Hopefully it was just a copy-paste problem that made your code look unreadable, but if it's not the case then try to change. Well formatted code is easier to understand and will make it easier for you to debug it.
For some reason the program always crashes the second time I main calls inputHolding() and tries to get the call number (the call number is entered and then it crashes). How do I fix this crash? Here is a picture of the call stack and where it is crashing in my code: http://i.imgur.com/zWJ17NC.png
#include <iostream>
#include "LibraryDrv.h"
using namespace std;
int main() {
Holding *hptr[5];
for (int i = 0; i < 5; i++) {
hptr[i] = inputHolding();
}
for (int i = 0; i < 5; i++) {
hptr[i]->print();
}
return 0;
}
Holding* inputHolding() {
char selection;
char title[50];
int callNumber = 0;
char author[50];
char performer[50];
char format;
cout << "Enter B for book, R for recording: ";
cin >> selection;
if (selection == 'B') {
cout << "Enter book title: ";
cin >> title;
cout << "Enter book author: ";
cin >> author;
cout << "Enter call number: ";
cin >> callNumber;
Book* aBook = new Book(title, callNumber, author);
return aBook;
}
else if (selection == 'R') {
cout << "Enter recording title: ";
cin >> title;
cout << "Enter performer: ";
cin >> performer;
cout << "Enter format: (M)P3, (W)AV, (A)IFF: ";
cin >> format;
cout << "Enter call number: ";
cin >> callNumber;
Recording* aRecording = new Recording(title, callNumber, performer, format);
return aRecording;
}
else {
cout << "Incorrect selection" << endl;
return nullptr;
}
}