Cannot dereference end list iterator - c++

I'm currently working on a project about browser histories. I'm using the STL's list implementation to keep track of the different websites. I have most of it figured out but I can't seem to resolve the error:
Screenshot; cannot dereference end list iterator.
The website data is contained within my Site objects.
class BrowserHistory {
private:
list<Site> history;
list<Site>::iterator current = history.begin();
public:
void visitSite(string, size_t)
void backButton();
void forwardButton();
void readFile(string);
};
void BrowserHistory::visitSite(string x, size_t y)
{
while (current != history.end()) {
history.pop_back();
}
history.push_back({ x, y });
current++;
}
void BrowserHistory::backButton()
{
if (current != history.begin())
current--;
}
void BrowserHistory::forwardButton()
{
if (current != history.end())
current++;
}
void BrowserHistory::readFile(string filename)
{
string action, url;
size_t pageSize;
ifstream dataIn;
dataIn.open(filename);
while (!dataIn.eof()) {
dataIn >> action;
if (action == "visit") {
dataIn >> url >> pageSize;
history.push_back({ url, pageSize });
current++;
}
if (action == "back") {
current--;
}
if (action == "forward") {
current++;
}
}
dataIn.close();
}
Can anyone explain to me what's wrong? Thanks in advance for any help.

When you initialise current, the list is empty.
Adding elements to the list does not suddenly make it a valid iterator, even though it will be different from end.
It looks like you're thinking of iterators as very much like pointers, but they're not.
Iterators are for iterating and should be considered transient, and not stored for later use.
Use a vector, and use an index for current instead of an iterator.
Further, I would rename the "button" functions (what does the history care about buttons?) to "goBack" and "goForward" and use your actual interface when reading:
void BrowserHistory::readFile(string filename)
{
ifstream dataIn(filename);
string action;
while (dataIn >> action) {
if (action == "visit") {
string url;
size_t pageSize;
if (dataIn >> url >> pageSize) {
visitSite(url, pageSize);
}
else {
// Handle error
}
}
else if (action == "back") {
goBack();
}
else if (action == "forward") {
goForward();
}
else {
// Handle error
}
}
}

Related

Cannot erase a shared_ptr from set

I am trying to have an object with a set of pointers to another object. when I try to erase on of the set's values I get an error and crash, I really dont know what could be causing it. here is the library and after that the main function:
when I try to run it it does everything its supposed to do, and when it gets to the removeemployee it crashes and sends out the following: Process finished with exit code -1073740940 (0xC0000374)
I run it on clion if that matters, and in c++11.
#include <ostream>
#include <iostream>
#include "Manager.h"
Manager::Manager(int id, string firstName, string lastName, int birthYear)
: Citizen(id, firstName, lastName,birthYear), salary(0), employees(), work_flag(false) {}
int Manager::getSalary() const {
return salary;
}
void Manager::setSalary(int _salary) {
if((salary + _salary) < 0){
salary = 0;
}else {
salary += _salary;
}
}
void Manager::addEmployee(Employee* employee_add) {
shared_ptr<Employee> employee(employee_add);
if(employees.find(employee) != employees.end()){
throw mtm::EmployeeAlreadyExists();
}
employees.emplace(employee);
}
//this is the function
void Manager::removeEmployee(int id) {
for(auto it = employees.begin(); it != employees.end(); it++){
if(it->get()->getId() == id){
employees.erase(it);
return;
}
}
throw mtm::EmployeeDoesNotExists();
}
Manager *Manager::clone() {
return new Manager(*this);
}
ostream &Manager::printShort(ostream &os) const {
os<<this->getFirstName()<<" "<<this->getLastName()<<endl;
os<<"Salary :"<<this->getSalary()<<endl;
return os;
}
ostream &Manager::printLong(ostream &os) const {
os<<this->getFirstName()<<" "<<this->getLastName()<<endl;
os<<"id - "<<this->getId()<<" birth_year - "<<this->getBirthYear()<<endl;
os<<"Salary :"<<this->getSalary()<<endl;
os<<"Employees:"<<endl;
for(const auto & employee : employees){
employee->printShort(os);
}
return os;
}
bool Manager::findEmployee(int id) {
int i = 0;
for(const auto & employee : employees){
cout<<++i<<endl;
if(employee->getId() == id){
cout<<"return true"<<endl;
return true;
}
}
cout<<"return false"<<endl;
return false;
}
bool Manager::isWorkFlag() const {
return work_flag;
}
void Manager::setWorkFlag(bool workFlag) {
work_flag = workFlag;
}
and this is the main function:
int main() {
Employee e1(1, "John", "Williams", 2002);
Employee e2(2, "Alex", "Martinez", 2000);
Manager m1(1,"Robert", "stark", 1980);
m1.addEmployee(&e1);
m1.addEmployee(&e2);
Employee e3(7, "Reuven", "Guetta", 2001);
m1.addEmployee(&e3);
m1.printLong(cout);
cout<<"Delete"<<endl;
//here is the problem
m1.removeEmployee(e2.getId());
m1.printLong(cout);
return 0;
}
shared_ptr<Employee> employee(employee_add);
There is only one reason to have a shared_ptr, in the first place; there's only one reason for its existence; it has only one mission in its life, as explained in every C++ textbook: to be able to new an object, and have the shared_ptr automatically take care of deleteing it when all references to the object are gone, avoiding a memory leak.
In your program this object was not instantiated in dynamic scope with new:
Employee e2(2, "Alex", "Martinez", 2000);
Manager m1(1,"Robert", "stark", 1980);
m1.addEmployee(&e1);
// etc, etc, etc...
and that's the reason for the crash.
If you are not using new, simply get rid of all shared_ptrs in the shown code.

