How to access private member - array with friend function - c++

I am new to C++ and I write code to see how friend functions work. Here are two classes and I ask the user in friend function for parameters, which if they are equal with the values of the member variables, to be displayed. And I can't access one of the private members - the array with the country names. In the function int elcountry(element &e, supply s) I am trying to display the number of elements which are of a certain type and from a particular country. The error is that member supply::country, (s.country[i]) in elCountry function is inaccessible. I don't know how to use getCountry() function to access the private array.
class element {
friend class supply;
private:
string name;
double value;
int serial;
public:
element();
int elCountry(element &e, supply &s);
double* nominals(element &e, supply &s);
string getName() {
return name;
}
int getSerial() {
return serial;
}
};
class supply {
private:
int serial;
string country[5];
int n;
public:
supply();
string* getCountry() {
string country = new string[5];
return country;
}
friend int elCountry(element &e, supply &s);
friend double* nominals(element &e, supply &s);
};
int elcountry(element &e, supply s){
string names, Country;
int n;
cout << "enter country = "; cin >> Country;
cout << "enter name of the element = "; cin >> names;
cout << "enter number of elements = "; cin >> n;
for (int i = 0; i < 5; i++) {
if (Country == s.country[i] && names == e.getName() && n == e.getSerial()) {
cout << "the country is " << count << endl;
cout << "the name is" << names << endl;
cout << "the number is " << n << endl;
}
}
return n;
}

