I have to create a small console application in C++ which will do the following:
Create class Subject which has next attributes: name of the subject, number of students and array of students who are attending that subject. After that createa class Student which has name and surname of the student as attributes. In Main file count how many duplicate names there are in each Subject.
I have few problems here. First one is that I don't know how to initialize an array in my Subject.h file. Second is how to actually put Student objects into Subject objects and compare the names in the end.
What I'd like output to look like:
Duplicate names in subjectA are: Michael.
Duplicate names in subjectB are: Nicholas, John.
Where subjectA and subjectB should be called C++ and C.
Here is my code so far (I googled for past hour or two about this problem of mine but I just couldn't find a proper answer/example).
NOTE: I'm including all these files for clarification.
Subject.h
#include <string>
#include <iostream>
using namespace std;
/*
* I should also have an array named `arrayOfStudents`
* which should store all students who are attending
* that Subject.
*/
class Subject
{
public:
Subject();
Subject(Subject &subject);
Subject(string nameOfSubject, int numberOfStudents);
~Subject();
const string getNameOfSubject();
const int getNumberOfStudents();
void setNameOfSubject(string nameOfSubject);
void setNumberOfStudents(int numberOfStudents);
void print();
private:
string nameOfSubject;
int numberOfStudents;
};
Subject.cpp
#include <iostream>
#include "Subject.h"
using namespace std;
Subject::Subject()
{
}
Subject::Subject(string nameOfSubject, int numberOfStudents)
{
this->nameOfSubject = nameOfSubject;
this->numberOfStudents = numberOfStudents;
}
Subject::Subject(Subject &Subject) : nameOfSubject(Subject.getNameOfSubject()), numberOfStudents(Subject.getNumberOfStudents())
{
}
Subject::~Subject()
{
cout << "Object is destroyed" << endl;
}
const string Subject::getNameOfSubject()
{
return nameOfSubject;
}
const int Subject::getNumberOfStudents()
{
return numberOfStudents;
}
void Subject::setNameOfSubject(string nameOfSubject)
{
nameOfSubject = this->nameOfSubject;
}
void Subject::setNumberOfStudents(int numberOfStudents)
{
numberOfStudents = this->numberOfStudents;
}
void Subject::print()
{
cout << "Subject: " << nameOfSubject << " :: Number of students: " << numberOfStudents << endl;
}
Student.h
#include <string>
#include <iostream>
using namespace std;
class Student
{
public:
Student();
Student(Student &student);
Student(string name, string surname);
~Student();
const string getName();
const string getSurname();
void setName(string name);
void setSurname(string surname);
void print();
private:
string name;
string surname;
};
Student.cpp
#include <iostream>
#include "Student.h"
using namespace std;
Student::Student()
{
}
Student::Student(string name, string surname)
{
this->name = name;
this->surname = surname;
}
Student::Student(Student &student) : name(student.getName()), surname(student.getSurname())
{
}
Student::~Student()
{
cout << "Object is destroyed" << endl;
}
const string Student::getName()
{
return name;
}
const string Student::getSurname()
{
return surname;
}
void Student::setName(string name)
{
name = this->name;
}
void Student::setSurname(string surname)
{
surname = this->surname;
}
void Student::print()
{
cout << "Student: " << name << " " << surname << endl;
}
Main.cpp
#include <iostream>
#include "Subject.h"
#include "Student.h"
using namespace std;
int main()
{
/*
* First three students should attend first Subject
* while other four the second Subject.
* Also note that only names matter and not surnames.
*/
Student stA("Michael", "Doe");
Student stB("Michael", "Doe");
Student stC("Thomas", "Doe");
Student stD("Nicholas", "Doe");
Student stE("Nicholas", "Doe");
Student stF("John", "Doe");
Student stG("John", "Doe");
Subject subjectA("C++", 3);
Subject subjectB("C", 4);
return 0;
}
1) Get an array of Students into your Subject object: you probably want to use vectors instead of arrays here:
in subject.h add
#include "Student.h"
public:
void addStudent(Student student);
private:
std::vector<Student> students_;
in subject.cpp add
void Subject::addStudent(Student student)
{
this->students_.push_back(student);
}
If you want to extract the student list somehow later, you need to write a function to access it (or make it public).
2) For finding duplicates, look here
Checking for duplicates in a vector
You have to pay attention: the Student objects are in your subject object, not the student names. You have to extract them first and e.g. put them in a vector.
Your task definition sais you should have an array of Students attribute of the Subject class, but i don't see this in your Subject class definition.
And maybe an add Student method and then iterate over the array.
Related
I've created a class Student which contains a dynamic array. I've filled the first two items with the constructor. Every method I've tried to use to access/print those two elements from the main get a read/access violation and crashes. I've added a cout in the constructor that shows the elements ARE filled and exist. I've included two failed methods in the main: A void function that attempts to send first element to cout, and a method that accepts an int for the desired index. Both have been commented out to allow a test run showing elements are created and printed by the constructor.
Header:
#ifndef STUDENT_H
#define STUDENT_H
#include <string>
#include <iostream>
#define ARRAY_MAX 15
using namespace std;
class Student
{
private:
string firstName, lastName;
unsigned int ID, numItems = 0;
typedef string* StringPtr;
StringPtr items;
public:
int capacity = 15;
Student();
Student(const string fName, const string lName, const unsigned int id);
string getfName() const;
string getlName() const;
void getItem(int num);
string getItemB(int num) const;
unsigned int getID() const;
};
#endif // STUDENT_H
Definitions:
#include "student.h"
using namespace std;
Student::Student()
{
}
Student::Student(const string fName, const string lName, const unsigned int id)
{
firstName = fName;
lastName = lName;
ID = id;
StringPtr items = new string[capacity];
numItems = 0;
items[0] = "stuff";
items[1] = "things";
cout << items[0] << endl << items[1] << endl;
}
string Student::getfName() const
{
return firstName;
}
string Student::getlName() const
{
return lastName;
}
void Student::getItem(int num)
{
cout << items[0] << endl;
}
string Student::getItemB(int num) const
{
return items[num];
}
unsigned int Student::getID() const
{
return ID;
}
Main:
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include "student.h"
using namespace std;
int main()
{
Student stu;
string str;
stu = Student("John", "Smith", 1200);
cout << stu.getfName() << " " << stu.getlName() << endl;
//stu.getItem(0);
//cout << stu.getItemB(0);
system("pause");
// Quit without error
return 0;
}
Solution
Change
StringPtr items = new string[capacity];
into
items = new string[capacity];
TL;DR
In
Student::Student(const string fName, const string lName, const unsigned int id)
{
firstName = fName;
lastName = lName;
ID = id;
StringPtr items = new string[capacity];
numItems = 0;
items[0] = "stuff";
items[1] = "things";
cout << items[0] << endl << items[1] << endl;
}
The line
StringPtr items = new string[capacity];
creates a new Automatic (local) variable items and initializes it rather than the intended private member variable StringPtr items;. This is commonly known as Variable Shadowing. The local items goes out of scope at the end of the function leaking the allocated memory and the member items is never initialized leading to stu.getItem(0); accessing an uninitialized pointer and triggering the crash.
void Student::getItem(int num)
{
cout << items[0] << endl; // items points Crom knows where, so items[0] is invalid.
}
This crash is quite fortunate. Accessing an unitintialized pointer results in Undefined Behaviour which means it could do anything from looking like it works to causing the universe to explode.
The next problem you have to deal with is observing The Rule of Three.
The best way to deal with this is std::vector
std::vector<string> items;
std::vector is Rule of Three (Rule of Five, actually) compliant so that you don't have to be.
If std::vector is not allowed, you need to implement a copy constructor
Student::Student(const Student & src):
firstName(src.firstName), lastName(src.lastName),
ID(src.ID), numItems(src.numItems),
items(new string[capacity])
{
for (int i = 0; i < src.numItems; i++)
{
items[i] = src.items[i];
}
}
and an assignment operator (Taking advantage of the Copy and Swap Idiom for simplicity)
Student & Student::operator=(Student src)
{
swap(*this,src);
return *this;
}
Writing swap I'll leave up to you.
I have this requirement.
I am trying to make a simple database schema, a little different than what I have seen in here. I have a class file (client.h) with it's implementation (client.cpp):
#ifndef CLIENT_H_
#define CLIENT_H_
#include <iostream>
using namespace std;
class Client {
public:
// constructors
Client();
Client(string new_name, string new_tel, string new_addr);
// getters
string getName();
string getAddr();
string getTel();
// setters
void setName(string);
void setAddr(string);
void setTel(string);
void display();
void input();
private:
// fields
string name;
string addr;
string tel;
};
#endif /* CLIENT_H_ */
/*
*ad client.cpp
*
* Created on: Jan 12, 2017
* Author: niksarid
*/
#include <iostream>
#include "client.h"
using namespace std;
Client::Client() {
setName("");
setAddr("");
setTel("");
}
Client::Client(std::string new_name, std::string new_addr, std::string new_tel) {
setName(new_name);
setAddr(new_addr);
setTel(new_tel);
}
string Client::getName() {
return name;
}
string Client::getAddr() {
return addr;
}
string Client::getTel() {
return tel;
}
void Client::setName(string p_name) {
name = p_name;
}
void Client::setAddr(string p_addr) {
addr = p_addr;
}
void Client::setTel(string p_tel) {
tel = p_tel;
}
void Client::input() {
string tmp;
cout << "INPUT CLIENT INFO" << endl;
cout << "Name: ";
cin >> tmp;
setName(tmp);
cout << "Address: ";
cin >> tmp;
setAddr(tmp);
cout << "Telephone: ";
cin >> tmp;
setTel(tmp);
}
void Client::display() {
cout << name << "\t" << addr << "\t" << tel << endl;
}
So I am trying to make a Company class that will hold a vector of Clients and at the startup of the program it will load the datafile "clients.dat", into the vector. I will be able to add a client or delete a client from the vector. At the end the vector will be saved back to "clients.dat".
So, the (company.h) file is like this:
class Company {
public:
Company();
~Company();
void add_client();
void print_clients();
void loadClientsFromFile();
void saveClientsToFile();
private:
vector<Client> clients;
} cmp;
#endif /* COMPANY_H_ */
but I can't seem to reference clients vector in any of the public methods of the class company.
EDIT: Sorry! Forgot the important part!!
For example when I try to add_client(),
void add_client() {
Client c;
c.input();
clients.push_back(c);
}
but I get
../src/company.cpp:49:2: error: 'clients' was not declared in this scope
clients.push_back(c);
So, how to achieve that?
As Morgan mentioned in the comments, this problem typically arises when you try to define the member function in your implementation file, but forget to add the class name as prefix (e.g. void add_client() {} instead of void Company::add_client() {}.
This mistake is common and can easily go unnoticed, since it is perfectly legal to define a new free function called add_client in your file, that would have nothing to do with the Company class. That's why the compiler only complains when you try to access a data member, but not before.
I've been doing c++ self study after taking two semesters of Java.
Below is a simple program which builds fine, but when I run it I get gradeBook2s displayInfo() method called twice. I'm sure its something basic I am missing, but any ideas why?
//GradeBook.h
#include<string>
#include<iostream>
using std::cout;
using std::endl;
using std::string;
string courseName;
int courseGrade;
class GradeBook {
public:
GradeBook(string name, int grade) {
setCourseName(name);
setCourseGrade(grade);
}
public:
void setCourseName(string name) {
courseName = name;
}
public:
string getCourseName() {
return courseName;
}
public:
void setCourseGrade(int score) {
courseGrade = score;
}
public:
int getCourseGrade() {
return courseGrade;
}
public:
void displayInfo(){
cout << "Course Name: " << getCourseName()
<< "Course grade: " << getCourseGrade()
<< endl;
}
};
//main.cpp
#include<iostream>
#include "GradeBook.h"
int main() {
GradeBook gradeBook1("Calculus 2", 90);
GradeBook gradeBook2("Chemistry", 80);
gradeBook1.displayInfo();
system("pause");
gradeBook2.displayInfo();
system("pause");
}
The problem that you have is that you are saving the variables courseName and courseGrade as global variables. Because of this, you are overwriting the previous class instance's data with the current, in this case, Chemistry. What you need to do is move the declaration of courseName and courseGrade inside the accessor private inside the class, like this:
class GradeBook {
private:
string courseName;
int courseGrade;
public:
//put your functions here
}
The locations where the code stores values is global, so all instances will appear the same.
Initial problem solved. (which was a redefinition error)
Furthermore, I don't know how to create a Student constructor which delivers the following:
This is how I want my program / constructors to work:
//main.cpp
Student s1(4015885);
s1.print();
Student s2("Test", "Student", 22, 5051022);
s2.print();
The output should be as follows:
Standart
Name
18
4015885
Test
Student
22
5051022
s1 works, but s2 doesn't work, because I don't have a fitting constructor
This is my Person.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Person {
public:
Person(string name = "Standard", string surname = "Name", int age**strong text** = 18);
//GET
//SET
void print();
protected:
string name, surname;
int age;
};
Person.cpp
#include <iostream>
#include <string>
#include "Person.h"
using namespace std;
Person::Person(string n, string s, int a) : name(n), surname(s), age(a)
{
cout << "Person constructor" << endl;
}
void Person::print() {
cout << name << endl << surname << endl << age << endl << endl;
}
Student.h
#pragma once
//#ifndef PERSON_H
//#define PERSON_H
#include "Person.h"
class Student : public Person {
public:
Student(int matrikel_nummer);
int get_matriculation_number();
void set_matriculation_number(int matriculation_number) {
this->matriculation_number = matriculation_number;
}
void print();
private:
int matriculation_number;
};
//#endif
Student.cpp
#include <iostream>
#include <string>
#include "Student.h"
using namespace std;
Student::Student(int matrikel_nummer) : Person(name, surname, age)
{
cout << "Student constructor" << endl;
this->matriculation_number = matriculation_number;
}
void Student::print() {
cout << name << endl
<< surname << endl
<< age << endl
<< matriculation_number << endl << endl;
}
In Student.h you have
Student(int matriculation_number) : Person(name, surname, age){};
Which declares and defines a constructor for Student. Then in Student.cpp you have
Student::Student(int matrikel_nummer) : Person(vorname, nachname, alter)
{
cout << "Student constructor" << endl;
this->matrikel_nummer = matrikel_nummer;
}
Which redefines the same constructor.
You either need to get rid of the constructor definition in the class
Student(int matriculation_number) : Person(name, surname, age){};
//becomes
Student(int matriculation_number);
or get rid of the constructor in the cpp file.
Also name, surname, age, vorname, nachname, alter do not appear anywhere in the code you have provided. This will not compile unless they declared somewhere else.
EDIT:
From the comments it looks like your Student constructor should be
Student(string n, string s, int a, int mn) : Person(n, s, a), matriculation_number(mn) {}
And you can put that in the header and you do not need a constructor definition in the cpp file.
Your error is here:
Student(int matriculation_number) : Person(name, surname, age){};
Remove the {} and the base ctor call:
Student(int matriculation_number);
You already defined the constructor body of student:
Student(int matriculation_number) : Person(name, surname, age){};
That is already a complete implementation of the constructor body, you should write this in the header:
Student(int matriculation_number);
Whenever I try to make an object and call a function on it, it doesn't seem to work.
I have no idea why, since I don't seem to have errors too.
I have searched around on here regarding constructors and the toString-method, but haven't find anything that worked.
I have tried to edit (distinct) the members in the constructor members,
Tried to rewrite the toString method.
Tried to make local object (with no pointer).
But it doesn't return me the things in the object that I created when calling the constructor.
Where does the problem situate in this problem?
Here is my code:
.h file:
#pragma once
#include "stdafx.h"
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
class Store{
private:
int id;
string name;
string adress;
string telephone;
string btwNumber;
public:
int getId();
void setId(int);
string getName();
void setName(string);
string getAdress();
void setAdress(string);
string getTelephone();
void setTelephone(string);
string getBtwNumber();
void setBtwNumber(std::string);
string toString();
Store(int, string, string , string, string);
};
.cpp file:
// Store.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "Store.h"
Store::Store(int idnum, string nameS, string adreS, string telephonE, string btwnummeR){
idnum = id;
nameS = name;
adreS = adress;
telephonE = telephone;
btwnummeR = btwNumber;
}
int Store::getId()
{
return id;
}
void Store::setId(int id){
this->id = id;
}
string Store::getName(){
return naam;
}
void Store::setName(string name){
this->naam = naam;
}
string Store::getTelephone(){
return telephone;
}
void Store:setTelephone(string telephone){
this->telephone = telephone;
}
string Store::getBtwNumber()
{
return btwNumber;
}
void Store::setBtwNumber(string btwNumber){
btwNumber = btwNumber;
}
string Store::getAdress(){
return adress;
}
void Store::setAdress(string adress){
this->adress = adress;
}
string Store::toString(){
stringstream s;
s << "Id: " << id << endl;
s << "Naam: " << name << endl;
s << "Adres: " << adress << endl;
s << "Telefoonnummer: " << telephone << endl;
s << "BTWnummer: " << btwNumber << endl;
return s.str();
}
int _tmain(int argc, _TCHAR* argv[])
{
Store *test = new Store (4, "Test", "test", "test", "test");
test->toString();
system("Pause");
return 0;
}
Your constructor is inversed: you are assigning member variables to constructor arguments and not vice versa.
nameS = name;
Should be
name = nameS;
And so on
The method toString does work, but it won't magically decide to output its return value to screen. You'll have to do it yourself:
std::cout << test->toString() << std::endl;
You'll need to add #include <iostream> on top of your cpp file.