Writing a JSON parser for C++

So far I have managed to put together a lexer and a stack in the hopes of achieving a LL1 parser. I am doing this purely to understand how parsing works, and maybe to use these ideas in future projects. I understand there are much better frameworks out there like json-cpp and rapid-json but I would like to understand this for myself.
The header file is give below.
#pragma once
#include <string>
#include <vector>
#include <map>
#include <variant>
#include <fstream>
#include <stack>
#include "Helper.h"
// Debugging
#include <iostream>
// Types to store JSON ouput
struct jlist;
struct jobject;
using json_value = std::variant<int, float, bool, std::string, jlist, jobject>;
enum tag { int_value, float_value, string_value, list, object };
struct jlist {
tag type;
std::vector<json_value *> vector_value;
};
struct jobject {
tag type;
std::map<std::string, json_value *> map_value;
};
class JSONParser
{
public:
JSONParser();
~JSONParser();
void parseFile(std::string);
private:
std::stack<std::string> s;
bool checkDeliminator(char);
std::vector<std::string> lexer(std::ifstream &);
void parser(std::vector<std::string> &);
void transitionTable(std::string cursor);
};
The implementation is as follows.
#include "genetic-optimization/JSONParser.h"
JSONParser::JSONParser() {
}
JSONParser::~JSONParser() = default;
void JSONParser::parseFile(std::string FILE) {
std::ifstream configfile(FILE);
std::vector<std::string> scan = lexer(configfile);
parser(scan);
}
bool JSONParser::checkDeliminator(char piece) {
switch (piece) {
case '[':
return true;
case ']':
return true;
case '{':
return true;
case '}':
return true;
case ':':
return true;
case ',':
return true;
case '"':
return true;
default:
return false;
}
}
std::vector<std::string> JSONParser::lexer(std::ifstream & configfile) {
char piece;
std::string capture = "";
std::string conversion;
std::vector<std::string> capture_list;
while(configfile >> piece) {
if (checkDeliminator(piece)) {
conversion = piece;
if (capture != "") {
capture_list.push_back(capture);
capture_list.push_back(conversion);
capture = "";
} else {
capture_list.push_back(conversion);
}
} else {
capture += piece;
}
}
return capture_list;
}
void JSONParser::parser(std::vector<std::string> & scan) {
for (auto it = scan.begin(); it != scan.end(); ++it) {
std::cout << *it << "\n"; // Make sure the lexer works
transitionTable(*it);
}
}
void JSONParser::transitionTable(std::string cursor) {
if(s.empty()) {
s.push(cursor);
} else {
if (s.top() == "[") {
s.push(cursor);
} else if (s.top() == "]") {
s.pop();
} else if (s.top() == "{") {
s.push(cursor);
} else if (s.top() == "}") {
s.pop();
}
}
}
I am unsure of how to proceed from here but have been using the json grammar as a starting point and the following tutorial for guidance.
json -> element
value -> object|array|string|number|bool|
object -> {}|{members}
members -> member|member,members
member -> string:element
array -> []|[elements]
elements -> element|element,elements
element -> value
I have three main problems.
The JSON grammar seems to have left indirect recursion. Since the grammar is not as simple as that shown in the tutorial I do not know how to eliminate it.
I do not know how to generate the parse table (finite state machine), specifically for something like First(object), what would this be? Is there any resource that has produced a parse table for JSON and might point me in the right direction?
The tutorial seems more to verify that the expression being parsed is produced by the grammar but I would like to store the structure in a variable. Where would this be done and do you have any advice for how this might look in pseudo (or even better C++) code.
For completeness, I am using the following JSON as a test.
[
{
"libraries":[
"terminal",
"binary"
] ,
"functions":[
"terminal-basic",
"binary-basic"
]
}
,
{
"name":"addition",
"type":"binary-basic",
"function":"add_float",
"input":{
"float" : 2
},
"output":"float",
"max-number":2
}
,
{
"name":"exponent",
"type":"binary-basic",
"function":"exponent_float",
"input":{
"float":2
},
"output":"float",
"max-number":2
}
,
{
"name":"exponent",
"type":"binary-basic",
"function":"exponent_float",
"input":{
"float":2,
"int":1
},
"output":"float",
"max-number":1
}
,
{
"name":"constant_1",
"type":"terminal-basic",
"function":"non_random_constant",
"value":0.5,
"input":{ },
"output":"float",
"max-number":3
}
,
{
"name":"constant_2",
"type":"terminal-basic",
"function":"non_random_constant",
"value":2.0,
"input":{ },
"output":"float",
"max-number":3
}
,
{
"name":"constant_3",
"type":"terminal-basic",
"function":"non_random_constant",
"value":true,
"input":{
"bool":1
},
"output":"bool",
"max-number":1
}
]
I wouldn't like to leave this question unanswered for anyone coming here in the future, however, I am personally not a big fan of the code that accompanies this answer. It feels inefficient, not particularly elegant and I am unsure if it represents the theoretical model I was trying to implement in the first place. I took my lead from #MSalters comment, which to me meant build something that works and worry if the model is theoretically sound later. Below is my attempt.
The header adds a few more functions. Many of them purely to assist fsm and parser.
class JSONParser
{
public:
JSONParser();
~JSONParser();
void parseFile(std::string);
private:
json_value root;
std::stack<std::string> s;
std::stack<json_value> s_value;
// Lexer
bool checkDeliminator(char);
std::vector<std::string> lexer(std::ifstream &);
// FSM varaibles
enum state { int_value, float_value, bool_value, string_value, default_value, bad_state};
state current;
// FSM
void fsm(std::string);
// Parser variables
enum stack_map { list_open, list_close, object_open, object_close, colon, comma, buffer, follow};
std::map<std::string, stack_map> stack_conversion;
// Parser helper functions
template<typename T> void addElement();
template<typename T> void insert(std::string &, T (*)(const std::string &));
template<typename T> void insert();
void insert(std::string &);
void pushBuffer();
template<typename ... T> bool multiComparision(const char scope, T ... args);
bool isDigit(const char);
static int st2i(const std::string & value);
static float st2f(const std::string & value);
static bool st2b(const std::string & value);
// Parser
void parser(const std::string & cursor);
};
The implementation file follows.
#include "genetic-optimization/JSONParser.h"
JSONParser::JSONParser() {
state current = default_value;
stack_conversion = { { "[", list_open }, { "]", list_close }, { "{", object_open }, { "}", object_close }, { ":", colon }, { ",", comma }, { "buffer", buffer } };
}
JSONParser::~JSONParser() = default;
void JSONParser::parseFile(std::string FILE) {
std::ifstream configfile(FILE);
std::vector<std::string> scan = lexer(configfile);
scan.push_back("terminate");
for (auto it = scan.begin(); it != scan.end(); ++it) {
parser(*it);
}
root = s_value.top();
s_value.pop();
}
// Lexer
bool JSONParser::checkDeliminator(char piece) {
switch (piece) {
case '[':
return true;
case ']':
return true;
case '{':
return true;
case '}':
return true;
case ':':
return true;
case ',':
return true;
default:
return false;
}
}
std::vector<std::string> JSONParser::lexer(std::ifstream & configfile) {
char piece;
std::string capture = "";
std::string conversion;
std::vector<std::string> capture_list;
while(configfile >> piece) {
if (checkDeliminator(piece)) {
conversion = piece;
if (capture != "") {
capture_list.push_back(capture);
capture_list.push_back(conversion);
capture = "";
} else {
capture_list.push_back(conversion);
}
} else {
capture += piece;
}
}
return capture_list;
}
// FSM
void JSONParser::fsm(std::string value) {
current = default_value;
char point;
auto it = value.begin();
while (it != value.end()) {
point = *it;
if (point == '"' & current == default_value) {
current = string_value;
return;
} else if (isdigit(point)) {
if (current == default_value | current == int_value) {
current = int_value;
++it;
} else if (current == float_value) {
++it;
} else {
current = bad_state;
return;
}
} else if (point == '.' & current == int_value) {
current = float_value;
++it;
} else if (point == 'f' & current == float_value) {
++it;
} else if (current == default_value) {
if (value == "true" | value == "false") {
current = bool_value;
return;
} else {
current = bad_state;
return;
}
} else {
current = bad_state;
return;
}
}
}
// Parser Helper functions
template<>
void JSONParser::addElement<jobject>() {
json_value value_read;
json_value key_read;
value_read = s_value.top();
s_value.pop();
key_read = s_value.top();
s_value.pop();
std::get<jobject>(s_value.top()).insert(key_read, value_read);
}
template<>
void JSONParser::addElement<jlist>() {
json_value value_read;
value_read = s_value.top();
s_value.pop();
std::get<jlist>(s_value.top()).push_back(value_read);
}
template<typename T>
void JSONParser::insert(std::string & value, T (*fptr)(const std::string &)) {
T T_value(fptr(value));
s_value.push(T_value);
}
template<typename T>
void JSONParser::insert() {
T T_value;
s_value.push(T_value);
}
void JSONParser::insert(std::string & value) {
value.erase(std::remove(value.begin(), value.end(), '"'), value.end());
s_value.push(value);
}
void JSONParser::pushBuffer() {
s.pop();
s.push("buffer");
}
template<typename ... T>
bool JSONParser::multiComparision(const char scope, T ... args) {
return (scope == (args || ...));
}
bool JSONParser::isDigit(const char c) {
return multiComparision<char>(c, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0');
}
int JSONParser::st2i(const std::string & value) {
return stoi(value);
}
float JSONParser::st2f(const std::string & value) {
return stof(value);
}
bool JSONParser::st2b(const std::string & value) {
if (value == "true") {
return true;
} else {
return false;
}
}
// Parser
void JSONParser::parser(const std::string & cursor) {
if(s.empty()) {
s.push(cursor);
} else {
stack_map stack_value;
std::string value = s.top();
if (stack_conversion.find(value) != stack_conversion.end()) {
stack_value = stack_conversion[s.top()];
} else {
stack_value = follow;
}
switch (stack_value) {
case buffer:
s.pop();
break;
case list_open:
insert<jlist>();
if (cursor == "]") {
pushBuffer();
return;
}
break;
case list_close:
addElement<jlist>();
s.pop();
s.pop();
break;
case object_open:
insert<jobject>();
if (cursor == "}") {
pushBuffer();
return;
}
break;
case object_close:
addElement<jobject>();
s.pop();
s.pop();
break;
case colon:
s.pop();
break;
case comma:
s.pop();
if (s.top() == "{") {
addElement<jobject>();
} else {
addElement<jlist>();
}
break;
default:
s.pop();
fsm(value);
switch (current) {
case string_value:
insert(value);
break;
case int_value:
insert<int>(value, st2i);
break;
case float_value:
insert<float>(value, st2f);
break;
case bool_value:
insert<bool>(value, st2b);
break;
default:
std::cout << "Bad state\n";
}
}
s.push(cursor);
}
}
The idea was to have the lexer break at each deliminator and place all the generated tokens into a vector. This vector called scan could then be looped through. At each iteration of this loop parser would be run. In general this reads the top of the stack s and determines whether a bracket/brace is opening or closing or a terminal value has been reached. If a bracket/brace is opening, a new jobject or jlist is generated and placed onto a new stack s_value, if a terminal value is reached fsm (finite state machine) runs and determines the type of value and places it on top of s_value, should a comma or closing bracket be reached the appropriate values are moved off the stack and the elements in s_value are inserted into their appropriate containers.
The biggest meatball in this spaghetti is how elements in the JSON tree are called.
std::cout << std::get<bool>(std::get<jobject>(std::get<jobject>(std::get<jlist>(root)[6])["input"])["bool"]); // Should return 1
While this does indeed return 1. The nested std::get calls seem just plain wrong and I'm not sure if they can be incorporated into the operator [] or through (sigh) a third stack that tracks the type of object being stored.
This was my basic attempt, it's not pretty but it does work. Hopefully I can refine it further and improve on what I have.
I am not an expert at parsing so my answer would be very heuristic...
JSON grammar is simple. I believe we do not need to try to understand of follow over-specified (E)BNF form to actually parse JSON string. Try to write your own simple form. After you do that, you may feel a need for a better form. Then you can re-try to fully understand why there are such grammars.
Isn't FSM simply "you have to do that in this state?" States are preferably managed by a stack (not like you have to have an instance whose members indicate states like an abstract figure in text book in many cases of the real world) and you will do what you have to do in loops based on a top state of the stack. I believe you do not need an instance of 'parse table.' Can it be abstract or pervasively exists somewhere in code?
I also started to practice parsing with JSON. Please check my single header file.
I used 7 stack statuses:
enum status {
READING_OBJECT_KEY,
READ_OBJECT_KEY,
READING_OBJECT_VALUE, READING_ARRAY_VALUE,
READ_OBJECT_VALUE, READ_ARRAY_VALUE, READ_OTHER_VALUE
};
Heuristically, I started actual parsing after skipping preceding whitespace and check the first non-whitespace character:
} else if (p.c == '{') {
p.ps.push(json::parsing::READING_OBJECT_KEY);
j = json::object();
p.js.push(j.v);
break;
} else if (p.c == '[') {
p.ps.push(json::parsing::READING_ARRAY_VALUE);
j = json::array();
p.js.push(j.v);
break;
}
Then I actually started to parse with 8 functions:
while (p.iss.get(p.c)) {
p.i++;
if (p.c == ' ' ) {}
else if (p.c == '{' ) json::parse__left_brace(p);
else if (p.c == '}' ) json::parse__right_brace(p);
else if (p.c == '[' ) json::parse__left_bracket(p);
else if (p.c == ']' ) json::parse__right_bracket(p);
else if (p.c == ':' ) json::parse__colon(p);
else if (p.c == ',' ) json::parse__comma(p);
else if (p.c == '\"') json::parse__quote(p);
else json::parse__else(p);
}

