C++: calling function from vector object in main - c++

I am trying to call printTotals() from main(). I tried person.printTotals() but it does not work because agent only calls functions within the vector STL. I checked other answers, such as C++ Calling Vectors from Function to Main and Using vector of user defined class type objects and How to create a vector of class objects in C++?.
I also checked my STL book, but this case it is not in there.
I have two questions:
Is there a way to call printTotals() outside of the constructor? Can I call it from main()? I want to keep my code clean and modular, but I am unable to access it outside of the constructor.
Each person has 3 neighbors consisting of Persons in a vector. I thought about declaring the neighbors vector like this, but was not sure:
vector<Person> neighbor
For a specific person with id = 3, how can I retrieve their second neighbor's voting status? Would it be:
person[3].neighbor[1].getPersonVotingStatus()?
This is my code:
Person.h
#include <iostream>
#include <string.h>
#include <vector>
class Person
{
public:
Person();
Person( std::vector<Person> person, maxPersons);
std::string getPersonVotingStatus(int ID);
void printTotals();
private:
std::string personName;
float personHeight;
int personID;
std::string isVoter;
vector<Person>neighbor; // <---
}
Person.cpp
#include <iostream>
#include <string.h>
#include <vector>
Person::Person()
{}
Person::Person(int pID, float pHeight, std::string pName, std::string isV)
{
personID = pID;
personHeight = pHeight;
personName = pName;
isVoter = isV;
}
Person::Person( std::vector<Person> person, int maxPersons)
{
for(int = 0; i < maxPersons; i++)
{
person[i].personID = i;
person[i].personHeight = i + 100;
person[i].personName = "testName";
if (i / 2 = 0) {
person[i].isVoter = "yes";
}
else {
person[i].isVoter = "no";
}
}
Person(person[i].personID, person[i].personHeight, person[i].personName, person[i].isVoter);
}
std::String getPersonVotingStatus( int ID)
{
return person[i].isVoter;
}
void printTotals( std::vector<Person> person)
{
int totalVoter = 0;
int totalNonvoter = 0;
for (int i = 0; i< person.size(); i++)
if (person[i].isVoter == "yes") {
totalVoter++;
}
else {
totalNonvoter++;
}
}
main.cpp
#include <iostream>
#include <string.h>
#include <vector>
int main()
{
int maxPersons = 10;
std::vector<Person> person;
Person obj( person, maxPersons);
person.printTotals(); // <--
return 0;
}

Try defining printTotals() as a static function:
class Person
{
public:
static void printTotals(std::vector<Person> person);
}
Then you can call it in main like this:
Person::printTotals(person);

Related

How to fix: Exception thrown: read access violation. **_Pnext** was 0xFDFDFE05

