Accessing multiple instances of a class in C++ - c++

I am creating a menu for a restaurant that can have 5 dishes of each category. So far I have created a class for meat dishes and I'm able to add up to 5 dishes, each with a unique identifier. What I am having trouble with is accessing the objects after they have been created.
(There will be multiple categories hence why there is a switch statement with only one case so far).
For example, how would I implement a way to change the description of the second dish?
Here is my code so far:
meat.h
class Meat{
private:
int meatNumber;
std::string meatCategory;
std::string meatDescription[MAX_ITEMS];
double meatPrice[MAX_ITEMS];
public:
Meat();
//setter functions
int setMeatNumber();
std::string setMeatDescription();
double setMeatPrice();
//getter functions
int getMeatNumber();
std::string getMeatCategory();
std::string getMeatDescription(int i);
double getMeatPrice(int i);
};
meat.cpp
#include "Meat.h"
//constructor
Meat::Meat() {
meatNumber = 0;
meatCategory = "Meat";
meatDescription[MAX_ITEMS] = "No description written.";
meatPrice[MAX_ITEMS] = 0.0;
}
//setter functions
int Meat::setMeatNumber(){
static int counter = 1;
meatNumber = counter++;
}
std::string Meat::setMeatDescription(){
int i = 0;
std::cout << "Please enter a short description: " << std::endl;
std::cin >> meatDescription[i];
return meatDescription[i];
}
double Meat::setMeatPrice(){
int i = 0;
std::cout << "Please set the price in a 00.00 format: " << std::endl;
std::cout << "£";
while(!(std::cin >> meatPrice[i])){
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Error. Please enter a number: ";
}
return meatPrice[i];
}
//getter functions
int Meat::getMeatNumber() { return meatNumber; }
std::string Meat::getMeatCategory() { return meatCategory; }
std::string Meat::getMeatDescription(int i) {return meatDescription[i]; }
double Meat::getMeatPrice(int i) { return meatPrice[i]; }
main.cpp
#include <iostream>
#include "Meat.h"
int main() {
int choice;
std::cout << "Menu Creation Terminal\n\n" << std::endl;
std::cout << "\t Welcome\nto Wrapid™ Restaurants\n\n" << std::endl;
std::cout << "1. Add Meat Dish\n2. Add Fish Dish\n3. Add Vegetarian Dish\n4. Add Drink\n"
"5. Edit Current Menu\n6. Quit\n\n" << std::endl;
std::cout << "Please select an option: ";
std::cin >> choice;
switch (choice) {
case 1:
{
int option = true;
int count = 0, i;
Meat meatDish;
std::cout << "Meat Dishes" << std::endl;
while (true) {
meatDish.setMeatNumber();
meatDish.setMeatDescription();
meatDish.setMeatPrice();
//functions to add details to dish
std::cout << "You have added the following dish: " << std::endl;
std::cout << "Item number: \n" << meatDish.getMeatNumber() << std::endl;
std::cout << "Item Category: \n " << meatDish.getMeatCategory() << std::endl;
std::cout << "Item Description: \n" << meatDish.getMeatDescription(i) << std::endl;
std::cout << "Item Price: \n £" << meatDish.getMeatPrice(i) << std::endl;
std::cout << "Would you like to add another item? Press 1 for yes or 2 for no: " << std::endl;
std::cin >> option;
count += 1;
if (count == 5) {
std::cout << "Error. Exceeded maximum items.";
break;
} //breaks out of loop if more than 5 items
if (option == 2) { break; } //breaks out of loop when user is finished adding items
}//while loop to contain menu
}//brace for scope of case 1
}
return 0;
}

As you are using c++ class Meat you can use [] to instantiate N items
for example 5 objects
Meat meats[5];
If you want to modify 2nd object then
meats[1].setMeatDescription(<pass argument>);
You need to change that method using this keyword
this->meatDescription = <pass argument>;
No need to create meatDescription[] as an array
use this code https://pastebin.com/bCkzbFZV you can use meats[i].getMeatDescription()

You could create a new class called DishesContainer. This class could have :
a private std::vector => it will hold every instance
a public function to create a new dish
a public function to change any type of value inside a dish meat.
For exemple to change the description
class DishContainer{
public:
void ChangeDescription(int indexMeat, std::string newDescription){
meats_[indexMeat].setMeatDescription(newDescription);
}
private:
std::vector<Meat> meats_;
}

Related

How can I use struct efficiently in my quiz?

