How to update a variable that comes from a getter - c++

I need my front method to be able to support doing something like this for my assignment. Its been 4 hours. I can't seem to figure it out. I've tried overloading the = operator but that doesn't seem to work.
vectD3.front() = '{';
vectD3.back() = '}';
basically I need that code to not throw an error when ran
here is my front and back methods
public:T front()
{
if(currentSize > 0)
{
return array[0];
}
else
{
throw std::runtime_error("dynarray has no members");
}
}
public:T back()
{
if(currentSize > 0)
{
return array[currentSize-1];
}
else
{
throw std::runtime_error("dynarray has no members");
}
}
Thanks is advance

You need to return reference by your getter function. then you can modify it.
Something like this :
class A
{
public:
A(char d1): data(d1) {}
char& getData()
{
return data;
}
private:
char data;
};
int main()
{
A a('a');
std::cout << a.getData();//data = a
a.getData() = 'b';
std::cout << a.getData();//data = b
return 0;
}

Related

C++: Issues with handling Errors in Abstract Class

Iam currently working on an assignment wherein;
I have to create my own array and array exception class.
SetElement(int arg) and GetElement(int arg) part of Array class, need to account for out of bound exceptions by throwing OutOfBoundsExcpetoinObject(Derrived) part of the Array Exception class (Base).,
I have to catch the Array Exception (base class).
I am getting an error that the abstract class cannot be caught.
These are the parameters. I have followed them, however i am still getting the abstract class cannot be caught error.
1.Give the ArrayException an abstract GetMessage() function that returns a std::string.
2.Give the OutOfBoundsException class a constructor with an int as argument that indicates the erroneous array index and store it in a data member.
3.Override the GetMessage() function and let the implementation return a message string saying the given index is out of bounds.
4.In the Array class, throw now a OutOfBoundsException object instead of an integer.
5.Change the main program so that it catches the ArrayException base class and uses the GetMessage() function to display an error message.
Main Function:
// creating an array
Array abc =Array(5);
Point* q = new Point(1,2);
//testing out of bounds cases in both get and set
abc.setElement(10,*q);
cout << abc.getElement(10);
ArrayException Class:
class ArrayException
{
private:
public:
ArrayException();
virtual string GetMessage() const=0;
};
class OutofBoundsException : public ArrayException
{
private:
int m_index;
public:
OutofBoundsException();
OutofBoundsException(int index);
virtual string GetMessage() const;
};
Array Class:
Array::Array():m_size(3),m_data(new CAD::Point[m_size]) {}
Array::Array(int size): m_size(size), m_data(new CAD::Point[m_size]) {}
Array::~Array()
{
delete[] m_data;
cout << "Destructor called" << endl;
}
Array::Array(const Array &obj) {
m_size = obj.m_size;
m_data = new CAD::Point[m_size];
for (int i = 0; i < m_size; i++)
{
m_data[i] = obj.operator[](i);
}
}
int Array::Size()
{
return m_size;
}
udbhavAg::CAD::Point &Array::getElement(int index)
{
try
{
if (index >= m_size || index < 0)
{
OutofBoundsException error = OutofBoundsException(index);
throw (error);
}
else
{
return m_data[index];
}
}
catch (ArrayException abc)
{
cout << abc.GetMessage();
}
}
void Array::setElement(int index, udbhavAg::CAD::Point p)
{
try
{
if (index >= m_size || index < 0)
{
OutofBoundsException error = OutofBoundsException(index);
throw (error);
}
else
{
m_data[index] = p;
}
}
catch (ArrayException error)
{
cout << error.GetMessage();
}
}
Array Array::operator=(const Array &source)
{
if (this == &source)
{
return *this;
}
m_data = source.m_data;
m_size = source.m_size;
return *this;
}
CAD::Point &Array::operator[](int index) {
return m_data[index];
}
const CAD::Point &Array::operator[](int index) const {
return m_data[index];
}
You should catch by reference to base, which can bind to a derived object:
catch (ArrayException const& abc)
Then just throw OutofBoundsException(index) directly,
I solved the error using referecnig and dereferencing. Since an instance of abstract class cannot be created it cannot be caught. However, an abstract class pointer can be created, hence i figured it can be caught.
I changed the code in my setElement & GetElement to the following and it works now:
udbhavAg::CAD::Point &Array::getElement(int index)
{
try
{
if (index >= m_size || index < 0)
{
OutofBoundsException error = OutofBoundsException(index);
ArrayException& abc = error;
throw (&abc);
}
else
{
return m_data[index];
}
}
catch (ArrayException *error)
{
cout << error->GetMessage();
}
}
void Array::setElement(int index, udbhavAg::CAD::Point p)
{
try
{
if (index >= m_size || index < 0)
{
OutofBoundsException error = OutofBoundsException(index);
ArrayException& abc = error;
throw (&abc);
}
else
{
m_data[index] = p;
}
}
catch (ArrayException *error)
{
cout << error->GetMessage();
}
}