The signature of two functions don't match, they're irrelevant, it's not friend function at all.
friend int elCountry(element &e, supply &s);
~ ~
int elcountry(element &e, supply s){
~
Note that the names don't match either.

Related

How to allow user input to indicate a size of an array? The array has to be a dynamically allocated array of type Person which is the class

This is what I have so far, and it does give me the desired output, but I couldn't figure out how to use a dynamically allocated array. I wanted to figure out the problem without that first, so I can figure out how the rest of the code would work.
Instead of using a constant variable for the size of the array, how can I have the user input a desired amount that would then be used for the array?
class Person
{
private:
string name;
int age;
public:
// Default constructor
Person()
{
name = " ";
age = 0;
}
Person(string name1, int age1)
{
name = name1;
age = age1;
}
int getAge() { return age; }
string getName() { return name; }
// Mutator functions to set name and age
void setName(string name1);
void setAge(int age1);
};
int lengthOfName(Person *p);
// Main Function
int main()
{
string name;
int age;
const int SIZE = 3;
Person personArray[SIZE];
for (int i = 0; i < SIZE; i++)
{
cout << "Enter the name:" << endl;
cin >> name;
personArray[i].setName(name);
cout << "Enter the age:" << endl;
cin >> age;
personArray[i].setAge(age);
}
for (int i = 0; i < SIZE; i++)
{
cout << "The name " << personArray[i].getName();
cout << " has length: " << lengthOfName(&personArray[i]) << endl;
}
}
// Returns the number of characters in a person's name *
int lengthOfName(Person *p)
{
string name = p->getName();
return name.length();
}
// Mutator function that sets variable name
void Person::setName(string name1)
{
name = name1;
}
// Mutator function that sets variable age
void Person::setAge(int age1)
{
age = age1;
}
Dynamic arrays are allocated using the new[] operator, and freed using the delete[] operator, eg:
size_t size;
cin >> size;
Person *personArray = new Person[size];
...
delete[] personArray;
However, you should use std::vector instead and let it manage the memory for you:
#include <vector>
size_t size;
cin >> size;
std::vector<Person> personArray(size);
...

How to update the members of objects in the array constructed from another class?

I have 2 separate classes in C++,which are Algorithms class and Student class, each of have the following members and methods.
#include <iostream>
using namespace std;
#define MAX 10
class Student {
private:
int ID;
string name;
string surname;
int quiz_scores[4];
public:
Student()
{
ID = 0;
name = "" ;
surname = "";
quiz_scores[4] = {0};
}
void setID(int ID_set);
int getID();
void setName(string name_set);
string getName();
void setSurName(string surname_set);
string getSurName();
void setQuizScores(int* quizscores);
const int* getQuizScores() const;
};
and Algorithms class as follows:
class Algorithms{
private:
Student students[MAX];
int num =0 ; // The current number of students in the course, initially 0.
float weightQ;
float weightHW;
float weightF;
public:
Algorithms()
{
students[num] = {};
weightQ = 0.3;
weightHW = 0.3;
weightF = 0.4;
}
int getNum(); // Returns how many students are in the course
void addNewStudent(Student new_student);
And here is the methods declerations of Student class and Algorithms class respectively.
// Method declerations for the class Student
void Student :: setID(int ID_set){
ID = ID_set;
}
int Student :: getID(){
return ID;
}
void Student :: setName(string name_set){
name = name_set;
}
string Student :: getName(){
return name;
}
void Student :: setSurName(string surname_set){
surname = surname_set;
}
string Student :: getSurName(){
return surname;
}
void Student :: setQuizScores(int* quizscores){
for(int i = 0; i<4; i++){
quiz_scores[i] = quizscores[i];
}
}
const int* Student :: getQuizScores() const {
return quiz_scores; }
// Method declerations for the class Algorithms
int Algorithms:: getNum(){
return num;
}
void Algorithms :: addNewStudent(Student new_student){
students[num] = new_student ;
num = num + 1;
}
void Algorithms :: updateWeights(float weightQ_update, float weightHW_update, float weightF_update){
weightQ = weightQ_update;
weightHW = weightHW_update;
weightF = weightF_update;
}
void Algorithms :: getStudentInfo(int ID_given, Algorithms &algorithms){
for(int i = 0; i<MAX; i++){
if(ID_given == students[i].getID()){
cout << "Student Name & Surname : " << students[i].getName() << " " << students[i].getSurName()<<"\n";
cout << "Quiz results :" << students[i].getQuizScores();
}
}
}
I have also user-interface in the main. It calls the following functions
void addNewStudent(int ID, string name, string surname, Algorithms &algorithms){
Student student;
student.setID(ID);
student.setName(name);
student.setSurName(surname);
algorithms.addNewStudent(student);
}
void showStudent(int ID, Algorithms &algorithms){
algorithms.getStudentInfo(ID, algorithms);
}
Both work properly with the code in main as below
int main(){
Algorithms ECE101;
int x;
int ID;
string name, surname;
string option_1 = "1) Add a student ";
string option_2 = "2) Search a student by ID";
string option_3 = "3) Change a student’s score";
cout << "Welcome to the ECE101 Classroom Interface"<<"\n";
cout << "Choose your option\n";
cin >> x;
do {
if (x == 1) {
cout << "Enter the student ID ";
cin >> ID;
cout << endl;
cout << "Enter the student name ";
cin >> name;
cout << endl;
cout << "Enter the student surname " ;
cin >> surname;
addNewStudent(ID, name, surname, ECE101);
}
else if (x==2){
cout << "Enter the student ID\n";
cin >> ID;
showStudent(ID, ECE101);
}
else {
int quiz_grades[4];
cout << "Enter the student ID";
cin >> ID;
cout << endl;
cout << "Enter the quiz grades" << endl;
for (int i = 0 ; i<4 ; i++) {
cin >> quiz_grades[i];
}
changeStudentScores(ID, quiz_grades);
}
The problem here comes from changeStudentScores(ID, quiz_grades, ECE101)
What I want to do is the program should take the array of 4 numbers(corresponds to the quiz grades) and set to the student, whose ID's given by the user. (Of course, firstly the student should be added to the course by the option 1) BUT, I could not pass the array to the changeStudentScores , where it is implemented by
void changeStudentScores(int ID, int* quizscores ){
// Problem occurs here, creating new students object is not so logical, but I tried.
Student student;
student.setID(ID);
student.setQuizScores();
// I just try to pass the quiz grades writing by the user to the set method, which set quiz grades to the students.
After choose the option 2 which shows the information about the students given the ID, I see the correct name and surname, but I could not update the quiz grades.
RESTRICTIONS:
There should be no other method and data members other than the written methods and data members.
But we can implement additional methods and functions (but not class data
members)
getStudentInfo(int ID_given, Algorithms &algorithms) function must return student information given ID, but my implementation I could use with void
QUESTIONS:
How can I implement correctly the changeStudentScores function so that the user can update the existing student quiz score?
My getStudentInfo(int ID_given, Algorithms &algorithms) function returns nothing that I can use for getting information. So need to be returned the student information, so the return type must not be void.
What is the general idea behind updating the members of the objects, which are used in another class with some data structure(here is array.)

Exception has occured, unknown signal error when using class object again inside each function

I'm trying to write a C++ code for a course I'm enrolled in, where I keep the information of the students enrolled in the course.
I should be able to add a student to the classrrom in the user interface written in main , by calling the function void addNewStudent(int ID, string name, string surname), where I create my object instances, Student, and Course inside the function.
I should also be able to search by given ID by calling the function void showStudent(int ID) in the main, where the function uses the getStudent(ID) method of the object of the classCourse
I did not write all the methods, but when I try to debug this code, I got the error " Exception has occured, unknown signal error."
My questions are:
What is the reason of this error? How can I fix it?
Suppose that the user interface in the main is necessary to use as well as the functions it calls. Do I have to create a class object again inside each function as I wrote?
Can a more effective implementation be made in accordance with the object oriented principles I have defined above?
#include <iostream>
using namespace std;
#define MAX 10
class Student {
private:
int ID;
string name;
string surname;
public:
Student()
{
ID = 0;
string name = "" ;
string surname = "";
}
void setID(int ID_set);
int getID();
void setName(string name_set);
string getName();
void setSurName(string surname_set);
string getSurName();
};
class Course {
private:
Student students[MAX];
int num =0 ; // The current number of students in the course, initially 0.
float weightQ;
float weightHW;
float weightF;
public:
Course()
{
students[num] = {};
weightQ = 0.3;
weightHW = 0.3;
weightF = 0.4;
}
int getNum(); // Returns how many students are in the course
void addNewStudent(Student new_student);
void updateWeights(float weightQ_update, float weightHW_update, float weightF_update);
void getStudent(int ID_given);
};
// Method declerations for the class Student
void Student :: setID(int ID_set){
ID = ID_set;
}
int Student :: getID(){
return ID;
}
void Student :: setName(string name_set){
name = name_set;
}
string Student :: getName(){
return name;
}
void Student :: setSurName(string surname_set){
surname = surname_set;
}
string Student :: getSurName(){
return surname;
}
// Method declerations for the class Course
int Course :: getNum(){
return num;
}
void Course :: addNewStudent(Student new_student){
students[num] = new_student ;
num = num + 1;
}
void Course :: updateWeights(float weightQ_update, float weightHW_update, float weightF_update){
weightQ = weightQ_update;
weightHW = weightHW_update;
weightF = weightF_update;
}
void Course :: getStudent(int ID_given){
for(int i = 0; i<MAX; i++){
if(ID_given == students[i].getID()){
cout << "Student Name & Surname : " << students[i].getName() << " " << students[i].getSurName()<<"\n";
}
}
}
void addNewStudent(int ID, string name, string surname){
Student student;
Course ECE101;
student.setID(ID);
student.setName(name);
student.setSurName(surname);
ECE101.addNewStudent(student);
}
void showStudent(int ID){
Course ECE101;
ECE101.getStudent(ID);
}
int main(){
Course ECE101;
cout << "Welcome to the ECE101 Classroom Interface"<<"\n";
cout << "Choose your option\n";
string option_1 = "1) Add a student ";
string option_2 = "2) Search a student by ID";
cout << "Enter your option: ";
int x;
int ID;
string name, surname;
cin >> x;
if (x == 1)
cout << "Enter the student ID ";
cin >> ID;
cout << endl;
cout << "Enter the student name ";
cin >> name;
cout << endl;
cout << "Enter the student surname " ;
cin >> surname;
addNewStudent(ID, name, surname);
return 0;
}
 To make the menu more interactive you could add a do while statement that would accept 3 options:
register
show data
exit
int main(){
Course ECE101;
int x;
int ID;
string name, surname;
string option_1 = "1) Add a student\n";
string option_2 = "2) Search a student by ID\n";
cout << "Welcome to the ECE101 Classroom Interface\n";
cout << "Choose your option\n";
cout << option_1 << option_2;
cin >> x;
do {
if (x == 1) {
cout << "Enter the student ID ";
cin >> ID;
cout << endl;
cout << "Enter the student name ";
cin >> name;
cout << endl;
cout << "Enter the student surname " ;
cin >> surname;
addNewStudent(ID, name, surname, ECE101);
}
else {
cout << "Enter the student ID\n";
cin >> ID;
showStudent(ID, ECE101);
}
cout << "Choose your option\n";
cin >> x;
} while(x != 3);
return 0;
}
addnewStudent() and showStudent() methods now accepts an instance of Course as an argument to be able to add students.
void addNewStudent(int ID, string name, string surname, Course &course) {
Student student;
student.setID(ID);
student.setName(name);
student.setSurName(surname);
course.addNewStudent(student);
}
void showStudent(int ID, Course &course) {
course.getStudent(ID, course);
}
the function is modified from the same class as well.
void Course::getStudent(int ID_given, Course &course) {
for(int i = 0; i<MAX; i++){
if(ID_given == students[i].getID()){
cout << "Student Name & Surname : " << students[i].getName() << " " << students[i].getSurName()<<"\n";
}
}
}
Demo
Your addNewStudent function creates a new course everytime it is called. You could pass a reference to the course as a parameter into the function and call Course.addNewStudent(student). You'll want to make sure you specify it's a reference though when you define your function or you'll just create a copy of the course.

How to print a string from an object?

I tried the below code to write an object to a dat file:
#include<iostream>
#include<fstream>
#include<string>
#include<string.h>
using namespace std;
class Student
{ //data members
int adm;
string name;
public:
Student()
{
adm = 0;
name = "";
}
Student(int a,string n)
{
adm = a;
name = n;
}
Student setData(Student st) //member function
{
cout << "\nEnter admission no. ";
cin >> adm;
cout << "Enter name of student ";
cin.ignore();
getline(cin,name);
st = Student(adm,name);
return st;
}
void showData()
{
cout << "\nAdmission no. : " << adm;
cout << "\nStudent Name : " << name;
}
int retAdmno()
{
return adm;
}
};
/*
* function to write in a binary file.
*/
void demo()
{
ofstream f;
f.open("student.dat",ios::binary);
for(int i = 0;i<4;i++)
{
Student st;
st = st.setData(st);
f.write((char*)&st,sizeof(st));
}
f.close();
ifstream fin;
fin.open("student.dat",ios::binary);
Student st;
while(!fin.eof())
{
fin.read((char*)&st,sizeof(st));
st.showData();
}
}
int main()
{
demo();
return 0;
}
But when I am executing the demo function I am getting some garbage values from the "student.dat"
file. I am creating a database and want to get the records but I am not able to get all the records in the dat file.
Please suggest a solution
You cannot write complex data types to a file in binary mode. They have some additional variables and functions inside,which you do not know or see. Those data types have some internal state that or context dependent. So, you cannot store in binary and then reuse it somewhere else. That will never work.
The solution is serialization/deserialization.
This sounds complicated, but is not at all in your case. It basically means that all your data from your struct shall be converted to plain text and put in a text-file.
For readin the data back, it will be first read as text, and then converted to your internal data structures.
And the default approach for that is to overwrite the inserter << operator and extractor >> operator.
See the simple example in your modified code:
#include<iostream>
#include<fstream>
#include<string>
#include<iomanip>
class Student
{ //data members
int adm;
std::string name;
public:
Student()
{
adm = 0;
name = "";
}
Student(int a, std::string n)
{
adm = a;
name = n;
}
Student setData(Student st) //member function
{
std::cout << "\nEnter admission no. ";
std::cin >> adm;
std::cout << "Enter name of student ";
std::getline(std::cin>> std::ws, name);
st = Student(adm, name);
return st;
}
void showData()
{
std::cout << "\nAdmission no. : " << adm;
std::cout << "\nStudent Name : " << name;
}
int retAdmno()
{
return adm;
}
friend std::ostream& operator << (std::ostream& os, const Student& s) {
return os << s.adm << '\n' << s.name << '\n';
}
friend std::istream& operator >> (std::istream& is, Student& s) {
return std::getline(is >> s.adm >> std::ws, s.name);
}
};
/*
* function to write in a binary file.
*/
void demo()
{
std::ofstream f("student.dat");
for (int i = 0; i < 4; i++)
{
Student st;
st = st.setData(st);
f << st;
}
f.close();
std::ifstream fin("student.dat");
Student st;
while (!fin.eof())
{
fin >> st;
st.showData();
}
}
int main()
{
demo();
return 0;
}

Creating a vector in class then using class object in function not working

I have a class Employees. I'm trying to make the user insert and delete an employee but it's not working. The size of the vectors should be 500.
class Employees{
public:
int maxx = 500;
vector<string> Surname;
vector<string> FirstName;
vector<string> birthdate;
int vacation[500];
public:
Employees() : Surname(500) {}
};
This is the function that inserts, but printing elements of the vectors is not working at all:
void Process(Employees ZZ){
string dateyear;
string datemonth;
string dateday;
int dateyear1;
int datemonth1;
int dateday1;
int Realage;
int Vacationi = 0;
for(int i = 0; i < 500; i++) {
string s;
cin >> s;
string d;
cin >> d;
string c;
cin >> c;
ZZ.Surname.push_back(s);
ZZ.FirstName.push_back(d);
ZZ.birthdate.push_back(c);
cout << endl << ZZ.Surname[1] << endl;
}
Now the delete function, if I input a string then search for it in the vector then get his index then delete, but the vector doesn't update any values.
void DeleteEmployee(Employees ZZ){
cout<< endl << ZZ.Surname[1] << endl ;
for (int i = 0; i < ZZ.Surname.size(); i++){
cout << ZZ.Surname[i] ;
}
cout << " delete employee";
string delete1;
cin >> delete1;
auto it = std::find(ZZ.Surname.begin(), ZZ.Surname.end(), delete1);
if (it == ZZ.Surname.end())
{
cout<< " name not in vector " << endl;
}
else
{
//auto index = distance(Names.begin(), find(Names.begin(), Names.end(), old_name_)));
//ZZ.Surname.erase(ZZ.Surname.begin()+index) ;
}
}
This is the main function, also the values of the vector are not printing:
int main()
{
Employees ZZ;
Process(ZZ);
DeleteEmployee(ZZ);
cout << "fyccck";
for (int i = 0; i < ZZ.Surname.size(); i++){
cout << ZZ.Surname[i] ;
}
}
There are a lot of things wrong with this code. But the particular issue you are asking about is caused by your functions passing the Employees object by value, so a copy is made, and any changes you make to the copy are not reflected in the original object in main().
You need to change the parameters to pass the Employees object by reference instead:
void Process(Employees &ZZ)
void DeleteEmployee(Employees &ZZ)
That being said, the whole design of the code is not good in general. The vectors are not being kept in sync properly, and for that matter you are using more vectors then you actually need, 1 single vector will suffice. And Process() and DeleteEmployee() should be members of the Employees class, not separate functions. And they are both accessing out-of-bounds of the Surname vector.
I would suggest completely rewriting the code from scratch, for instance something more like this:
struct Employee{
string Surname;
string FirstName;
string BirthDate;
int Vacation;
string DisplayName() const { return Surname + ", " + FirstName; }
};
class Employees{
public:
static const int maxx = 500;
vector<Employee> employees;
Employees() { employees.reserve(maxx); }
bool Add(const Employee &e);
bool Delete(string Surname, string FirstName);
};
bool Employees::Add(const Employee &e) {
if (employees.size() < maxx) {
employees.push_back(e);
return true;
}
return false;
}
bool Employees::Delete(string Surname, string FirstName) {
auto it = std::find_if(employees.begin(), employees.end(),
[&](const Employee &e){
return e.Surname == Surname && e.FirstName == FirstName;
}
);
if (it != employees.end()) {
employees.erase(it);
return true;
}
return false;
}
int main()
{
Employees ZZ;
for(int i = 0; i < Employees::maxx; ++i) {
Employee e;
cin >> e.Surname;
cin >> e.FirstName;
cin >> e.BirthDate;
e.Vacation = 0;//cin >> e.Vacation;
ZZ.Add(e);
cout << endl << e.DisplayName() << endl;
}
cout << " delete employee";
string Surname, FirstName;
if (cin >> Surname >> FirstName) {
if (ZZ.Delete(Surname, FirstName)) {
cout << " name deleted from vector " << endl;
} else {
cout << " name not in vector " << endl;
}
}
cout << "fyccck";
for (auto &e : ZZ.employees) {
cout << e.DisplayName() << endl;
}
return 0;
}