I'm trying to "build" a house which contains rooms. My teacher told me to do it with composition. My idea was to generate as many Rooms objects as many rooms my house has. I tried it with the following code but in the house.cpp's constructor my for cycle runs only once than it crashes at the line rooms[i] = load; with Exception thrown: read access violation.
_Pnext was 0xFDFDFE05.
Here's my code:
main.cpp:
'''
#include <iostream>
#include "House.h"
#include "Rooms.h"
using namespace std;
int main()
{
Rooms basic("basic");
House house(basic,2);
house.setRooms();
house.setWhichroom(1);
cout << house.getRooms().getRoomname();
return 0;
}
'''
house.h:
'''
#pragma once
#include <iostream>
#include <string>
#include "Rooms.h"
using namespace std;
class House
{
Rooms* rooms;
unsigned roomcount;
unsigned whichroom = 0;
public:
House();
House(const Rooms&, unsigned);
House(unsigned);
~House();
void setRoomcount(unsigned);
unsigned getRoomcount()const;
void setWhichroom(unsigned );
unsigned getWhichroom()const;
void setRooms();
Rooms getRooms()const;
};
'''
house.cpp:
'''
#include "House.h"
House::House(const Rooms& load, unsigned rc)
{
roomcount = rc;
for (int i = 0; i < roomcount; i++)
{
rooms = new Rooms;
rooms[i] = load;
}
}
House::House(unsigned x):roomcount(x)
{
}
House::~House()
{
roomcount = 0;
delete rooms;
}
void House::setRoomcount(unsigned x)
{
roomcount = x;
}
unsigned House::getRoomcount() const
{
return roomcount;
}
void House::setWhichroom(unsigned x)
{
whichroom = x;
}
unsigned House::getWhichroom() const
{
return whichroom;
}
void House::setRooms()
{
for (unsigned i = 1; i <= roomcount; i++)
{
char c = i;
string s = "room";
s += c;
rooms[i].setRoomname(s);
}
}
Rooms House::getRooms() const
{
return rooms[whichroom];
}
'''
rooms.h:
'''
#pragma once
#include <iostream>
#include "Things.h"
using namespace std;
class Rooms
{
protected:
string roomname;
Things things;
public:
Rooms();
Rooms(string);
~Rooms();
void setRoomname(string);
string getRoomname()const;
void setThings();
unsigned getThings()const;
};
'''
rooms.cpp:
'''
#include "Rooms.h"
Rooms::Rooms()
{
}
Rooms::Rooms(string name)
{
roomname = name;
}
Rooms::~Rooms()
{
}
void Rooms::setRoomname(string name)
{
roomname = name;
}
string Rooms::getRoomname() const
{
return roomname;
}
void Rooms::setThings()
{
things.setOnoff();
}
unsigned Rooms::getThings() const
{
return things.getOnoff();
}
'''
The problem is in the House constructor, where you have
for (int i = 0; i < roomcount; i++)
{
rooms = new Rooms;
rooms[i] = load;
}
You will create one single Rooms object, but treat it as an array of multiple rooms.
You also create and create and create new Room objects each iteration of the loop, making you loose the earlier objects.
The simple solution, if you need to continue to use explicit memory handling yourself, is to allocate the objects once and before the loop:
rooms = new Rooms[roomcount];
for (int i = 0; i < roomcount; i++)
{
rooms[i] = load;
}
Since you now use new[] you must match it with a delete[] in the destructor. And you need to learn about the rules of three and five.
To simplify your code I implore you to use a std::vector instead, as that will make life so much simpler for you as a C++ programmer.

Trouble with printing C++ Hash Table

I'm pretty new to C++ and am trying to teach myself how to implement a hash table(I know I could use unordered_map, but I'm challenging myself). Right now I have a vector of structs(cell) that holds person-specific information. I have a PrintTable function that I want to use to print out each struct member of every item in the table. However, I can't seem to access the specific members of the struct(cell). What am I doing wrong here?
#include <iostream>
#include <string>
#include <vector>
struct cell
{
std::string name;
int age;
std::string weapon;
};
class HashTable
{
private:
std::vector<cell> *table;
int total_elements;
int getHash(int key)
{
return key % total_elements;
}
public:
HashTable(int n)
{
total_elements = n;
table = new std::vector<cell>[total_elements];
}
void SearchTheTable(int hashIndex);
void AddItem(std::string name, int age, std::string weapon);
void RemoveItem();
void PrintTable();
};
void HashTable::SearchTheTable(int hashIndex)
{
int x = getHash(hashIndex);
std::cout << x;
}
void HashTable::AddItem(std::string name, int age, std::string weapon)
{
cell newCell = { name, age, weapon };
table->push_back(newCell);
}
void HashTable::RemoveItem()
{
}
void HashTable::PrintTable()
{
for (int i = 0; i < table->size; i++)
{
std::cout << table[i].name; // Right here I get an error that says: class "std::vector<cell, std::allocator<cell>>" has no member "name".
}
}
int main()
{
HashTable theTable(5);
theTable.AddItem("Ryan", 27, "Sword");
theTable.AddItem("Melony", 24, "Axe");
theTable.PrintTable();
}

How do I add an object to an array in c++?