I'm trying to create a simple quiz with struct. But my program here is very repetitive. How can I modify it and make it more efficient? Especially to check if the answers are correct I do not want to declare a separate variable and store it as int correct. Thank You.
#include <iostream>
using namespace std;
struct Quiz{
string question;
string answers[3];
};
struct Quiz2{
string question2;
string answers2[3];
};
int correct;
int main()
{
Quiz Question;
Question.question = "What is the smallest county?";
cout << Question.question << endl;
Question.answers[0] = "1. USA";
cout << Question.answers[0] << endl;
Question.answers[1] = "2. India";
cout << Question.answers[1] << endl;
Question.answers[2] = "3. Vatican City";
cout << Question.answers[2] << endl;
cout << endl;
cout << "Choose 1-3: ";
cin >> correct;
if(correct == 3)
cout << "Correct!";
else
cout << "Incorrect!";
cout << endl;
cout << endl;
// Question 2
Quiz2 Question2;
Question2.question2 = "What is the biggest animal in the world?";
cout << Question2.question2 << endl;
Question2.answers2[0] = "1. Elephant";
cout << Question2.answers2[0] << endl;
Question2.answers2[1] = "2. Blue Whale";
cout << Question2.answers2[1] << endl;
Question2.answers2[2] = "3. Great white shark";
cout << Question2.answers2[2] << endl;
cout << endl;
cout << "Choose 1-3: ";
cin >> correct;
if(correct == 2)
cout << "Correct!";
else
cout << "Incorrect!";
return 0;
}
That's as much as non-repetitive as I can imagine after a few minutes of thinking. Maybe it can become smaller, but for my taste this looks alright.
You basically rely on std::vector class, instead of a typical array, because vectors can be of dynamic size. This allows us to use only one struct, but make as many answers as we want (3, 5, 10, whatever). We then create the whole quiz as another vector of questions. We're only left with printing to the console - for that we use loops, as our quiz structure is very simple and self-repetitive.
#include <iostream>
#include <vector>
using namespace std;
struct Question{
string question;
int correct_idx;
vector<string> answers;
Question(string question, int correct_idx, vector<string> answers)
:question(question), correct_idx(correct_idx), answers(answers)
{}
};
int main()
{
vector<Question> whole_quiz = {
Question{
"What is the smallest country?",
2, // indexes start from 0, e.g. 0, 1, 2. So 2 is correct
{"USA", "India", "Vatican City"}
},
Question{
"What is the biggest animal in the world?",
1,
{"Elephant", "Blue Whale", "Great white shark"}
},
};
for(auto question : whole_quiz) {
cout << question.question << endl;
for(int i = 0; i < question.answers.size(); ++i) {
cout << i+1 << ". " << question.answers[i] << endl;
}
cout << "Choose 1-" << question.answers.size() << endl << endl;
int guess;
cin >> guess;
if (guess-1 == question.correct_idx) {
cout << "Correct!" << endl << endl;
} else {
cout << "Incorrect!" << endl << endl;
}
}
return 0;
}
I would propose a more complicated, but also a more fun solution. Have a huge list of answers, like 100, or 1000, or as many as you like. Then in your struct have a std::string question, and std::vector<int> possible answers that are indexes in the huge list. First answer in the list is the correct one. So when you ask a question you pick first index, and three more indexes at random, and you shuffle them up, and present this to the user. The quiz will be different every time.
struct acts as a template, not a single variable. so there's no need to create 2 different struct. Also, a correct variable can be added to the struct for ease of checking.
Code (I split it into different functions for clearer understanding):
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct quiz
{
int correct;
string question;
vector<string> answers;
};
vector<quiz> questionsToAsk;
void addNewQuestion(string ques, vector<string>ans, int cor)
{
quiz q1;
q1.question = ques;
q1.answers = ans;
q1.correct = cor;
questionsToAsk.push_back(q1);
}
void displayQuestion(int idx)
{
quiz cur = questionsToAsk[idx];
cout << cur.question << '\n';
for (int i = 0; i < cur.answers.size(); i++)
{
cout << cur.answers[i] << '\n';
}
cout << "Choose 1-3: "; int inp; cin >> inp;
if (inp == cur.correct) {cout << "Correct";} else {cout << "Incorrect";} cout << '\n';
}
int main()
{
vector<string> ans1({"1. USA", "2. India", "3. Vatican City"});
vector<string> ans2({"1. Elephant", "2. Blue Whale", "3. Great white shark"});
addNewQuestion("What is the smallest county?", ans1, 3);
addNewQuestion("What is the biggest animal in the world?", ans2, 2);
for (int i = 0; i < questionsToAsk.size(); i++)
{
displayQuestion(i);
}
}
Result:
What is the smallest county?
1. USA
2. India
3. Vatican City
Choose 1-3: 1
Incorrect
What is the biggest animal in the world?
1. Elephant
2. Blue Whale
3. Great white shark
Choose 1-3: 2
Correct
You can use a template like
<typename T = int>
T get_answer(std::istream& in) {
T res;
in >> res;
return res;
}
...
if(get_answer(std::cin) == 3)
cout << "Correct!";
else
cout << "Incorrect!";
You can also overload operator<<.
#include <iostream>
#include <string>
template<typename T = int>
T get_answer(std::istream& in) {
T res;
in >> res;
return res;
}
class Quiz{
public:
Quiz(const std::string& q, const std::string& a1, const std::string& a2, const std::string& a3, unsigned correct)
: question(q), answers{a1, a2, a3}{
CheckAnswer(correct);
}
friend std::ostream& operator<<(std::ostream& os, const Quiz& quiz) {
os << quiz.question << "\n";
unsigned i = 1;
for (const auto & answer : quiz.answers) {
os << i++ << ". " << answer << "\n";
}
os << "\n";
return os;
}
void CheckAnswer(unsigned correct) {
std::cout << *this << "Choose 1-3: ";
if(get_answer(std::cin) == correct)
std::cout << "Correct!";
else
std::cout << "Incorrect!";
std::cout << std::endl;
std::cout << std::endl;
}
private:
std::string question;
std::string answers[3];
};
int main()
{
Quiz Question("What is the smallest county?", "USA", "India", "Vatican City", 3);
// Question 2
Quiz Question2("What is the biggest animal in the world?", "Elephant", "Blue Whale", "Great white shark", 2);
return 0;
}
The only thing you can do is define the correct variable in the struct itself. You can use a loop for decreasing the repetitiveness but obviously the question and the answers will have to be stored, it cannot be simplified further.

