I'm trying to make a program and while I'm making it I'm learning classes, inheritance and things I'll need. I'll give you the condition of the program and the code to where I got to.
The 2nd class I made it inherit the 1st, but I can't get the console to return the student's grade. Тhe condition they gave me confuses me and I can't figure out how they want to calculate the student's grade? Thanks in advance for your time and kindness :)
I. Define a student class CStudent storing name information,
student's faculty number and major to provide:
Create objects using a copy constructor
Creation of objects by explicit constructor (with parameters)
Using an implicit constructor
Assignment operator =
Comparison operator ==
Comparison operator < (by faculty number)
To read student data from stream input - operator>>
To output the student data to stream output - operator<<
Establish the member variables (mutators)
Reading the member variables (accessors)
II. Define a student booklet class CStudBook that inherits
CStudent with a member data container of the student's grades. To implement
a constructor with a filename parameter from which to initialize
container and the following methods:
Create an object using another object (copy constructor)
Creating an object using explicit parameters
Creating an object by default constructor
Calculate and return the student's grade point average
operator>>
operator<<
Print
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
using namespace std;
class CStudent {
public:
// Default constructor
CStudent() = default;
// Explicit constructor
CStudent(string name, int facnum, string specialty) {
this->name = name;
this->facnum = facnum;
this->specialty = specialty;
}
// Copy constructor
CStudent(const CStudent& obj) {
this->name = obj.name;
this->facnum = obj.facnum;
this->specialty = obj.specialty;
}
// Method, that prints the contents of the object
void PrintStudent() const {
cout << "Name: " << name << endl;
cout << "Fac. num: " << facnum << endl;
cout << "Specialty: " << specialty << endl;
}
friend std::ostream& operator <<(std::ostream& out, const CStudent& obj) // output operator
{
out << "Name:" << obj.name << "-> FacNumber: " << obj.facnum << std::endl;
}
bool operator <(const CStudent& obj) // operator for comparison of two objects
{
return name < obj.name;
return facnum < obj.facnum;
}
// operator login should be added here
private:
string name;
int facnum;
string specialty;
};
class CStudBook : public CStudent {
private:
int grade;
};
// Function, that gets student data from the console
// and creates an instance of the CStudent class using this data
CStudent CreateFromConsole() {
cout << "Enter name: ";
string name;
cin >> name;
cout << "Enter fac. num: ";
int facnum;
cin >> facnum;
cout << "Enter specialty: ";
string specialty;
cin >> specialty;
cout << "Enter student grade: ";
int grade;
cin >> grade;
cout << endl;
return CStudent(name, facnum, specialty); // returns an instance of the class
}
int main() {
vector<CStudent> students; // stack-like container
cout << "Enter total number of students: ";
int count;
cin >> count;
cout << "Enter details of students" << endl << endl;
for (int i = 0; i < count; i++) {
// Create an instance of the class
CStudent student = CreateFromConsole();
// Push a copy of the object into the container
students.push_back(student);
}
cout << endl;
cout << "Details" << endl << endl;
for (int i = 0; i < students.size(); i++) {
students[i].PrintStudent();
cout << endl;
}
fflush(stdin); // Reset input console
getchar(); // Pause
return 0;
}
I think grade is private members of class CStudBook so you can't call it from class CStudent.
If you want to access it my suggested keyword for you to find is protected members
Related
I tried this code but when I am calling the member function inside the loop it is giving the garbage value of the details and when I am calling the member function outside the loop it is giving me error.
#include<iostream>
#include<string.h>
using namespace std;
class student
{
char name[10];
int id,rollno;
public:
student(char name[10],int id,int rollno)
{
strcpy(this->name,name);
this->id=id;
this->rollno=rollno;
cout<<"the name of the student is:"<<name<<endl;
cout<<"the id of the student is:"<<id<<endl;
cout<<"the roll no of the student is:"<<rollno<<endl;
}
};
int main()
{
int id1,rollno1;
char name1[10];
for(int i=1;i<=2;i++)
{
cout<<" enter the detail of the student "<<i<<" "<<endl;
cout<<"enter the name of the student:";
cin>>name1;
cout<<"enter the id of the student:";
cin>>id1;
cout<<"enter the roll no of the student:";
cin>>rollno1;
student d[]={student(name1,id1,rollno1)};
d[i].print();
}
return 0;
}
Here's your code review.
#include <iostream>
#include <string.h>
using namespace std; // it is strongly suggested that you don't use the whole header unless your intent is speeding up coding
class Student // capitalize classes
{
char _name[10];// it is ok, however, if you use the <string> header, why would you go back to char type?
int _id, _rollno;
public:
Student(char name[10] /* this is just the array's first item passed! */, int id, int rollno)
{
// Don't use this->, use an underscore for one of the names.
// I use underscores for the encapsulated data
strncpy_s(_name, name, 9);// a safer version
_id = id;
_rollno = rollno;
cout << "\nCtor says: ";
cout << "the name of the student is: " << _name << endl;
cout << "the id of the student is: " << _id << endl;
cout << "the roll no of the student is: " << _rollno << endl;
cout << '\n';
}
const char* getName() { return _name; }
const int getId() { return _id; }
const int getRollNo() { return _rollno; }
// unless you overload operator<< , you have to make getters for your info, or make it public
};
int main()
{
int id, rollno;// why 1? they won't intersect with the function
char name[10];
Student *s[2];//you must make that on the heap; otherwise you need a default constructor
for (int i{ 0 }; i < 2; i++)// start with 0 and make it just <
{
cout << "enter the details of the student " << i << endl;// Why so many spaces?
cout << "enter the name of the student: "; // add space after the colon
cin >> name;// remember, you're limited to 9 chars + \n !!!
cout << "enter the id of the student: ";
cin >> id;
cout << "enter the roll no of the student: ";
cin >> rollno;
//student d[] = { student(name,id,rollno) }; // you can't do this. It's not flexible.
// You either assign enough space for the intended number of students in the stack, statically, or
// you lett it find more space in the heap = dynamically
//this goes to the heap
s[i]= new Student( name,id,rollno );// parentheses are well
//s[i] = new Student{ name,id,rollno };// initializer list may also do
//d[i].print();// what's to print here? It's not POD, cout needs instructions
cout << "Stored data -> Id: " <<
s[i]->getId() << ", Name: " // -> dereferences the pointer, and s is a pointer now
<< s[i]->getName() << ", Roll no: "
// or you can dereference it
<< (*s[i]).getRollNo()
<< endl << endl; // make some extra space here
}
return 0;
}
#include <iostream>
#include <cstring>
using namespace std;
class Film {
private:
string name;
int year_prod;
string producer;
string main_actor;
public:
Film();
void print()
{
cout << "\nThe name of movie: " << name;
cout << "\nThe year of produced: " << year_prod;
cout << "\nProducer: " << producer;
cout << "\nMain actor: " << main_actor << endl;
}
void SetName(string xName)
{
name = xName;
}
string GetName()
{
return name;
}
void SetYearP(int xYearP)
{
year_prod = xYearP;
}
int GetYearP()
{
return year_prod;
}
void SetProducer(string xProducer)
{
producer = xProducer;
}
string GetProducer()
{
return producer;
}
void SetMaina(string xMaina)
{
main_actor = xMaina;
}
string GetMaina()
{
return main_actor;
}
};
int main()
{
Film obs[100]; // maximum of 100 hundred films
int n;
cout << "how many films ";
cin >> n;
for (int i = 0; i < n; ++i)
{
string name;
int year;
string prod;
string actor;
cout << "enter the film name ";
cin >> name;
cout << "enter the production year ";
cin >> year;
cout << "enter the producer name ";
cin >> prod;
cout << "enter the actor name ";
cin >> actor;
obs[i].SetName(name);
obs[i].SetYearP(year);
obs[i].SetProducer(prod);
obs[i].SetMaina(actor);
}
}
I've done half of my code but I get errors while compiling saying: unresolved external symbol "public: __thiscall Film::Film(void)" (??0Film##QAE#XZ) referenced in function _main AND 1 unresolved externals. I'm not sure if I had in the correct way objects of n Film from user input because I'm still a beginner in OOP.
You didn't implement your constructor:
public:
Film();//<-- declared, but not defined.
If you don't want your constructor to do anything, just add an empty body:
public:
Film() {};
or even better, explicitly declare it as the default-constructor:
public:
Film()=default;
Please try this out. Hope this helps.
class Film {
...
...
...
public:
//Film(); Remove this line if you are not defining Film()
void print()
{
cout << "\nThe name of movie: " << name;
cout << "\nThe year of produced: " << year_prod;
cout << "\nProducer: " << producer;
cout << "\nMain actor: " << main_actor << endl;
}
...
...
...
}
If you want it to be a default constructor add an empty block Film(){}
You have to implement the constructor for your class. The constructor is the method that create an instance of the class. The set functions have the purpose to modify the attributes of an object, but the initialization of the attributes must be done in the constructor.
For example:
public:
//default constructor: it does not take
//anything as input, it sets name as an
//empty string and the year to 1900
Film(){
name = "";
year = 1900;
}
// It creates a Film object, whose name
// is NAME and whose year is YEAR
Film(string NAME, int YEAR){
name = NAME;
year = YEAR;
}
// set function which allows to modify the
// year of a Film object.
void setYear(int newYear){
year = newYear;
}
Have a look here for a quick introduction.
EDIT: you may want to set the default constructor as
Film(){};
In this way you have to invoke all the set functions to initialise its attributes.
I am trying to do some stuff with C++ and i am new in it :)
I have tried 1 program of class that gets the student details and print the output of it.
#include <iostream>
using namespace std;
#define MAX 10
class student
{
private:
char name[30];
int rollNo;
int total;
float perc;
public:
//member function to get student's details
void getDetails(void);
//member function to print student's details
void putDetails(void);
};
//member function definition, outside of the class
void student::getDetails(void){
cout << "Enter name: " ;
cin >> name;
cout << "Enter roll number: ";
cin >> rollNo;
cout << "Enter total marks outof 500: ";
cin >> total;
perc=(float)total/500*100;
}
//member function definition, outside of the class
void student::putDetails(void) {
cout << "Student details:\n";
cout << "Name:"<< name << ",Roll Number:" << rollNo << ",Total:" << total << ",Percentage:" << perc;
}
int main()
{
student std[MAX]; //array of objects creation
int n,loop;
cout << "Enter total number of students: ";
cin >> n;
for(loop=0;loop< n; loop++){
cout << "Enter details of student " << loop+1 << ":\n";
std[loop].getDetails();
}
cout << endl;
for(loop=0;loop< n; loop++) {
cout << "Details of student " << (loop+1) << ":\n";
std[loop].putDetails();
}
return 0;
}
Its very basic code and works fine and I am able to give inputs and print the output.
Now I want to add new Student object at runtime using Dynamic memory allocation and want to add that object in the existing array of object (So that I can get the highest, lowest marks of any student)
I know I need to use new operator for this.
But I am not sure what could be the best way to write this solution.
Any help will be highly appreciated.
Thanks!
IMO, The best way to do this using dynamic memory is by using std::unique_ptr or std::shared_ptr (it actually depends on the requirement).
Here is one example of usage of unique_ptr:
using StudentPtr = std::unique_ptr<student>;
int main() {
std::vector<StudentPtr> studentDetails;
int n;
cout << "Enter the number of students: ";
cin >> n;
studentDetails.resize(n);
for (auto &s: studentDetails) {
s = StudentPtr(new student);
s->getDetails();
}
return 0;
}
For getting minimum and maximum, you may use min_element and max_element provided by STL respectively.
How could I use <vector> for an array of objects, which need to be given value through constructors? e.g class with name,age would need to get in an array with information given through constructor Student(string n, int a ) { name = n , age = a } .
All the data will be given through keyboard..
Here is an example code of a program capable of getting and storing the name and the age of a list of students using vectors. After that, it prints the information stored. I am using MSVC as the compiler, so if you are not on windows, you can remove system("pause"):
#include <vector>
#include <string>
#include <iostream>
using namespace std;
class Student {
public:
Student(string n, int a) : name(n), age(a) {}
string GetName(void) { return name; }
int GetAge(void) { return age; }
private:
string name;
int age;
};
int main(void) {
vector<Student> students;
unsigned int n;
cout << "How many students are there?" << endl;
cin >> n;
for (unsigned int i = 0; i < n; ++i) {
string name;
int age;
cout << endl << "Please give me the information of the student " << i + 1 << endl;
cout << "What is the name of the student?" << endl;
cin >> name;
cout << "What is the age of the student?" << endl;
cin >> age;
students.push_back(Student(name, age));
}
cout << endl << "Printing information of the students" << endl << endl;
for (unsigned int i = 0; i < n; ++i) {
Student& student = students[i];
cout << "Student " << i + 1 << " is " << student.GetName() << " and is " << student.GetAge() << " years old." << endl;
}
system("pause");
return 0;
}
One can use an initializer-list to directly construct a vector of students:
std::vector<Student> students{
{ "John", 22 },
{ "Melissa", 19 }
};
To add a student later one could use member function emplace_back() which just forwards its arguments to the Student constructor:
students.emplace_back( "Andy", 23 );
Pre C++11 one would have to use member function push_back() instead:
students.push_back( Student( "Andy", 23 ) );
More usage examples can be found on the linked reference pages.
I am having trouble trying to get this program to loop if user enter 'y' they'd like to continue. I'm super new to programming by the way so any help is greatly appreciated. I figured the best was to add a do/while in main and as k the user if they'd like to continue at the end of the code but, I quickly realized that wouldn't work unless I called the previous methods for user input and output. That's where the issue is arising.
Thanks again for any help!
/*
• Ask the user if they want to enter the data again (y/n).
• If ’n’, then the program ends, otherwise it should clear the student class object and
repeat the loop (ask the user to enter new data...).
*/
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
class Student {
public:
Student();
~Student();
void InputData(); // Input all data from user
void OutputData(); // Output class list to console
void ResetClasses(); // Reset class list
Student& operator =(const Student& rightSide); // Assignment operator
private:
string name;
int numClasses;
string *classList;
};
//array intialized to NULL
Student::Student() {
numClasses = 0;
classList = NULL;
name = "";
}
//Frees up any memory of array
Student::~Student() {
if(classList != NULL) {
delete [] classList;
}
}
// This method deletes the class list
// ======================
void Student::ResetClasses() {
if(classList != NULL) {
delete [ ] classList;
classList = NULL;
}
numClasses = 0;
}
//inputs all data from user (i.e. number of classes)
//using an array to store classes
void Student::InputData() {
int i;
// Resets the class list in case the method
// was called again and array wasn't cleared
ResetClasses();
cout << "Enter student name." << endl;
getline(cin, name);
cout << "Enter number of classes." << endl;
cin >> numClasses;
cin.ignore(2,'\n'); // Discard extra newline
if (numClasses > 0) {
//array to hold number of classes
classList = new string[numClasses];
// Loops through # of classes, inputting name of each into array
for (i=0; i<numClasses; i++) {
cout << "Enter name of class " << (i+1) << endl;
getline(cin, classList[i]);
}
}
cout << endl;
}
// This method outputs the data entered by the user.
void Student::OutputData() {
int i;
cout << "Name: " << name << endl;
cout << "Number of classes: " << numClasses << endl;
for (i=0; i<numClasses; i++) {
cout << " Class " << (i+1) << ":" << classList[i] << endl;
}
cout << endl;
}
/*This method copies a new classlist to target of assignment. If the operator isn't overloaded there would be two references to the same class list.*/
Student& Student::operator =(const Student& rightSide) {
int i;
// Erases the list of classes
ResetClasses();
name = rightSide.name;
numClasses = rightSide.numClasses;
// Copies the list of classes
if (numClasses > 0) {
classList = new string[numClasses];
for (i=0; i<numClasses; i++) {
classList[i] = rightSide.classList[i];
}
}
return *this;
}
//main function
int main() {
char choice;
do {
// Test our code with two student classes
Student s1, s2;
s1.InputData(); // Input data for student 1
cout << "Student 1's data:" << endl;
s1.OutputData(); // Output data for student 1
cout << endl;
s2 = s1;
cout << "Student 2's data after assignment from student 1:" << endl;
s2.OutputData(); // Should output same data as for student 1
s1.ResetClasses();
cout << "Student 1's data after reset:" << endl;
s1.OutputData(); // Should have no classes
cout << "Student 2's data, should still have original classes:" << endl;
s2.OutputData(); // Should still have original classes
cout << endl;
cout << "Would you like to continue? y/n" << endl;
cin >> choice;
if(choice == 'y') {
void InputData(); // Input all data from user
void OutputData(); // Output class list to console
void ResetClasses(); // Reset class list
}
} while(choice == 'y');
return 0;
}
Just get rid of
if(choice == 'y') {
void InputData(); // Input all data from user
void OutputData(); // Output class list to console
void ResetClasses(); // Reset class list
}
Because the variables s1 and s2 are inside the do-while loop, they'll be recreated on each iteration. (The constructor will be called at the definition, and the destructor will be called at the closing brace of the loop, before it tests choice == 'y' and repeats).
The other problem you run into is that your standard input isn't in a state compatible with calling s1.InputData() again. Because you just used the >> extraction operator to read choice, parsing stopped at the first whitespace, and there is (at least) a newline leftover in the buffer. When Student::InputData calls getline, it will find that newline still in the buffer and not wait for additional input.
This is the same reason you used cin.ignore after reading numClasses. You'll want to do the same here.