Im playing around with a tiny c++ project. Im trying to add an object of person (from my Person class) into an Array.
But when i run my code it tells me that Person struct is NULL.
However, it also sais that my person got a name and an adress, so it doesnt seem like its null?
I have a Person class:
.h
{
public:
std::string name;
std::string adress;
Person() = default;
Person(std::string name, std::string adress);
void Print();
~Person();
};
.cpp
#include "Person.h"
#include <iostream>
#include <string>
Person::Person(std::string name, std::string adress)
{
this->name = name;
this->adress = adress;
}
void Person::Print()
{
std::cout << "Namn: " << name << ". Adress: " << adress << std::endl;
}
Person::~Person()
{
}
I Have an PersonRegister class:
.h
#include "Person.h"
class PersonReg
{
public:
int indexInt = 0;
int maxSize = 50;
Person *person;
PersonReg() = default;
PersonReg(int maxSize);
void AddPerson(Person *person);
void PrintPersons();
void DeletePerson(Person *person);
~PersonReg();
};
.cpp
#include <string>
#include "Person.h"
PersonReg::PersonReg(int maxSize)
{
this->maxSize = maxSize;
person = new Person[maxSize];
}
void PersonReg::AddPerson(Person *person)
{
person[indexInt++] = *person;
}
void PersonReg::PrintPersons()
{
for (Person* personPtr = person; personPtr != person + maxSize; ++personPtr)
{
personPtr->Print();
}
}
void PersonReg::DeletePerson(Person *person)
{
if (person != nullptr)
{
for (Person *personPtr = person; personPtr != person + maxSize; ++personPtr)
{
personPtr->name = "NO NAME";
}
}
}
PersonReg::~PersonReg()
{
delete[]person;
}
When I execute it, I get the Error:
Exception thrown at 0x7AFC3729 (vcruntime140d.dll) in Labb3_c++.exe: 0xC0000005: Access violation writing location 0xCCCCCCCC.
But in the output, I can see that person name and adress has values.
Im reading to PersonReg from a text-file like this. This is my main:
#include "pch.h"
#include <iostream>
#include <fstream>
#include "Person.h"
#include "PersonReg.h"
bool ReadReg(PersonReg& reg, std::string fileName)
{
std::string line;
std::ifstream myfile(fileName);
if (myfile.is_open())
{
while (getline(myfile, line))
{
while (line.length() == 0 && getline(myfile, line))
;
std::string name(line);
std::string adress;
getline(myfile, adress);
reg.AddPerson(&Person(name, adress));
}
myfile.close();
return true;
}
else {
std::cout << "Unable to open file";
return false;
}
}
void Test1(Person* person, PersonReg personReg)
{
ReadReg(personReg, "PersonExempel.txt");
personReg.PrintPersons(); std::cout << "\n\n";
personReg.DeletePerson(person);
}
int main()
{
Person *person = new Person();
PersonReg personReg = PersonReg();
Test1(person, personReg);
delete person;
return 0;
};
Im supposed to add a person in my personArray.
Then print the person with a simple print function.
And then delete the Person again.
EDIT: Sorry for long post but Im not sure where the problem is located (besides the memory). Im a totally beginner is C++ so it sure can look like a mess!
Take a look at this code:
void PersonReg::AddPerson(Person *person)
{
person[indexInt++] = *person;
}
You are using person on both left and right side. But what is person here? Is it the passed argument? Is it the member variable of the class?
It seems that you want the LHS to be the member variable while you want the RHS to be the passed argument. But how do you expect the compiler to know that?
You can use this->person to explicit refer to the member variable. However, I'll recommend a renaming of the member variable to something like personArray or a renaming of the argument like: void PersonReg::AddPerson(Person *pers).
Further:
PersonReg personReg = PersonReg();
Shouldn't this be
PersonReg personReg = PersonReg(42);
^^
some number
so that you call the intended constructor, i.e. the constructor that calls new and reserve memory for the array.
All that said - I'll recommend that you use std::vector instead of an array allocated using new
First of all the maxSize is not getting the value of 50. That's why there is not object Person. You should delete the PersonReg() = default; and keep the other constructor like this PersonReg(int maxSize=50);
As #PeterT mentioned you had a problem in this function. this-> should fix it:
void PersonReg::AddPerson(Person *person)
{
this->person[indexInt++] = *person;
}
I corrected a few other things. PrintPersons could be this way and it works:
void PersonReg::PrintPersons()
{
for(int i=0; i<indexInt; i++){
person[i].Print();
}
}
Also on the DeletePerson function I cannot understand what exactly you want to do. If you want to delete a spesific person you should change the function to this:
void PersonReg::DeletePerson(Person *person)
{
if (person != nullptr)
{
for(int i=0; i<indexInt; i++){
if(this->person[i].name==person->name&&this->person->adress==person->adress){
this->person->name="NO NAME";
this->person->adress="NO ADDRESS"; //or something like that.
}
}
}
}
I tested all of these and they work. I hope I helped.

Printing vector out in functions

