I have got a problem with understanding the following code where I am trying to convert from the pointer to an object class Passenger* passenger to class Passenger passenger. I am not sure how I can modify my code to do perform the same functionality without the pointers. I am particularly confused with setting and comparing to NULL. Do I need to keep those if statements if I am no longer using the pointers? Any advises or suggestions would be appreciated.
class Seat
{
private:
class Passenger* passenger;
public:
Seat()
{
passenger = NULL;
}
~Seat()
{
if (passenger)
{
delete passenger;
passenger = NULL;
}
}
bool insertSeat(class Passenger* p)
{
bool bsuccess = TRUE;
if ( p != NULL )
{
if (passenger == NULL)
passenger = p;
else
bsuccess = FALSE;
}
else
passenger = NULL;
return bsuccess;
}
bool outputSeat(int row,int seat)
{
if (passenger)
cout << (passenger->toString()) << endl;
else
cout << "Empty " << row << seat+'A' << endl;
return passenger != NULL;
}
};
The simplest way is :
class Seat
{
private:
Passenger passenger;
public:
Seat()
{ }
void insertSeat( const Passenger& p ) // pass by const reference
{
passenger = p;
}
bool outputSeat( int row, int seat )
{
cout << passenger.toString() << endl;
}
};
You can always implement checking; eg : you don't want an invalid or default constructed passenger when passing it to
insertSeat() function :
bool insertSeat( const Passenger& p ) // pass by const reference
{
if( /* p.empty() or p.invalid() or whatever*/ ) return false; // implement empty() method
passenger = p;
return true
}
Related
I have a problem with queue, with deleting first elements. Pointer "nastepca" should store address of next structure variable in a queue, but it stores nullptr for all of data in the structure and I cannot fixed it. I have tried many option but none of them worked. Is my queue works properly, is it put data in correct way, address alongside address before?
dolacz() - means add/equeue
zdejmij() - means delete/dequeue
koniec - means end
#include <iostream>
#include <string>
using namespace std;
template<typename T>
class Kolejka
{
struct Element
{
T dane;
Element* nastepca;
Element(const T& dane, Element* nastepca) : dane(dane), nastepca(nastepca) {}
};
Element* start = nullptr; //pusty wskaznik nullptr
Element* koniec = nullptr; //pusty wskaznik nullptr
int licz_elementow = 0;
public:
void dolacz(const T& dane)
{
if (start == nullptr) //jezeli kolejka jest pusta to dodaj na poczatek (poczatek i koniec jest ten sam)
{
start = new Element(dane, start);
licz_elementow++;
}
else
{
ss++;
koniec = new Element(dane, koniec);
licz_elementow++;
}
}
void zdejmij() //nie działa
{
if (start == koniec)
{
start = koniec = nullptr;
licz_elementow--;
}
else
{
Element* tmp = start;
start = start->nastepca;
delete tmp;
licz_elementow--;
}
}
T& gora() //zwroci referencje typu T na początek kolejki
{
if (koniec == nullptr)
{
throw runtime_error("Pusta kolejka!");
}
return start->dane;
}
T& tyl() //zwroci referencje typu T na koniec kolejki
{
if (koniec == nullptr)
{
throw runtime_error("Pusta kolejka!");
}
return koniec->dane;
}
int rozmiar()
{
return licz_elementow;
}
bool pusty()
{
return start == nullptr;
}
};
class Auto
{
string marka;
friend ostream& operator <<(ostream& w, Auto& a); //zaprzyjaźniona funkcja przeciążająca operator <<
public:
Auto(string marka): marka(marka) {}
};
ostream& operator <<(ostream& w, Auto& a)
{
w << a.marka;
return w;
}
int main()
{
Kolejka <Auto> kol;
try
{
kol.dolacz(Auto("aaa"));
kol.dolacz(Auto("bbb"));
kol.dolacz(Auto("ccc"));
kol.dolacz(Auto("ddd"));
kol.zdejmij();
cout << "Liczba elementow: ";
cout << kol.rozmiar();
cout << endl;
cout << "Poczatek kolejki: ";
cout << kol.gora();
cout << endl;
cout << "Koniec kolejki: ";
cout << kol.tyl();
}
catch (runtime_error& BLAD)
{
cout << BLAD.what();
}
}
enter image description here
While debugging:
nastepca always have 0x00000000
start = new Element(dane, start);
should be
start = koniec = new Element(dane, nullptr);
When you add the first element, you should change the first and last pointers.
koniec = new Element(dane, koniec);
should be
Element* temp = new Element(dane, nullptr);
koniec->nastepca = temp;
koniec = temp;
When you add a new element (apart from the first) you need to make the old last element point to the new last element.
Pointer operations are tricky, you have to think carefully about what you are really doing. It might help to draw diagrams of the operations you have coded. That way you'd qucikly see that what you coded wasn't right.
I have the below program of an execution class which populates a map shown below
map<string,map<string,vector<StructAbsTypeObject>>>
Here I am making shared objects and assigning them which are valid during first check, but on second check shared_ptr returns null. I need to know the reason why. The code seems fine but don't know where is it going wrong.
//Code begins
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <memory>
using namespace std;
class Test {
public:
Test(int i):t(i) {
}
private:
int t;
};
class ConcTypeObject {
public:
ConcTypeObject() {
}
ConcTypeObject(const ConcTypeObject& other) {
m_ptr_Test = other.m_ptr_Test;
}
ConcTypeObject& operator=(const ConcTypeObject& other) {
m_ptr_Test = other.m_ptr_Test;
}
void setTest(shared_ptr<Test> ptr) {
cout << "setTest" << endl;
m_ptr_Test = ptr;
}
shared_ptr<Test> getTest() {
return m_ptr_Test;
}
bool isValid() {
if(m_ptr_Test) {
return true;
} else {
return false;
}
}
private:
shared_ptr<Test> m_ptr_Test;
};
class AbsTypeObject {
public:
explicit AbsTypeObject(const string str) {
m_str = str;
}
AbsTypeObject(const AbsTypeObject& other) {
m_str = other.m_str;
m_ptr_ConcTypeObject = other.m_ptr_ConcTypeObject;
}
AbsTypeObject& operator=(const AbsTypeObject& other) {
m_str = other.m_str;
m_ptr_ConcTypeObject = other.m_ptr_ConcTypeObject;
}
bool operator==(const AbsTypeObject& other) {
if(m_str == other.m_str)
return true;
else
return false;
}
void setConcTypeObject(shared_ptr<ConcTypeObject> ptr) {
m_ptr_ConcTypeObject = ptr;
}
shared_ptr<ConcTypeObject> getConcTypeObject() {
return m_ptr_ConcTypeObject;
}
bool isValid() {
if(m_ptr_ConcTypeObject) {
cout << "AbsTypeObject 1 " << endl;
return m_ptr_ConcTypeObject->isValid();
} else {
cout << "AbsTypeObject 2 " << endl;
return false;
}
}
private:
string m_str;
shared_ptr<ConcTypeObject> m_ptr_ConcTypeObject;
};
class StructAbsTypeObject {
public:
StructAbsTypeObject(const string str):m_AbsTypeObject(str) {
}
void SetAbsTypeObject(AbsTypeObject& id) {
m_AbsTypeObject = id;
}
AbsTypeObject& GetAbsTypeObject() {
return m_AbsTypeObject;
}
private:
AbsTypeObject m_AbsTypeObject;
};
class Executor {
public:
static Executor m_Executor;
static Executor& get() {
return m_Executor;
}
Executor() {
StructAbsTypeObject sid(std::string("ABCD"));
vector<StructAbsTypeObject> a_vecstid;
a_vecstid.push_back(sid);
m_executormap["ExecutorInterface"]["ExecutorName"] = a_vecstid;
}
void check() {
for(auto outermap : m_executormap) {
for(auto innermap : outermap.second) {
for(auto vec_element: innermap.second) {
if(vec_element.GetAbsTypeObject().isValid()) {
cout << "PTR VALID" << endl;
} else {
cout << "PTR NOT Valid" << endl;
}
}
}
}
}
void fillAbsTypeObject(AbsTypeObject &id) {
shared_ptr<Test> ptr_test = make_shared<Test>(20);
shared_ptr<ConcTypeObject> ptr_ConcTypeObject = make_shared<ConcTypeObject>();
id.setConcTypeObject(ptr_ConcTypeObject);
id.getConcTypeObject()->setTest(ptr_test);
}
void Init(AbsTypeObject id) {
for(auto outermap : m_executormap) {
for(auto innermap : outermap.second) {
for(auto vec_element: innermap.second) {
if(vec_element.GetAbsTypeObject() == id) {
cout << "Id Equal" << endl;
fillAbsTypeObject(id);
vec_element.SetAbsTypeObject(id);
if(vec_element.GetAbsTypeObject().isValid()) {
cout << "PTR VALID" << endl;
} else {
cout << "PTR NOT Valid" << endl;
}
}
}
}
check();
}
}
private:
using executormap = map<string,map<string,vector<StructAbsTypeObject>>>;
executormap m_executormap;
};
Executor Executor::m_Executor;
int main()
{
AbsTypeObject id(std::string("ABCD"));
Executor::get().Init(id);
}
//Code Ends
The above code is completely compilable and Runnable. Currently I am getting the following output
//Output Begins
Id Equal
setTest
AbsTypeObject 1
PTR VALID
AbsTypeObject 2
PTR NOT Valid
//Output Ends
The PTR NOT VALID is output when check function is executed. Expecting output is
PTR VALID in both cases.
Please let me know what is going wrong in the above code. I did try few things but did not work. If it does not work, what is the reason and what is the correct way to make it work.
Thanks in advance.
In your for loops:
for(auto outermap : m_executormap) {
for(auto innermap : outermap.second) {
for(auto vec_element: innermap.second) {
You are using auto which defaults to a non-reference type so you are taking a copy of each element in the map/vector. Your changes are being applied to these temporary copies so are lost.
Simply change these to references to update the original lists:
for(auto& outermap : m_executormap) {
for(auto& innermap : outermap.second) {
for(auto& vec_element: innermap.second) {
I am trying to implement a Dynamic Stack in c++.
i have 3 members in class stack
1.cap is the capacity.
2.top- points to top of stack
3. arr- pointer to an integer.
in the class constrcutor I am allocating memory to stack(malloc).
later in the meminc() I am trying to realloc the memory.
I have written a function meminc() to realloc the memory but i get this invalid old size error.
It would be helpful if you let me know what is wrong in this code. I will also appreciate any advice given to me.
Thank you.
#include <iostream>
using namespace std;
#define MAXSIZE 5
class stack {
int cap;
int top;
int *arr;
public:
stack();
bool push(int x);
bool full();
bool pop();
bool empty();
bool meminc();
};
stack::stack()
{
cap = MAXSIZE;
arr = (int *)malloc(sizeof(int)*MAXSIZE);
top = -1;
}
bool stack::meminc()
{
cap = 2 * cap;
cout << cap << endl;
this->arr = (int *)realloc(arr, sizeof(int)*cap);
return(arr ? true : false);
}
bool stack::push(int x)
{
if (full())
{
bool x = meminc();
if (x)
cout << "Memory increased" << endl;
else
return false;
}
arr[top++] = x;
return true;
}
bool stack::full()
{
return(top == MAXSIZE - 1 ? true : false);
}
bool stack::pop()
{
if (empty())
return false;
else
{
top--;
return true;
}
}
bool stack::empty()
{
return(top == -1 ? true : false);
}
int main()
{
stack s;
char y = 'y';
int choice, x;
bool check;
while (y == 'y' || y == 'Y')
{
cout << " 1.push\n 2.pop\n" << endl;
cin >> choice;
switch (choice)
{
case 1: cout << "Enter data?" << endl;
cin >> x;
check = s.push(x);
cout << (check ? " push complete\n" : " push failed\n");
break;
case 2: check = s.pop();
cout << (check ? " pop complete\n" : " pop failed\n");
break;
default: cout << "ERROR";
}
}
}
To add to john's answer,
the way you're using realloc() is ... flawed.
bool stack::meminc()
{
cap = 2 * cap;
cout << cap << endl;
this->arr = (int *)realloc(arr, sizeof(int)*cap);
return(arr ? true : false);
}
If realloc() fails it will return nullptr and the only pointer (arr) to the original memory region will be gone. Also, instead of return(arr ? true : false); you should simply use return arr != nullptr;.
The righttm way to use realloc():
bool stack::meminc()
{
int *temp = (int*) realloc(arr, sizeof(*temp) * cap * 2);
if(!temp)
return false;
cap *= 2;
arr = temp;
return true;
}
Also, where is your copy-ctor, assignment operator and d-tor?
The full function is incorrect. It should be
bool stack::full()
{
return(top == cap - 1 ? true : false);
}
or more simply and with added const
bool stack::full() const
{
return top == cap - 1;
}
Also you are using the top variable incorrectly. Since top starts at -1 you should increment top before you set the value, not afterwards
arr[++top] = x;
Not a bug, but from a design perpective meminc should be a private function.
i am having a bit of trouble here. I dont know what i am doing wrong. My bike.cpp class is fine. But i think the problem is with bike_shed class, i am having problem with the "park" and "checklegal" methods. we are asked to do something like this: " The class BikeShed with a private array of 10 default constructed Bike objects. The class should have the following public methods:
A default constructor BikeShed() as supplied by the compiler.
A function bool park( const Bike& ) which adds a bike to an available
spot and returns true. If the BikeShed is full, the function returns
false.
A function Bike remove( const string&int ) that removes and returns
the first bike with an owner of the given name. If such a bike is not
found, the function returns a bike "None".
A function bool checkLegal() that will return true if all bikes
owned by other than "None" are legal. If a bike is found illegal
print a message printing the bike.
A function void print( ) that prints all the bikes with owners
other than "None"."
here is my code:
here is bike_shed.cpp file
#include <iostream>
#include "bike_shed.h"
#include "Bike.h"
using namespace std;
void bike_shed::print(){
cout<< "Bike: " << sizeof(Bike) <<endl;
}
bool bike_shed::checkLegal() {
Bike bike1;
if(bike1.getOwner() == "None"){
return false;
}
else{
return true;
}
}
//Bike bike_shed::remove( const string&, int ) {
//
//
//}
bool bike_shed::park( const Bike& ) {
if (sizeof(Bike) > 10) {
return false;
}
}
and here is the Bike.cpp file
#include "Bike.h"
#include <iostream>
using namespace std;
void Bike::setNLight(int _light) {
d_nLight = _light;
}
void Bike::setBell(bool _bell) {
d_bell = _bell;
}
void Bike::setOwner(string _owner) {
d_owner = _owner;
}
void Bike::setReflector(bool _reflector) {
d_reflector = _reflector;
}
int Bike::getNLight() {
return d_nLight;
}
string Bike::getOwner() {
return d_owner;
}
bool Bike:: hasReflector() {
if (d_reflector == true) {
return true;
}
else {
return false;
}
}
bool Bike:: hasBell(){
if(d_bell == true) {
return true;
}
else{
return false;
}
}
bool Bike::isLegal() {
if (d_nLight >= 1 && d_reflector && d_bell) {
return true;
}
else {
return false;
}
}
void Bike::print() {
cout << "Owner: " << d_owner << " Color: " << d_color.Red << " " << d_color.Green << " " << d_color.Blue
<< " " << " Lights: " << d_nLight << " Bell: " << d_bell << " Reflector: " <<d_reflector << endl;
}
Bike::Bike(string name, Color color){
d_owner = name;
d_color = color;
}
and here is the bike_shed.h file
#include "Bike.h"
class bike_shed {
public:
bike_shed();
bool park( const Bike& );
Bike remove( const string&, int );
bool checkLegal();
void print();
public:
Bike bike[10];};
i would really appreciate if someone can help me. Thank you :)
In the following block of code,
if (sizeof(Bike) > 10) {
return false;
}
I am guessing that you are trying to make sure that you don't allow parking of more than 10 bikes in the shed.
In order to do that, you need to have a member variable in park_shed to indicate the number of bikes parked in the shed. Then, you can use:
bool bike_shed::park( const Bike& bike)
{
if ( number_of_parked_bikes < 10 )
{
bikes[number_of_parked_bikes] = bike;
++number_of_parked_bikes;
return true;
}
else
{
retun false;
}
}
Make sure to initialize number_of_parked_bikes to zero in the constructor.
The checkLegal function would be something like:
// Make it a `const` member function since it does not
// change anything in bike_shed.
bool bike_shed::checkLegal() const
{
bool isLegal = true;
for ( int i = 0; i < number_of_parked_bikes; ++i )
{
if ( bikes[i].getOwner() == "None" )
{
// No need to check whether this bike is legar or not.
}
else if (!bikes[i].isLegal() )
{
isLegal = false;
cout << "Illegal bike found.\n";
bikes[i].print();
}
}
return isLegal;
}
In method checkLegal() you may want to check whether a given Bike is valid or not before insertion, so you can write something like :
bool bike_shed::checkLegal(const Bike &bike1) {
if(bike1.getOwner() == "None"){ // or maybe bike1.isLegal()
return false;
}
else{
return true;
}
}
Also if you want to print all bikes in bike_shed you might want to write something like :
void bike_shed::print(){
for (int iBike = 0; iBike < nbBikes < iBike++)
bike[iBike].print();
}
I tried to strictly implement in c++ what I'm studying in algorithmic at the moment, recursive functions with simple linked lists. Here is what I've come by :
#include <iostream>
using namespace std;
class Liste {
private :
int val;
Liste *suivante;
public :
Liste(int val = 0, Liste *suivante = NULL) {
this->val = val;
this->suivante = suivante;
}
void afficherElement() const {
cout << "Adresse : " << this << endl;
cout << "Valeur : " << val << endl;
cout << "Adresse suivante : " << suivante << endl;
cout << endl;
}
int tete() const {
return val;
}
Liste reste() const {
return *suivante;
}
bool estVide() const {
return (suivante == NULL);
}
Liste prefixer(int val) {
Liste *nouvelle = new Liste(val, this);
return *nouvelle;
}
Liste suffixer(int val) {
suivante = new Liste(val);
afficherElement(); // test (last element won't be displayed)
return *suivante;
}
};
int main() {
Liste uneListe(3); // 1st element
uneListe.suffixer(5).suffixer(8).suffixer(10); // adding 3 more
cout << "-----------\n\n";
uneListe.afficherElement(); // displaying 1st element : ok
uneListe.reste().afficherElement(); // displaying 2nd element : pointer is NULL !!???
// uneListe.reste().reste().afficherElement(); --> segmentation fault, predictably enough
return 0;
}
As you can guess, it doesn't work. When I add elements, calling the display method within the add method, elements seem to be well formed although the pointer value and the next element's adress differ (I don't get why).
But, after adding process is done, I try to display the list again, 1st element is well linked with 2nd, but then there is a NULL pointer value. Wonder why ??
I've seen a code with two classes (Node and List), that works fine, but I'd like to know what is wrong with mine. Is it that I'm creating new objects of a class within this same class ?
Thanks,
for right this problem you most change this line
Liste suffixer(int val)
to
Liste* suffixer(int val)
and then change this line
return *suivante;
to
return suivante;
and in main use this line
uneListe.suffixer(5)->suffixer(8)->suffixer(10);
instead of
uneListe.suffixer(5).suffixer(8).suffixer(10);
Your class methods Liste::prefixer(int val) and Liste suffixer(int val) will return a copy of the object created, they should return a pointer to the object (or a reference).
e.g.
Liste *Liste::suffixer(int val){
if(suivante == nullptr)
suivante = new Liste(val);
else
throw std::runtime_error("Generic error message");
return suivante;
}
or
Liste &Liste::suffixer(int val){
... previous inner method ...
return *suivante;
}
Class Liste contains a value and a reference, which is not what a list is: a singly linked list is a pointer to an element containing a value and a pointer to the next node.
You might use a value+pointer element as a list object, ignoring the val member. This would require different coding for some methods, e.g., for tete() and reste().
But, since using
typedef Liste * real_list_type;
is what you have in mind (? - see below), let's look at the methods.
bool estVide() const { return (suivante == NULL); }
This is in contradiction to the real_list_type being a mere List *; if you compare this to method reste(), it actually tests whether the tail is empty, not the list itself! (It would be in sync with using a value+pointer object as the list object.)
Liste suffixer(int val) { suivante = new Liste(val); ... }
This is bad: it replaces suivante with a new object, no matter what's stored in there (a memory leak). You'll have to do
Liste suffixer(int val) {
if( suivante == NULL ){
suivante = new Liste(val);
} else {
suivante->suffixer( val );
}
return *this;
}
LATER
I think that would be the best way to keep it as close to the abstract concept as possible. Note that there is no "isEmpty" - this is done by a test whether the List * variable representing the list equals NULL, but you can't have a method for that.
template<typename T>
class List {
public:
List( T v, List* t = nullptr ) : value(v), next(t){}
~List(){ delete next; }
List* prepend( T v ){
return new List( v, this );
}
List* append( T v ){
if( next == nullptr ){
next = new List( v );
} else {
next->append( v );
}
return this;
}
T head(){ return value; }
List* tail(){ return next; }
void dump(){
List* curr = this;
std::string del = "";
while( curr != nullptr ){
std::cout << del << curr->value;
del = ", ";
curr = curr->next;
}
std::cout << std::endl;
}
private:
T value;
List* next;
};
int main(){
typedef List<int> * intList;
intList list = new List<int>( 1 );
list->append( 2 )->append( 3 );
list->dump();
}
Here is the "fixed" version of my first attempt :
#include <iostream>
using namespace std;
class Liste {
private :
int val;
bool vide;
Liste *suivante;
public :
Liste(int val = 0, bool vide = true, Liste *suivante = NULL) {
this->val = val;
this->vide = vide;
this->suivante = suivante;
}
void afficherElement() const {
cout << "Adresse : " << this << endl;
cout << "Valeur : " << val << endl;
cout << "Vide : " << vide << endl;
cout << "Adresse suivante : " << suivante << endl;
cout << endl;
}
int head() const {
return val;
}
Liste *reste() const {
return suivante;
}
bool estVide() const {
return vide;
}
Liste *prefixer(int val) {
Liste *nouvelle = new Liste(val, this);
return nouvelle;
}
Liste *suffixer(int val) {
if(suivante == NULL) {
suivante = new Liste(val);
vide = false;
}
return suivante;
}
};
void afficherListe(Liste *uneListe) {
(*uneListe).afficherElement();
if(!(*uneListe).estVide()) {
afficherListe((*uneListe).reste());
}
}
int main() {
Liste *test = new Liste(3);
(*test).suffixer(5);
afficherListe(test);
return 0;
}
As expected it's awfully unpractical.
Laune's solution looks good...
However, the whole thing is bizarre, I suppose I'd be better off sticking with the regular List/Nodes way. Definitely gonna talk about that with my teacher.