Semantic error in the selection condition of the type of LED lamps

I have a class of light bulbs. There are methods and constructors in this class. There is even a destructor) The problem is that I have to determine and display information about class members with type "n" in the TEST() method (LED lamps).
To implement this task, he developed the gettype() method, which returns the type of an object, and, in fact, the TEST() method, which displays information about light bulbs.
The problem is that nothing works for me. I tried a lot of things, but it doesn’t work out for me to implement this task. I'm new to programming (
Code:
#include <iostream>
using namespace std;
class lamp
{
public:
// methods
void TEST(void);
char* gettype (void);
void INIT(void);
void SHOW(void);
// construcrors
lamp();
lamp(const char *t, int powe, const char *c, double cos);
lamp(const lamp & obj);
// destructor
~lamp();
private:
// data
char type[100]; // LED, energy-saving or incandescent lamp
int power; // LED lamp - "n"
char color[100];
double cost;
};
lamp::lamp() {
cout << "This object was created in the default constructor.\n";
strcpy(type, "");
power = 0;
strcpy(color, "");
cost = 0;
}
lamp::lamp(const char *t, int powe, const char *c, double cos) {
cout << "This object was created in the constructor with parameters.\n";
strcpy(type, t); //*t
power = powe;
strcpy(color, c); //*c
cost = cos;
}
lamp::lamp(const lamp & obj) {
cout << "This object was created in the copy constructor.\n";
strcpy(type, obj.type);
power = obj.power;
strcpy(color, obj.color);
cost = obj.cost;
}
lamp::~lamp() {
cout << "Deletion of object by destructor.\n";
}
void lamp::SHOW(void) {
cout << "Lamp Information:\n";
cout << "\nType > " << type;
cout << "\nPower > " << power;
cout << "\nColor > " << color;
cout << "\nCost > " << cost << endl;
}
void lamp::INIT(void) {
cout << "Enter lamp information:\n";
cout << "\nType (if LED, then n) > "; cin >> type;
cout << "\nPower > "; cin >> power;
cout << "\nColor > "; cin >> color;
cout << "\nCost > "; cin >> cost;
}
char* lamp::gettype (void) {
return type;
}
void lamp::TEST(void) {
cout << "\nType > " << type;
cout << "\nPower > " << power;
cout << "\nColor > " << color;
cout << "\nCost > " << cost << endl;
}
void main() {
setlocale(0, "");
// default constructor for 1 class instance
lamp l1;
cout << "Entering data for the first product." << endl;
l1.INIT();
// constructor with parameters for 2 class instances
cout << endl << "Information about the second object: \n";
lamp l2("n", 950, "yellow", 1580);
// copy constructor for the third object
cout << endl << "Information about the third object: \n";
lamp l3(l2);
// Derived information about all the lamps using the method SHOW
l1.SHOW();
l2.SHOW();
l3.SHOW();
// I create an array of two objects using the default constructor
lamp la[2];
I enter data into an array of objects using the method INIT
cout << "Fill an array of objects with 2 elements." << endl;
for(int i = 0; i < 2; i++) {
la[i].INIT();
}
// I output data from an array of objects using the method SHOW
cout << "Showing items." << endl;
for (int i = 0; i < 2; i++) {
la[i].SHOW();
}
// looking for and displaying information about LED lamps
cout << "Search and display information about LED lamps." << endl;
for (int i = 0; i < 3; i++) {
if (la[i].gettype() == "n") {
cout << endl << " lamp number : " << (i + 1) << endl;
la[i].TEST();
cout << endl;
}
}
system("pause");
}
There are several errors in your code:
strcpy is included in <cstring> which is missed. You need to add it in the beginning:
#include <cstring>
main() function should be declared as int main() and you need to add a return statement
int main() {
//YOUR CODE HERE
return 0;
}
You missed a comment sign at line 104
lamp la[2];
//I enter data into an array of objects using the method INIT
cout << "Fill an array of objects with 2 elements." << endl;
After fixed, your code should be able to run.