Sorting linked list in C++ fails at runtime

void head_insert(DomesticPtr& head, string firstNameD, string lastNameD, string province, float cgpaD, int researchScoreD, int idD)
{
DomesticPtr temp_ptr;
DomesticPtr temp2;
temp_ptr= new DomesticStudent(head, firstNameD, lastNameD, province,cgpaD,researchScoreD,idD);
temp2 = head->getLink();
temp2==temp_ptr;
head=temp_ptr;
if (head->getLink() == NULL)
return;
else
{
bubblesort(head);
}
}
void bubblesort(DomesticStudent* head)
{
int rsd;
int cgpad;
int p;
DomesticPtr tempc, tempd, tempe;
tempd=head;
tempe= head->getLink();
{
while(tempd != NULL)
{
rsd=compareResearchScore(tempd, tempe);
if (rsd==1)
{
tempc=head;
head->next=head;
head=tempc;
}// if
else if (rsd==0)
{
cgpad= compareCGPA(tempe,tempd);
if (cgpad==1)
{
tempc=head;
head->next=head;
head=tempc;
}// if (cgpad[k]>cgpad[k+1])
else if(cgpad==0)
{
p=compareProvince(tempd,tempe);
if(p==1)
{
tempc=head;
head->next=head;
head=tempc;
}// if (p[k]>p[k+1])
}//
}// else if cgpad[k]
}// else if rsd[k]
// }
// }
tempd = tempe;
}
int compareResearchScore(DomesticPtr RSA, DomesticPtr RSB)
{
if (RSB == NULL || RSA==NULL )
{
return 0;
}
if (RSA->researchScoreD==RSB->researchScoreD) //compares if is the same for domesetic students returns value for bubble sort
{
return 0;
}
if (RSA->researchScoreD > RSB->researchScoreD)
{
return 1;
}
if (RSA->researchScoreD< RSB->researchScoreD)
{
return -1;
}
}
I'm trying to to have my linked list sorted every time a new node is inserted. It compiles but every time I try to run the program it is stuck on the point that I am trying to print my list. I have a destructor but no copy constructor or assignment operator.
The head_insert calls the sort function and the sort function calls the compare function to receive an integer output so that it can make a swap. I want to compare research, the cgpa, and then province. Any input would be much appreciated, this is for a project so I wouldn't like any blocks of code but if you could point me in the right direction or multiple directions.

how to remove a shared ptr element from set?

I have a set where each element in the set is of type shared_ptr, I want to remove an element from the set, in eclipse the element was actually removed but when I test this in bash with valgrind I get a lot of invalid size mistakes ...
So this made me think that maybe there is a different way to remove element of type shared_ptr ?
Every element in the peoplePointer is a class of certain person:
typedef std::shared_ptr<person> peoplePointer;
class AA {
std::set<peoplePointer> setOfPeople;
public:
// function getName() return name of the person (person is another class)
void removeSomeonefromA(const std::string& name) {
for (std::set<peoplePointer>::iterator it = setOfPeople.begin();it != setOfPeople.end(); it++) {
if(name == (*it).get()->getName()) {
setOfPeople.erase((it));
}
}
}
};
Idea inspired by remove_if equivalent for std::map.
If you are able to use a C++11 or later compiler, you can use:
void removeSomeonefromA(const string& name)
{
for (set<peoplePointer>::iterator it = setOfPeople.begin(); it != setOfPeople.end(); /* Empty */ )
{
if(name == (*it).get()->getName())
{
it = setOfPeople.erase(it);
}
else
{
++it;
}
}
}
If you are required to use a prior compiler version, you can use:
void removeSomeonefromA(const string& name)
{
for (set<peoplePointer>::iterator it = setOfPeople.begin(); it != setOfPeople.end(); /* Empty */ )
{
if(name == (*it).get()->getName())
{
setOfPeople.erase(it++);
}
else
{
++it;
}
}
}

Debug error abort() has been called Qt

When adding this code I get the debug error. This function is called from a Dialog class if you need to see that code too I'll post it, but what I do there is convert QString to strings and int's and then call the function.
void MediaHandler::changeMedia(std::string title, std::string des, int publishYear,
int rating, std::string var1, int var2)
{
int pos = this->find(title);
Book *aBookPtr = dynamic_cast<Book*>(this->medias[pos]);
Movie *aMoviePtr = dynamic_cast<Movie*>(this->medias[pos]);
TvSeries *aTvSeriesPtr = dynamic_cast<TvSeries*>(this->medias[pos]);
if(aBookPtr != nullptr)
{
aBookPtr->setTitle(title);
aBookPtr->setDes(des);
aBookPtr->setPublishYear(publishYear);
aBookPtr->setRating(rating);
aBookPtr->setAuthor(var1);
aBookPtr->setNrOfPages(var2);
}
else if(aMoviePtr != nullptr)
{
aMoviePtr->setTitle(title);
aMoviePtr->setDes(des);
aMoviePtr->setPublishYear(publishYear);
aMoviePtr->setRating(rating);
aMoviePtr->setMainActor(var1);
aMoviePtr->setMovieLength(var2);
}
else if(aMoviePtr != nullptr)
{
aTvSeriesPtr->setTitle(title);
aTvSeriesPtr->setDes(des);
aTvSeriesPtr->setPublishYear(publishYear);
aTvSeriesPtr->setRating(rating);
aTvSeriesPtr->setMainActor(var1);
aTvSeriesPtr->setNrOfEpisodes(var2);
}
}