Can't call a function in a class returning a char

There is an error saying "expression preceding parentheses of apparent call must have (pointer-to-) function type" when I'm trying to call st.top()
string infixToPostfix(string hasil)
{
Stack st;
string postfix = "";
for (int i = 0; i < hasil.length(); i++)
{
if (hasil[i] == ' ')
{
continue;
}
else if (isOperator(hasil[i]))
{
while (st.isEmpty() && hasHigherPrecedence(st.top(), hasil[i])) // the error is here
{
postfix = postfix + st.top(); // and here
}
}
}
}
class Stack {
public:
int top = -1;
char array[MAX];
bool isEmpty()
{
if (top == -1)
{
return true;
}
else
{
return false;
}
}
bool isFull()
{
if (top == (MAX-1))
{
return true;
}
else
{
return false;
}
}
void push(char masuk)
{
if (isFull())
{
cout << "Expresi yang anda masukkan telah melebihi stack" << endl;
}
else
{
top++;
array[top] = masuk;
}
}
void pop()
{
if (isEmpty())
{
cout << "Stack sudah kosong!" << endl;
}
else
{
top--;
}
}
char top()
{
if (isEmpty())
{
cout << "Stack kosong" << endl;
}
else
{
return array[top];
}
}
};
You have both a public member variable and a public function called top. You should rename one of them.
You should also seriously consider making the variable (and, indeed, all variables) private since, otherwise, forces outside your class are free to fiddle with its internals in a way that you won't enjoy.
The whole point of encapsulation is hiding this sort of stuff from the outside world so that your class has a limited number of things it presents. For example, with a public variable, I could just do:
st.m_top = -2; // Assumes you've renamed it to distinguish from top().
and sit back and enjoy the fireworks :-)

Objects Array - C++

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 am not sure what I am doing wrong but I keep getting an error c++