Variable not changing from user input in C++

I'm trying to create multiple calculators in the C++ console for Geometry Theorems and other formulas in Algebra, and for some weird reason on the start of the program, when selecting an option the variable scene does not want to change(shown before the array of calculators[], and instead of going to the Pythagorean Theorem(scene 1), the console says, "Press any key to continue. . ." and closes.
I've tried both the switch() andif() statements to navigate scene management, but what am I doing incorrectly? (I'm still a C++ learner by the way, but I have other programming language experience).
Thanks for the help in advance.
#include "stdafx.h"
#include <iostream>
#include <cmath>
int scene(0);
char calculators[3][25] =
{
"",
"Pythagorean Theorem",
"Homer's Formula"
};
void selection()
{
std::cout << "Enter a number to select a calculator." << std::endl; // Opening
for (int i = 1; i <= 2; i += 1) {
std::cout << "Option " << i << ": " << calculators[i] << std::endl;
}
}
void pTheorem()
{
int a;
int b;
std::cout << "Enter side a: ";
std::cin >> a;
std::cout << "Enter side b: ";
std::cin >> b;
std::cout << "Side length of c is " << sqrt(pow(a, 2) + pow(b, 2)) << std::endl;
}
int main()
{
switch(scene)
{
case 0:
selection();
std::cin >> scene;
std::cout << "You've selected the " << calculators[scene] << " Calculator" << std::endl;
break;
case 1:
pTheorem();
break;
}
return 0;
}
Your main problem is that scene has been declared and initialized 0 at the beginning(globally) itself. This will give you always the same switch case = 0. Changing scene inside the switch cases will not work. Instead, you need to input the scene before the switch.
int main()
{
selection();
int scene = 0;
std::cin >> scene;
switch(scene)
{
......
}
}
Secondly, use std::string instead of char array and use std::vector<>/std::array to store them. For example:
std::array<std::string,2> calculators =
{
"Pythagorean Theorem",
"Homer's Formula"
};
and for loop can be:
for (int i = 0; i < 2; ++i)
std::cout << "Option " << i+1 << ": " << calculators[i] << std::endl;

Static vector as a class objects container