I need to print the vector i have filled in listInput. When i go to listPrint the program crashes. What can i do to fix it? Here is my main:
#include <iostream>
#include <string>
#include <vector>
#include "func.h"
using namespace std;
int main(int argc, char** argv) {
subjects a;
int r=1;
while(r!=0){
int select=a.userChoice();
switch(select){
case 1:
a.listPrint();
break;
case 2:
listInput(a);
break;
}
}
return 0;
}
My header:
#ifndef SUBJECT
#define SUBJECT
#include <string>
#include <vector>
class subjects{
private:
std::string subjectName;
std::string lectName;
std::string lectSurname;
int credits;
int studentnum;
public:
/* subjects(){
subjectName="";
lectName="";
lectSurname="";
credits=0;
studentnum=0;
}*/
int userChoice();
int enterNumber(std::string name);
void menu();
std::string getSubjectName(){
return subjectName;
}
std::string getLectName(){
return lectName;
}
std::string getLectSurname(){
return lectSurname;
}
int getCredits(){
return credits;
}
int getStudentNum(){
return studentnum;
}
friend void listInput(subjects a);
void listPrint();
bool checkName(std::string &text);
std::vector<subjects*> entry;
subjects(const std::string subjectName="", const std::string lectName = "", const std::string lectSurname="", const int credits = 0, const int studentnum = 0) :
subjectName(subjectName),
lectName(lectName),
lectSurname(lectSurname),
credits(credits),
studentnum(studentnum){
}
};
#endif
And my function file:
void listInput(subjects a){
.
.
.
a.entry.push_back(new subjects(a.subjectName, a.lectName,a.lectSurname,a.credits, a.studentnum));
}
void subjects::listPrint(){
for(int i=0; i<entry.size(); i++){
cout<<entry[i]->getSubjectName()<<" "<<entry[i]->getLectName()<<" "<<entry[i]->getLectSurname()<<" "<<entry[i]->getCredits()<<" "<<entry[i]->getStudentNum()<<endl;
}
}
I know that using friend functions arent recommended, but i am required to use atleast one of them. Also if i print the vector in listInput, then it only prints the first entry. If there is more than one entry in the vector, it also crashes.
You pass the a instance by value to the list function and then you try to print it. You should consider passing it by reference if you plan to use it outside the scope of the list function.

C++ vector erase method delete my object

I first get an object A from the vector, then I call the erase method to destroy that object in my vector because I don't need it anymore. However, from the debugger, I found that the object A I got before calling erase method is also destroyed. I don't understand that because I thought that what I got is a copy of that object and erase method should have nothing to do with my object A.
Code
Class Unit
Header file
#ifndef UNIT_H
#define UNIT_H
#include <iostream>
class Unit
{
protected:
int id;
public:
Unit::Unit(int num = -1);
virtual ~Unit() = default;
virtual int getID();
};
#endif
CPP file
#include "Unit.h"
Unit::Unit(int num)
{
id = num;
}
int Unit::getID()
{
return id;
}
Class Box
Header file
#ifndef BOX_H
#define BOX_H
#include <string>
#include <iostream>
#include "Unit.h"
class Box : public Unit
{
private:
std::string* type;
int* val;
public:
Box::Box();
~Box();
int getVal();
std::string getName();
int getID() override;
};
#endif
CPP file
#include <time.h>
#include "Box.h"
Box::Box() : Unit(5)
{
int tmp = rand() % 3;
if (tmp == 0)
{
type = new std::string("hp"); // health cur
val = new int(rand() % 10 + 1);
}
else if (tmp == 1)
{
type = new std::string("exp"); // skill level or health max
val = new int(rand() % 5 + 1);
}
else
{
type = new std::string("punish"); // minus health cur
val = new int(-1);
}
}
Box::~Box()
{
delete type;
delete val;
}
int Box::getVal()
{
return *val;
}
std::string Box::getName()
{
return *type;
}
int Box::getID()
{
return id;
}
main file
using namespace std;
int main()
{
Box test;
std::vector<Box> bag;
bag.push_back(test);
Box tmp = bag[0];
bag.erase(bag.begin() + 0);
cout << tmp.getVal();
system("pause");
return 0;
}
Below is the screenshot from the debugger and because I don't have 10 reputations, I can't display it directly.
before
after
As you can see, the "type" and "val" data member of class Box is modified.
Check out this page about the return type from the index call
http://en.cppreference.com/w/cpp/container/vector/operator_at
I believe that you may have a reference, not a different object.