for (int i = peekIndex; i < pdp->size(); i++)
{
string x = pdp->peek();
if (x.at(0) == 's')
{
out << pdp->peek() << endl;
pdp->moveForward();
}
else
{
pdp->moveForward();
}
}
The error I get is
terminate called after throwing and instance of std::out_of_range
what(): basic_string::at()
Abort
The peek method returns a string in the position of the peekIndex.
The moveFowrard method increments the peekIndex.
pdp is a vector of size 100. I am supposed to peek and print only words that start with 's' that have been pushed to the <vector>. I am basically done but this part is proving somewhat difficult.
Thanks
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class StringDeque {
protected:
vector<string>* elements;
int frontItem; //CLASS INV: indexes item with least index
int rearSpace; //CLASS INV: indexes space after item with greatest index
int upperBound; //For array[0..n-1] this is "n" not "n-1".
public:
StringDeque(int guaranteedCapacity):
elements (new vector<string>( 2*guaranteedCapacity))
frontItem (guaranteedCapacity),
rearSpace ( guaranteedCapacity),
upperBound ( 2*guaranteedCapacity)
{}
proteted:
virtual bool isEmpty() const { return frontItem == rearSpace; }
virtual bool isFull() const { return rearSpace == upperBound || frontItem == 0; }
virtual int size() const { return rearSpace - frontItem; }
virtual string popRear() {
if (isEmpty()) {
cerr<< "Later we'll define and throw an EmptyQException"<< endl;
return "";
} else {
return elements->at(--rearSpace);
}
}
virtual string popFront() {
if (isEmpty()) {
cerr<<"Later we'll define and throw an EmptyQException"<<endl;
return "";
} else {
return elements->at(frontItem++);
}
}
/** Directions include similarly testing for "full" in the C++ code.
*/
virtual void pushFront(string newItem) {
elements->at(--frontItem)= newItem;
}
virtual void pushRear(string newItem) {
elements->at(rearSpace++) = newItem;
}
virtual string toString() {
string out = "";
for (int i = frontItem; i < rearSpace; i++) {
out += elements->at(i) + " ";
}
return out;
}
};
class PeekDeque : public StringDeque {
private:
int peekIndex;
public:
PeekDeque(int guaranteedCapacity):
StringDeque(guaranteedCapacity),
peekIndex(guaranteedCapacity/2)
{}
virtual void moveFrontward() {
if (peekIndex == upperBound) {
cerr<<"Cannot move past total capacity"<<endl;
} else{
elements->at(peekIndex ++);
}
}
virtual void moveRearward () {
if (peekIndex == -1) {
cerr<<"Cannot move below total capacity"<<endl;
} else{
elements ->at( peekIndex--);
}
}
virtual string popFront() {
cerr<<"Attempt to pop from empty PeekDeque"<<endl;
}
virtual string popRear() {
cerr<<"Attempt to pop from empty PeekDeque"<<endl;
}
virtual string peek() {
if (isEmpty()) {
cerr<<"Cannot peek an Empty index"<<endl;
return "";
} else {
return elements->at(peekIndex + 1);
}
}
virtual string toString() {
string out = "";
for (int i = frontItem; i < rearSpace; i++) {
out += elements->at(i) + " ";
}
return out;
}
};
int main(){
PeekDeque* pdp = new PeekDeque(101);
pdp->pushFront("oh");
pdp->pushFront("say");
pdp->pushFront("can");
pdp->pushFront("you");
pdp->pushFront("see");
pdp->pushRear("any");
pdp->pushRear("bad bugs");
pdp->pushRear("on");
pdp->pushRear("me?");
for(int i = peekIndex; i<pdp->size(); i++){
string x =
if(x.at(0)=='s'){
cout<<pdp->peek()<<endl;
pdp->moveForward(); }
else{
pdp->moveForward();
}
}
}
May be your test should be:
if(!x.empty() && x.at(0)=='s')
I can't tell exactly, without seeing more context, but I'm pretty sure x.empty() is a probable case.
UPDATE:
pdp is a vector of size 100
Are you sure to have used the pdp.resize(100,std::string()); method to ensure all positions are initialized correctly?
it is not empty i have pushed 8 things to pdp
Also std::vector<>::resize() and std::vector<>::push_back() might not work together as you expect. Use either std::vector<>::push_back() or std::vector<>::resize() to give it a pre-allocated size and manipulate entries by index. Always check for std::vector<>::size() for indexed access.
UPDATE 2:
But the real answer is apparently simpler. You have:
virtual string peek() {
if (isEmpty()) {
cerr<<"Cannot peek an Empty index"<<endl;
return ""; // This will certainly result in a string that is empty!
Here's how your container looks like after initial pushes:
0 202
| ... | ... | ... | ... |
^ ^ ^
| | rearSpace
| peekIndex
frontItem
Now, size() returns rearSpace - frontItem, but iteration starts from peekIndex and thus goes beyond rearSpace index, peeking uninitialized (empty) strings.
That's certainly an approximate answer, since your work with indices is a mess. Please be really careful and think it through.

Single assignment for basic types in C++

I'd like to create a "single assignment" wrapper for basic types (such as int) that talks like an int, walks like an int, smells like an int, but can only be modified or assigned to at most once (like in some pure functional languages). For example (copy constructor omitted to keep the example simple):
template<class T>
struct SA {
SA<T>(T init) : wasAssigned(false) {
val = tmp = init;
}
SA<T> & operator=(const T& other) {
if (!wasAssigned) {
if (val != tmp) {
val = tmp;
} else {
val = tmp = other;
}
wasAssigned = true;
}
return *this;
}
operator T& () {
if (!wasAssigned && (val != tmp)) {
wasAssigned = true;
val = tmp;
} else {
tmp = val;
}
return tmp;
}
private:
bool wasAssigned;
T val, tmp;
};
This is close, but not perfect. It relies on the val/tmp equality test to detect changes, and fails in this case:
SA<int> i(3);
cin >> i;
i = 5;
Iff the cin >> i assigns the same value as the initial value (3), i will be 5 at the end. How can this be fixed?
Something like the following might work, although I'm not 100% sure about the side-effects. Basically returning a reference to tmp on all but the first call that gets a non-const reference, plus const methods for read-only access.
operator T& () {
if (wasAssigned) {
tmp = val;
return tmp;
} else {
wasAssigned = true;
return val;
}
}
operator const T& () const {
return val;
}
operator T () const {
return val;
}