I've seen many questions and answers about this issue but still I can't solve my problem. How should I initialize a static vector? I'm also asking you for checking I use a default construct properly. I don't mean checking if it's working because I know that it does. I just wonder if it is an elegant implementation?
class Employee
{
private:
static std::vector<Employee> employee;
std::string name;
int age;
Employee::Employee()
{
std::string localName;
int localAge;
std::cout << "So... do you want to hire a new employee? Let's look at CVs " << std::endl;
localName = "Marek"; //GenerateName();
localAge = 21; //these function is not ready yet. it'd be just a rand()
std::cout << "I've got one. What do u think about " << localName << " age " << localAge << "?" << std::endl;
int decision;
do
{
std::cout << "Do you want hire him [1] or not [2] ? " << std::endl;
std::cin >> decision;
switch (decision)
{
case 1:
name = localName;
age = localAge;
decision = 0;
break;
case 2:
employees.erase(employees.end());
decision = 0;
break;
default:
std::cout << "Incorrect option. Try again" << std::endl;
}
} while (decision != 0);
}
public:
static void Employ()
{
employees.push_back(Employee::Employee());
}
};
int main()
{
Employee::Employ();
system("pause");
}
Your code didn't work when I ran it. In addition to adding includes and fixing some typos, I had to add this line:
std::vector<Employee> Employee::employee;
However, I don't think this is the best solution. For sweet clarity's sake, an Employee shouldn't contain a vector of Employees, but should be, well, an employee. If you want a vector of employees, you can declare one in main (or elsewhere). If you want your vector of employees to have some added features like the interactive employee-adding function you wrote, you can do it like this:
class EmployeeForce: public std::vector<Employee>
{
void interactivelyAddEmployee ();
...
};
...
EmployeeForce myStaff;
I've changed entire the concept. The problem was that I unnecessary wanted to put inside the class the container of objects (in this case: std::vector). I know now that class should only contain informations about the single object; it shouldn't know about anything about others one.
class Employee
{
public:
std::string name;
int age;
};
std::ostream& operator<<(std::ostream& out, const std::vector<Employee>& v)
{
out << "[";
for (size_t i = 0; i < v.size(); ++i)
{
out << "Name: " << v[i].name << " age: " << v[i].age;
if (i != v.size() - 1)
out << ", ";
}
out << "]";
return out;
}
Employee generate_random_employee(Employee obj)
{
obj.name = "Marek"; //GenerateName();
obj.age = 21; //these function is not ready yet. it'd be just a rand()
return obj;
}
int main()
{
int decision;
std::string name;
std::vector<Employee> employees;
Employee some_new_employee;
std::cout << "Welcome mrs. manager. What do you want to do today, sir?" << std::endl << std::endl;
do
{
std::cout << "Hire sombody [1], Fire somebody [2], Exit [0] " << std::endl;
std::cin >> decision;
switch (decision)
{
case 1:
some_new_employee = generate_random_employee(some_new_employee);
if (should_i_employ(some_new_employee))
{
employees.push_back(some_new_employee);
}
break;
case 2:
std::cout << "Who do you want to fire?" << std::endl;
std::cin >> name;
if (is_the_employee_exist(employees, name))
{
if (are_u_sure())
{
}
}
else
std::cout << "" << std::endl;
break;
case 3:
std::cout << employees << std::endl;
break;
case 0:
std::cout << "Good bye, sir" << std::endl;
break;
default:
std::cout << "There is not these option. Try again " << std::endl;
}
} while (decision != 0);
system("pause");
}

Setting a string value to none when a class related to it is deleted

