I want to delete every element at a certain index (that corresponds to a certain content), but I'm getting a segmentation fault... This is the structure of my code and the method deleteRecord is what I've tried but doesn't work:
class Tab {
public:
Tab();
~Tab() {};
bool colIsPresent(const string & col_name);
template <typename S> void deleteRecord(S & content, const string & col_name) {
int delete_pos;
if (!this->colIsPresent(col_name)) return;
const auto & it_columns = _columns.find(col_name);
if (it_columns != _columns.end()) {
auto ci = dynamic_cast<ColumnImpl<S> *>(it_columns->second.get());
if (ci != nullptr) {
for (int i = 0; i < ci->getData().size(); i++) {
if (ci->getData()[i] == content) {
delete_pos = i;
}
for (auto & it_columns_2 : _columns) {
auto ci2 = dynamic_cast<ColumnImpl<S> *>(it_columns_2.second.get());
ci2->getData().erase(ci2->getData().begin() + delete_pos);
}
}
}
}
}
private:
map<string, shared_ptr<Column>> _columns;
};
template <typename T> class ColumnImpl : public Column {
public:
ColumnImpl() : Column() {}
ColumnImpl(const T& to_set);
vector<T> & getData() { return _data; }
protected:
vector<T> _data;
};
class Column {
public:
Column();
virtual ~Column() {};
virtual string getType() = 0;
};
class Database {
public:
Database();
~Database();
bool tabIsPresent(const string & tab_name);
template <typename S> void deleteRecordFromTab(const string & tab_name, S & content, const string & col_name) {
const auto & it_target_tab = _tables.find(tab_name);
it_target_tab->second.deleteRecord(content, col_name);
}
private:
map<string, Tab> _tables;
};
Reproducible example:
Database data_base;
string tab = "EX_TAB", str1 = "STR_EX1", str2 = "STR_EX2", age = "AGE", name = "NAME", integer = "INT", text = "TEXT";
int a = 17, b = 18;
data_base.createNewTable(tab);
data_base.addColumnToTab(tab, age, integer);
data_base.addColumnToTab(tab, name, text);
data_base.addElemToColOfTab(tab, age, a);
data_base.addElemToColOfTab(tab, age, b);
data_base.addElemToColOfTab(tab, name, str1);
data_base.addElemToColOfTab(tab, name, str2);
data_base.deleteRecordFromTab(tab, str1, name);
// createNewTable creates a new table
// addColumnToTab adds a new column of the right type to _columns
// addElemToColumnOfTab adds an element to the targeted column
Related
I have an UserAcount class that has an abstract class ContBancar, and other class Banca which reads some users from a file (with method void Banca::citire_conturi()). When it reads the users, I get an error "Access violation writing location" in ContBancar at void setBal(double bal) { _balanta = bal; }. Thx for help !
PS : The file has only one line : 1CBS Dragos 0 dragos12! Gzpvia01= .
Also, i want to make a bank account system, with an user class that has an bank account class which inherits 3 types of a bank accounts, and a bank class which reads some users from a file or put them on it.
class UserAccount
{
private:
std::string _nume, _user, _pass;
std::string _cod_us;
std::shared_ptr <ContBancar> _cont;
public:
void setUser(std::string user) { _user = user; }
void setPass(std::string pass) { _pass = pass; }
void setNume(std::string nume) { _nume = nume; }
void setCodUs(std::string cod) { _cod_us = cod; }
void setContBal(double balanta) { (*_cont).setBal(balanta); }
std::string getUser() const { return _user; }
std::string getPass() const { return _pass; }
std::string getNume() const { return _nume; }
std::string getCodUs() const { return _cod_us; }
double getContBal() const { return (*_cont).getBal(); }
void setContBancar();
};
void UserAccount::setContBancar()
{
if (_cod_us == "1CBS")
_cont.reset(new ContBancarSilver());
else if (_cod_us == "2CBG")
_cont.reset(new ContBancarGold());
else
_cont.reset(new ContBancarDiamond());
}
class ContBancar
{
protected:
double _balanta;
public:
void setBal(double bal) { _balanta = bal; }
double getBal() { return _balanta; }
virtual bool depozitare(unsigned int) = 0;
virtual bool retragere(unsigned int) = 0;
};
class Banca
{
private:
std::vector<UserAccount> vec;
public:
void citire_conturi();
};
void Banca::citire_conturi()
{
std::ifstream file;
file.open("Baza_Date.txt");
UserAccount temp;
std::string cod, nume, user, pass;
double balanta;
while (file >> cod >> nume >> balanta >> user >> pass)
{
temp.setCodUs(cod);
temp.setNume(nume);
temp.setContBal(balanta);
temp.setUser(user);
temp.setPass(pass);
vec.push_back(temp);
}
file.close();
}
class ContBancarSilver : public ContBancar
{
private:
static constexpr unsigned int max_balanta = 5000;
static constexpr unsigned int max_depozitare = 2500;
static constexpr unsigned int max_retragere = 1000;
static constexpr double tax_retragere = 0.08;
static constexpr double bonus_depunere = 0.03;
static constexpr double bonus_tax_retragere = 0.05;
static constexpr unsigned int max_depozitari = 1;
static constexpr unsigned int max_retrageri = 1;
public:
virtual bool depozitare(unsigned int) override;
virtual bool retragere(unsigned int) override;
};
Based on available informationyou should fix your code like this:
class UserAccount
{
.....
void setCodUs(std::string cod) {
_cod_us = cod;
setContBancar();
}
void setContBal(double balanta) {
if (!_cont) setContBancar(); // lazy initialization
_cont->setBal(balanta);
}
...
};
void UserAccount::setContBancar()
{
if (_cod_us == "1CBS")
_cont = std::make_shared<ContBancarSilver>();
else if (_cod_us == "2CBG")
_cont = std::make_shared<ContBancarGold>();
else
_cont = std::make_shared<ContBancarDiamond>();
}
Note I do not understand what kind of logic you are implementing. This changes just ensured that _cont is initialized and up to date with _cod_us.
Please stop use explicitly new and delete. Everything can be created by std::make_shared and std::make_unique and containers like std::vector.
Vehicle header file
#define vehicle_h
#include "date.h"
#include "storable.cpp"
#include <string>
using namespace std;
typedef enum{bike = 1,car = 2,towera = 3} VehicleType;
class Vehicle : public Storable
{
private:
string registrationnumber;
VehicleType type;
int seats;
string companyname;
double pricePerKm;
Date PUCExpirationDate;
public:
Vehicle(
string registrationnumber,
VehicleType type,
int seats,
string companyname,
double pricePerKm,
Date PUCExpirationDate, long recordID);
string getregistrationnumber() const;
VehicleType getVehicleType() const;
string getVehicleTypeName() const;
int getseats() const;
string getcompanyName() const;
double getPricePerKm() const;
Date getPUCExpirationDate() const;
void setPricePerKm(double newPrice);
void display() const;
string toString() const;
void setDataForm (Storable * s);
};
#endif // vehicle
Vehicle
#include "Vehicle.h"
#include "STRING_HELPER.h"
const char DELIMETER =';';
Vehicle :: Vehicle(string registrationnumber,VehicleType type,int seats,
string companyName , double pricePerKm , Date PUCExpirationDate , long recordID=0):Storable(recordID)
{
this->registrationnumber =registrationnumber;
this->type= type;
this->seats = seats;
this-> companyname = companyname;
this->pricePerKm = pricePerKm;
this->PUCExpirationDate = PUCExpirationDate;
}
string Vehicle ::getregistrationnumber() const
{
return this->registrationnumber;
}
VehicleType Vehicle::getVehicleType() const
{
return this->type;
}
int Vehicle::getseats() const
{
return this->seats;
}
string Vehicle::getcompanyName() const
{
return this->companyname;
}
double Vehicle::getPricePerKm() const
{
return this->pricePerKm;
}
Date Vehicle::getPUCExpirationDate() const
{
return this->PUCExpirationDate;
}
void Vehicle::setPricePerKm( double newprice)
{
this->pricePerKm= newprice;
}
string Vehicle::getVehicleTypeName() const
{
switch(this->type)
{
case VehicleType:: bike:
return "bike";
case VehicleType:: car:
return "car";
case VehicleType:: towera:
return "Tower";
default:
return " ";
}
}
void Vehicle::display() const
{
cout<< "Vehicle Details :"<<endl;
cout<< "Registration Number : "<< this->registrationnumber<<endl;
cout<< "Vehicle Type : "<< this->type<<endl;
cout<< "No of seats : "<< this->seats<<endl;
cout<< "Company Name : "<< this->companyname<<endl;
cout<< "Price PER Km : "<< this->pricePerKm<<endl;
cout<< "PUC ExpirationDate : "<< this->PUCExpirationDate.toString()<<endl;
}
string Vehicle::toString() const
{
stringstream ss;
ss<<recordID<< DELIMETER<< registrationnumber<< DELIMETER<< type<< DELIMETER<< seats<< DELIMETER<< companyname<< DELIMETER
<< to_string(pricePerKm)<< DELIMETER<< PUCExpirationDate.toString();
return ss.str();
}
void Vehicle ::setDataForm(Storable *s)
{
Vehicle *v = dynamic_cast<Vehicle *> (s);
if(v)
{
this->registrationnumber= v->registrationnumber;
this->type= v->type;
this->companyname= v->companyname;
this->seats= v->seats;
this->pricePerKm = v->pricePerKm;
this->PUCExpirationDate= v->PUCExpirationDate;
}
}
Template Table header file
#define table_h
#include "storable.cpp"
#include "Vehicle.h"
#include "error.cpp"
#include <vector>
#include<string>
#include <fstream>
using namespace std;
template <class T> class Table {
private:
string fileName;
fstream fileStream;
vector<Storable *> * records = NULL;
T * getRefOfRecord(long recordID) const throw(IOError);
void writeToFile () throw(IOError);
T * addNewRecord (T data) const throw (IOError);
void updateRecord (T updateRecord) const throw (IOError);
public:
Table(string fileName) throw (MemoryError);
~Table();
long getNextRecordId() const;
const T* const getRecordForld(long recordId) const throw(IOError);
friend class Database;
};
#endif // table_h
Template table .cpp
#include "Table.h"
#include<iostream>
using namespace std;
template <class T> Table<T> ::Table(string fileName)
throw(MemoryError)
{
this->fileName = fileName;
this->records = new vector<Storable *> ();
if(!this->records)
{
throw MemoryError();
}
}
template <class T> long Table<T> ::getNextRecordId() const
{
return this->records->size()+1;
}
template <class T> T* Table<T> ::addNewRecord (T record) const throw (IOError)
{
T *newRecord = new T(record);
if(!newRecord)
{
throw new MemoryError();
}
newRecord->recordId = this->getNextRecordId();
this->records->push_back(newRecord);
try
{
this->writeToFile();
}
catch(IOError error)
{
this->records->pop_back();
delete newRecord;
throw;
}
return newRecord;
}
template <class T> void Table<T> ::updateRecord(T updateRecord) const throw(IOError)
{
for(auto & record:*this->records)
{
if(record->getRecordID()== updateRecord.getRecordID())
{
T * ptr = dynamic_cast<T*> (record);
if(ptr)
{
T oldRecord = T(* ptr);
record->setDataFrom(&updateRecord);
try
{
this->writeToFile();
return;
}
catch(IOError error)
{
record->setDataFrom (&oldRecord);
throw;
}
}
}
}
throw MemoryError();
}
template <class T> void Table<T> ::writeToFile() throw (IOError)
{
this->fileStream.open(fileName,ios::out | ios::trunc);
if(!this->fileStream)
{
throw IOError();
}
for(auto & record: *records)
{
fileStream <<record->toString()<<endl;
}
this->fileStream.close();
}
template <class T> const T* const Table<T> ::getRecordForld(long recordId) const throw(IOError)
{
try
{
return this->getRefOfRecord(recordId);
}
catch(IOError)
{
throw;
}
}
template <class T> T* Table<T> ::getRefOfRecord(long recordId) const throw (IOError)
{
for(auto &record :*records)
{
if(record->getRecordID()== recordId)
{
return dynamic_cast<T*> (record);
}
}
throw IOError();
}
template <class T> Table<T> ::~Table()
{
for(auto & record : *this->records)
{
delete dynamic_cast<T*> (record);
}
this->records->clear();
this->records->shrink_to_fit();
delete this->records;
}
the template class working fine with the other class such as user or trip but with vehicle class I am getting this error
give the error invalid abstract parameter type 'Vehicle'
I am stuck in this place two three day ago I terid but didn't find any clue !!
There is a base class
class LineEditItem
{
public:
LineEditItem(QLineEdit* le, const Values_t& values = Values_t()):
values(values),
le(le)
{}
LineEditItem &addValue(int v, const QString &s)
{
values[v] = s;
return *this;
}
LineEditItem &addValues(const Values_t& vals)
{
for (auto key: vals.keys())
{
values[key] = vals[key];
}
return *this;
}
void setValue(uint32_t v)
{
QString str;
if (values.contains(v))
{
str = values[v];
}
else
{
str = "";
}
le->setText(str);
}
void clearValue()
{
le->clear();
}
protected:
Values_t values;
QLineEdit* le;
};
There is a child class that must inherit the addValue and addValues methods
class LineEditItemBits: public LineEditItem
{
public:
LineEditItemBits(QLineEdit* le, int begin, int end, const Values_t& values = Values_t()):
LineEditItem(le, values),
begin(begin),
end(end)
{}
void setValue(uint32_t v)
{
int s = end - begin + 1;
v = (v >> begin) & ((1 << s) - 1);
LineEditItem::setValue(v);
}
LineEditItemBits &addValue(int v, const QString &s)
{
LineEditItem::addValue(v, s);
return *this;
}
LineEditItemBits &addValues(const Values_t& vals)
{
LineEditItem::addValues(vals);
return *this;
}
private:
int begin;
int end;
};
But you have to explicitly prescribe these methods and call base class methods from them.
How to inherit these methods from the base class so that they return a reference to the child class?
From my understanding you are trying to override these functions, so you should make them virtual in parent class.
I have a assignment where I'm suppose to build template using these specifications.
ISet is a container that holds values of a certain where order doesn't matter and
which does not allow duplicates (or multiples).
A dynamically allocated array of type T should be used as an internal data structure for the Set.
The Set should inherit from the ISet interface below - this must not be modified:
template <typename T>
class ISet
{
public:
virtual bool insert (T element) = 0;
virtual bool remove (T element) = 0;
virtual int size () const = 0;
};
• insert (T element): adds elements to the set and returns true provided that
the element is not already present in the quantity (in which case the element is not added and false is returned).
• remove (T element): removes elements from the set and returns true.
If the element is missing in the quantity, false returns.
• size (): returns the number of elements in the set.
In addition to the member functions, you must implement constructor, destructor, copy constructor
and assignment operator.
And so far have I come up with this code:
#pragma once
#include <string>
#include <iostream>
using namespace std;
template <class T>
class ISet
{
public:
virtual bool insert(T element) = 0;
virtual bool remove(T element) = 0;
virtual int size() const = 0;
};
#pragma once
#include "ISet.h"
template <class T>
class Set : public ISet<T>
{
public:
Set(string name);
~Set();
Set(const Set &origin);
//Set& operator=(const Set &origin);
bool insert(T element);
bool remove(T element);
int size()const;
private:
string name;
T *arr;
int cap, nrOfElement;
};
template<class T>
Set<T>::Set(string name)
{
this->name = name;
this->cap = 10;
this->nrOfElement = 0;
this->arr = new T[this->cap];
}
template<class T>
Set<T>::~Set()
{
delete[] arr;
}
template<class T>
Set<T>::Set(const Set & origin)
{
this->nrOfElement = origin.nrOfElement;
this->cap = origin.cap;
arr = new T*[cap];
for (int i = 0; i < nrOfElement; i++)
{
arr[i] = origin.arr[i];
}
}
template<class T>
bool Set<T>::insert(T element)
{
bool found = false;
if (nrOfElement == 0)
{
this->arr[0] = element;
this->nrOfElement++;
}
else
{
for (int i = 0; i < this->nrOfElement; i++)
{
if (this->arr[i] == element)
{
i = this->nrOfElement;
found = true;
}
}
if (found == false)
{
this->arr[nrOfElement++] = element;
}
}
return found;
}
template<class T>
bool Set<T>::remove(T element)
{
bool removed = false;
for (int i = 0; i < this->nrOfElement; i++)
{
if (this->arr[i] == element)
{
this->arr[i] = this->arr[nrOfElement];
nrOfElement--;
removed = true;
}
}
return removed;
}
template<class T>
int Set<T>::size() const
{
return this->nrOfElement;
}
And my problems starts when I start to test this code by adding the different data-type we are suppose to test the template against.
#include "Set.h"
#include "ISet.h"
#include "Runner.h"
int main()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
Set<string> test("test");
test.insert("lol");
cout << test.size();
test.remove("lol");
cout << test.size();
Set<Runner> test2("test");
getchar();
return 0;
}
Getting the error saying that "No operator found which takes a left-hand operand type of 'Runner'. So I have to create a operator== that handles this but don't know?
Runner class looks like this:
#pragma once
#include "Competitor.h"
#include <string>
using namespace std;
class Runner : public Competitor
{
public:
Runner();
Runner(string firstName, string lastName, int startNr);
~Runner();
void addResult(int resultTime);
int getResult() const;
string toString() const;
Runner *clone() const;
private:
int resultTime;
};
#include "Runner.h"
Runner::Runner()
{
this->resultTime = 0;
}
Runner::Runner(string firstName, string lastName, int startNr) : Competitor(firstName, lastName, startNr)
{
this->resultTime = 0;
}
Runner::~Runner()
{
}
void Runner::addResult(int resultTime)
{
this->resultTime = resultTime;
}
int Runner::getResult() const
{
return this->resultTime;
}
string Runner::toString() const
{
return (to_string(this->resultTime) + " sec");
}
Runner * Runner::clone() const
{
return new Runner(*this);
}
How do I build a operator== that will work for this?
You need to add operator== to the Runner class:
bool operator==(const Runner& other) const;
Base class : Employee
Derived class : Regular
Employee.cpp
void Employee::setValue(string id, string name, double s, int n)
{
empID = id;
empName = name;
salary = s;
}
Regular.cpp
void Regular::setValue(string id, string name, double s, int n)
{
annualLeave = n;
}
Employee::setValue() only stores the first 3 arguments passed in, but not int n, too.
I'm supposed to inherit that setValue() in Regular::setValue() and then just pass in the arguments, but this time store int n to annualLeave.
How do I do that?
Or, is there a way for me to set int n in the base class for the child class?
You can call the base class's implementation:
void Regular::setValue(string id, string name, double s, int n) {
annualLeave = n;
return Employee::setValue(std::move(id), std::move(name), s);
}
Otherwise, make base class polymorphic:
struct Employee {
void setValue(string id, string name, double s, int n) {
empID = std::move(id);
empName = std::move(name);
salary = s;
setLeave(n);
}
virtual ~Employee() {}
protected:
virtual void setLeave(int) = 0;
string empID;
string empName;
double salary;
};
struct Regular: Employee {
private:
void setLeave(int n) override { annualLeave = n; }
int annualLeave;
};
If necessary to keep a single-signature setValue function, it is possible to do it like that:
-
Includes:
#include <any>
#include <map>
#include <string>
-
Employee.h:
class CEmployee
{
protected:
virtual void setValue(std::map<std::string, std::any> &info);
int m_empID = 0;
std::string m_empName = {'\0'};
int m_salary = 0;
}
Employee.cpp:
void CEmployee::setValue(std::map<std::string, std::any> &info)
{
std::any item;
item = info["empID"];
if (item.has_value())
m_empID = std::any_cast<int>(item); // int
item = info["empName"];
if (item.has_value())
m_empName = std::any_cast<std::string>(item); // std::string
item = info["salary"];
if (item.has_value())
m_salary = std::any_cast<int>(item); // int
}
-
Regular.h:
class CRegular : public CEmployee
{
public:
void setValue(std::map<std::string, std::any> &info) override;
protected:
std::string m_annualLeave = {'\0'};
}
Regular.cpp:
void CRegular::setValue(std::map<std::string, std::any> &info)
{
std::any item;
CEmployee::setValue(info);
item = info["annualLeave"];
if (item.has_value())
m_annualLeave = std::any_cast<std::string>(item); // std::string
}
-
& call it like that:
void MyClass::HardcodedExample()
{
CRegular regular_employee;
std::map<std::string, std::any> info, update;
info["empID"] = { 100 };
info["empName"] = { std::string("Trump") };
info["salary"] = { 1000000 };
info["annualLeave"] = { std::string("29 Jul 2018") };
regular_employee.setValue(info); // Set all info
// Or:
update["annualLeave"] = { std::string("29 Dec 2018") };
regular_employee.setValue(update); // Update just "annualLeave"
// Or:
update["salary"] = { 1200000 };
update["annualLeave"] = { std::string("04 Jul 2018") };
regular_employee.setValue(update); // Update "salary" & "annualLeave"
}
-
Otherwise, setValue with 3 parameters to base-class, & with 4 parameters to the derived-class (that calls to the base-class with the 3 parameters and sets by itself the 4th one) - similar to what #RemyLebeauis offers - is a better solution.
-
& better to use #define / enum keys instead of string-keys (& change the key-type of the map accordingly), but this is a different issue.