I need help with something which I believe is simple. I can assign a student to a project. But when I delete the project, the student is still keeping the project name. I'm thinking of just renaming it back to "None" but I have no idea on how to do that. Help?
Edit
map<int, Student> mstore and vector<int> storeid added.
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <map>
using namespace std;
class Human {
public:
virtual void print() const = 0;
};
class Student : public Human {
protected:
string studname;
int studId;
string project;
public:
Student();
Student (string studname, int studId) : studname("Unknown"), studId(0), project("None")
{
cout << "A student is created: Name = " << studname
<< ". Id = " << studId << endl;
}
virtual void print() const {
cout << "Name = " << studname << ". Id = " << studId << ". Project = " << project <<endl; }
void setSName (string sname) { studname = sname; }
void setSID (int sID) { studId = sID; }
void printStudentInfo() const;
void printStudentInfoline() const;
};
void Student::printStudentInfo() const
{
cout << "\nStudent name: " << studname << endl;
cout << "Student ID: " << studId << endl;
cout << "Project: " << project << endl;
}
void Student::printStudentInfoline() const
{
cout << studId << ", " << studname << ", " << project << endl;
}
class Project {
protected:
string projname;
public:
vector <Student> students;
vector <int> storeid;
Project (string projname) : projname(projname) { cout << "Project " << projname << " created" << endl;}
void setPName (string projname) { this->projname = projname; }
void add (int& sid)
{
//student.setProject (projname);
storeid.push_back(sid);
}
int returnid(int& a)
{
return storeid[a];
}
int returnsize()
{ return storeid.size(); }
void printproj() const {
cout << endl << projname << " list: \n";
cout << "Student(s) : " << endl;
for (int i = 0; i < storeid.size(); i++){
cout << storeid[i] << endl;
}
}
void printprojname() const {
cout << projname << endl;
}
};
int main() {
string StudentName;
string ProjectName;
int Studentid;
Student *s1;
Project *p1;
vector<Student> store;
vector<Project> projstore;
map<int, Student> mstore;
map<int, Student>::const_iterator itr;
for (int n=0; n<3; n++) //loop to create 3 students
{
cout <<"Enter name : ";
getline(cin, StudentName);
cout <<"Enter ID : ";
cin >> Studentid;
s1 = new Student(StudentName, Studentid);
s1->setSName(StudentName);
s1->setSID(Studentid);
store.push_back(*s1);
mstore.insert(make_pair(Studentid, *s1));
cin.get();
}
//print map
for(itr=mstore.begin(); itr!=mstore.end() ;++itr)
itr->second.printStudentInfo();
//itr=mstore.begin()+2;
//itr.print();
cout << "Enter project name: ";
getline(cin, ProjectName);
p1 = new Project(ProjectName);
p1->setPName(ProjectName);
//Assigning student to project
cout << endl;
cout << "How many students? :" ;
int y;
cin >> y;
for ( int i = 0; i < y; i++){
cout << "Who would you like to add to this project?" << endl;
int x = 1;
for(itr=mstore.begin(); itr!=mstore.end() ;++itr)
itr->second.printStudentInfoline();
int insID;
cout << "Enter ID number: ";
cin >> insID;
p1->add(insID);
/*
for ( it = store.begin(); it != store.end(); ++it ) {
// For each friend, print out their info
cout << x << ". ";
it->printStudentInfoline();
x++;
}
x = 1;
int insS;
cout << "Enter number: ";
cin >> insS;
p1->add(store[(insS-1)]); //stores selected student into the object
*/
cout << "\nAdding Student done\n" << endl;
}
projstore.push_back(*p1);
//Mstore finds for related ids and displays them accordingly
cout << "print project"<< endl;
vector<Project>::iterator pt;
for ( pt = projstore.begin(); pt != projstore.end(); ++pt ) {
pt->returnsize();
for (int i=0; i <pt->returnsize(); i++){
cout << pt->returnid(i) << endl;
itr=mstore.find(pt->returnid(i));
itr->second.printStudentInfo();
}
}
cout << endl;
cout << "Deleting project" << endl;
cout << "What would you like to remove?" << endl;
int x = 1;
//storeid will display ids. How do I link them to `store` map?
for ( pt = projstore.begin(); pt != projstore.end(); ++pt ) {
cout << x << ". ";
pt->printprojname();
x++;
}
//Now to delete the selected project
int delP;
cout << "Enter number: ";
cin >> delP;
cin.ignore();
system("pause");
projstore.erase(projstore.begin()+delP-1);
// Students
cout << "\n Current students" << endl;
for(itr=mstore.begin(); itr!=mstore.end() ;++itr)
itr->second.printStudentInfo();
}
Look at how you add a Student to a Project:
void add (Student& student)
{
student.setProject (projname);
students.push_back (student); // <-- AHA!
}
First you assign the Project name to the Student, then the Project stores a copy of the Student. After that, the Project has no link to the original Student, and can't inform him/her of its own demise when the time comes.
You'll have to rethink this design; there are three major options: 1) the Students can look up their respective Projects in the store, 2) the Project can look up its Students in the students vector, or 3) the Project owns the Students (in which case they should probably be GraduateStudents).
EDIT:
If that's the way you want to do it, use map<int, Student> store to store the Students, using ID number as an index. Then a Project can have a vector<int> (or set<int>) of student ID numbers. It can look Students up in the store with ease.
EDIT:
To print out the entire collection of students:
for(map<int, Student>::const_iterator itr=store.begin(); itr!=store.end() ;++itr)
itr->second.print();
EDIT:
If the Project has a vector<int> of student ID numbers, then what argument do you think Project::add(?) should take?
EDIT:
The Project can act on a Student by means of the student ID number and access to mstore:
// in Project:
mstore[id].whatever()
EDIT:
Sometimes asking the right question -- or in this case, phrasing the question correctly -- is half the battle. 'Now how do I change "None" to the inserted project name?' A better way to put it is 'How does the Project change one of its Student's project from "None" to projname?' Once you put it that way, the answer is almost obvious:
// in Project:
mstore[id].setSProject(projname);
Note that Student does not yet have setSProject(string), you'll have to add it. Also, note that this solution is not ideal since 1) anybody can change a Student's project, and 2) a Student's project need not actually be the name of a real Project. There is more than one way to deal with these problems.