My code (below) works unless the required key isn't in the list yet (so if a node doesn't have a reference to its parent). It ignores the nodes and just makes a tree without them. How can I fix it? I'm thinking about just re-looping once all the keys are in and just keep adding and removing accordingly.
#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include <map>
struct Foo {
int data{0};
int left{-1};
int right{-1};
};
std::istream& operator>>(std::istream& in, Foo& ff) {
in >> ff.data >> ff.left >> ff.right;
return in;
}
struct Del {
template <class T>
void operator()(T* p) {
std::cout << "[deleted #" << (p ? p->data : 0) << "]\n";
delete p;
}
};
struct Bar {
int data{0};
std::unique_ptr<Bar, Del> lef;
std::unique_ptr<Bar, Del> rig;
};
void print(const std::unique_ptr<Bar, Del>& node) {
if (node) {
std::cout << ' ' << node->data;
print(node->lef);
print(node->rig);
}
}
int main() {
std::string input =
"101 1 3 102 2 8 104 6 7 103 -1 5 109 -1 -1 106 4 -1 107 -1 -1 108 -1 "
"-1 105 -1 -1";
std::istringstream IN(input);
std::map<int, std::pair<Bar*, bool>> mlist;
std::unique_ptr<Bar, Del> root;
int row = 0;
Foo entry;
while (IN >> entry) {
if (0 == row) {
root.reset(new Bar);
Bar* node = root.get();
node->data = entry.data;
std::cout << row << " [created #" << entry.data << ']';
if (0 <= entry.left)
mlist.emplace(entry.left, std::make_pair(node, true));
if (0 <= entry.right)
mlist.emplace(entry.right, std::make_pair(node, false));
} else {
auto it = mlist.find(row);
if (mlist.end() != it) {
if (it->second.second) {
it->second.first->lef.reset(new Bar);
Bar* node = it->second.first->lef.get();
node->data = entry.data;
std::cout << row << " [created #" << entry.data << ']';
if (0 <= entry.left)
mlist.emplace(entry.left, std::make_pair(node, true));
if (0 <= entry.right)
mlist.emplace(entry.right, std::make_pair(node, false));
mlist.erase(it);
} else {
it->second.first->rig.reset(new Bar);
Bar* node = it->second.first->rig.get();
node->data = entry.data;
std::cout << row << " [created #" << entry.data << ']';
if (0 <= entry.left)
mlist.emplace(entry.left, std::make_pair(node, true));
if (0 <= entry.right)
mlist.emplace(entry.right, std::make_pair(node, false));
mlist.erase(it);
}
// mlist.erase( it );
}
}
std::cout << " list size " << mlist.size() << '\n';
++row;
}
std::cout << "final list size " << mlist.size() << "\n\n";
print(root);
std::cout << "\n\n";
std::cout << "Lets see whats left in the list:";
return 0;
}
Actually, I just used a vector of nodes and it worked perfectly. Sorry for all the confusion!
Related
Consider the following simple class.
#include <iostream>
using namespace std;
class test
{
public:
int* myvar;
int sz;
test()
{
sz = 10;
myvar = new int[10];
}
void dump()
{
for(int i = 0; i < sz; i++)
{
cout << myvar[i] << " ";
}
cout << endl;
}
int& operator()(int index)
{
if(index >= sz)
{
int* newvar = new int[index+1];
for(int i = 0; i < sz; i++)
{
newvar[i] = myvar[i];
}
sz = index+1;
delete myvar;
myvar = newvar;
}
return myvar[index];
}
const int operator()(int index) const
{
if(index >= sz)
{
throw "index exceeds dimension";
}
else
{
return myvar[index];
}
}
};
It should behave like a dynamic array. I overloaded the () operator. My idea was, that for an assignment (lvalue), the upper version of the () will be called, and for a "read only" operation (rvalue) the lower version of () is used. The sample code should explain more clearly what I mean:
int main()
{
test x;
// will give 10 times zero
x.dump();
// assign some values
x(1) = 7;
x(9) = 99;
// will give
// 0 7 0 0 0 0 0 0 0 99
x.dump();
// should give 7
cout << x(1) << endl;
// should give 99
cout << x(9) << endl;
// this will increase the size of myvar to 15 elements and assign a value
x(15) = 15;
// this should give
// 0 7 0 0 0 0 0 0 0 99 0 0 0 0 0 15
x.dump();
// this should throw an exception because x(20) got never assigned a value!
// but instead of calling the lower version of operator() it also calls the
// upper, resulting in x being expanded now to 21 elements.
cout << x(20) << endl;
// will give 21 elements, instead of 16.
x.dump();
return 0;
}
So I access the contents of myvar via the () operator. It should be possible to assign a value just to any element, but it shall not be possible to query the value of an element that has never been set before. I thought by using different versions of (), one of which being const should suffice, but apparently, the compiler is always using the upper version of my operator, and never the lower. How can I fix this problem?
I read about the proxy object, e.g here, but I think this implementation will not work in my case because I am using an array. So
a) is it possible without the proxy, or if not
b) how should the proxy look like in my case?
So this is the solution I finally came up with (sort of):
#include <iostream>
using namespace std;
template <class T> class myclass
{
private:
unsigned numel;
T* elem;
public:
class proxy
{
private:
T*& elem;
unsigned& numel;
const unsigned index;
proxy(T*& elem, unsigned& numel, unsigned index) : elem(elem), numel(numel), index(index) { }
// didn't really need those two
// proxy(const proxy&) = default;
// proxy(proxy&&) = default;
friend class myclass;
public:
proxy& operator=(const T& value)
{
if(index >= numel)
{
cout << "assignment to an element outside the range!" << endl;
cout << "old size: " << numel << endl;
cout << "new size: " << index+1 << endl << endl;
T* newelem = new T[index+1];
for(unsigned i = 0; i <= index; i++)
{
if(i < this->numel)
{
newelem[i] = this->elem[i];
}
else
{
newelem[i] = 0;
}
}
if(this->elem != nullptr)
{
delete this->elem;
}
this->elem = newelem;
this->numel = index+1;
}
this->elem[index] = value;
return *this;
}
proxy& operator=(const proxy &other)
{
*this = (const T&)other;
return *this;
}
operator T&()
{
if(index >= numel)
{
cout << "cannot query the value of elements outside the range!" << endl;
cout << "# of elements: " << numel << endl;
cout << "index requested: " << index << endl << endl;
throw out_of_range("");
}
return elem[index];
}
operator const T&() const
{
if(index >= numel)
{
throw out_of_range("");
}
return elem[index];
}
};
myclass() : numel(0), elem(nullptr) {};
myclass(unsigned count)
{
this->numel = count;
this->elem = new T[count];
}
~myclass()
{
if(this->elem != nullptr)
{
delete this->elem;
}
}
friend ostream& operator<<(ostream& os, const myclass& mc)
{
os << endl;
for(unsigned i = 0; i < mc.numel; i++)
{
os << mc.elem[i] << " ";
os << endl;
}
os << endl;
return os;
}
proxy operator()(unsigned index)
{
return proxy(this->elem, this->numel, index);
}
};
int main()
{
myclass<double> my;
my(1) = 77;
my(0) = 200;
my(8) = 12;
cout << my;
try
{
cout << my(0) << endl;
cout << my(1) << endl;
cout << my(8) << endl;
cout << my(10) << endl;
}
catch(...)
{
cout << "error catched" << endl << endl;
}
my(10) = 10101;
cout << my(10) << endl;
}
the output on the terminal looks like this:
assignment to an element outside the range!
old size: 0
new size: 2
assignment to an element outside the range!
old size: 2
new size: 9
200
77
0
0
0
0
0
0
12
200
77
12
cannot query the value of elements outside the range!
# of elements: 9
index requested: 10
error catched
assignment to an element outside the range!
old size: 9
new size: 11
10101
I have this "movie store.cpp"
#include "List.h"
#include <iomanip>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cmath>
using namespace std;
//****************************************************************************************************
const static char* FILE_NAME = "Movies.csv";
int totalCheckedIn1 = 0;
int totalCheckedOut1 = 0;
//****************************************************************************************************
struct Movie
{
int MPAC;
int year;
int runtime;
int checkedIn;
int checkedOut;
string title;
Movie()
{
}
Movie(int m, int y, int r, int ci, int co, string t)
{
MPAC = m;
year = y;
runtime = r;
checkedIn = ci;
checkedOut = co;
title = t;
}
bool operator == (const Movie& rhs) const
{
return (MPAC == rhs.MPAC);
}
Movie& operator =(const Movie& rhs)
{
MPAC = rhs.MPAC;
year = rhs.year;
runtime = rhs.runtime;
checkedIn = rhs.checkedIn;
checkedOut = rhs.checkedOut;
title = rhs.title;
return *this;
}
friend ostream& operator <<(ostream& os, const Movie& m);
};
void setInventory(List<Movie> z, double f)
{
}
//****************************************************************************************************
ostream& operator<<(ostream& os, const Movie& m)
{
os << setw(7) << left << m.MPAC
<< setw(25) << left << m.title
<< setw(7) << left << m.year
<< setw(10) << left << m.runtime
<< setw(7) << left << m.checkedIn
<< setw(7) << left << m.checkedOut;
return os;
}
//****************************************************************************************************
void getData(List<Movie>& Movies);
void displayList(List<Movie>& Movies);
void findMovies(List<Movie> Movies);
//****************************************************************************************************
int main()
{
List<Movie> WebsterMovies;
getData(WebsterMovies);
cout << "CHECK";
displayList(WebsterMovies);
// findMovies(WebsterMovies);
setInventory(WebsterMovies, 10.5);
cout << "The following data is the updated Webster Movies store\n";
//displayList(WebsterMovies);
system("PAUSE");
return 0;
}
//****************************************************************************************************
void getData(List<Movie>& Movies)
{
ifstream infile(FILE_NAME);
if (!infile)
{
cout << "Problem opening file" << endl;
exit(99);
}
while (!infile.eof())
{
Movie m;
if (infile.peek() == EOF)
break;
infile >> m.MPAC;
infile.ignore();
infile >> m.year;
infile.ignore();
infile >> m.runtime;
infile.ignore();
infile >> m.checkedIn;
infile.ignore();
infile >> m.checkedOut;
infile.ignore();
getline(infile, m.title);
Movies.insert(m);
}
infile.close();
}
//****************************************************************************************************
void displayList(List<Movie>& Movies)
{
int totalCheckedIn = 0;
int totalCheckedOut = 0;
cout << "The Webster Movie Store list includes : " << endl;
cout << setw(7) << left << "MPAC"
<< setw(25) << left << "Title"
<< setw(7) << left << "Year"
<< setw(10) << left << "RunTime"
<< setw(7) << left << "In"
<< setw(7) << left << "Out" << endl;
cout << "-------------------------------------------------------------------------------" << endl;
double totalRunTime = 0;
for (int i = 0, size = Movies.getNumber();
i < size; ++i)
{
Movie m = Movies.getNext();
cout << m << endl;
totalRunTime += m.runtime;
totalCheckedIn += m.checkedIn;
totalCheckedOut += m.checkedOut;
}
cout << "The average run time for the " << Movies.getNumber()
<< " movies is " << fixed << setprecision(1)
<< totalRunTime / Movies.getNumber() << endl;
cout << "There are " << totalCheckedIn << " movies checked in " << endl;
cout << "There are " << totalCheckedOut << " movies checked out" << endl;
totalCheckedIn1 = totalCheckedIn;
}
//****************************************************************************************************
void findMovies(List<Movie> Movies)
{
while (true)
{
cout << "Enter the MPAC of a movie to locate:";
int input;
cin >> input;
if (input == 0)
break;
Movie m;
m.MPAC = input;
if (Movies.getMember(m))
{
cout << setw(7) << left << "MPAC"
<< setw(25) << left << "Title"
<< setw(7) << left << "Year"
<< setw(10) << left << "RunTime"
<< setw(7) << left << "In"
<< setw(7) << left << "Out" << endl;
cout << "-------------------------------------------------------------------------------" << endl;
cout << m << endl;
}
else
{
cout << "That movie is not in the store" << endl;
}
}
}
this is "list.h"
#ifndef LIST_H
#define LIST_H
#include <iostream>
//********************************************************************************
template <typename T>
class List
{
public:
List();
List(int size);
List(const List &obj);
~List();
void insert(T);
T getNext(); // Returns the next element in the array.
bool getMember(T&); // Returns true if we can find the member, false otherwise.
int getNumber(); // Returns the number of items in the list.
private:
T *pList;
int numberInList; // Number of elements in the list.
int listSize; // Size of the list.
int nextIndex; // Index that points to the next element in the array.
};
//********************************************************************************
// Default Constructor
template <typename T>
List<T>::List()
{
numberInList = 0;
listSize = 100;
nextIndex = 0;
pList = new T[listSize];
}
//********************************************************************************
// Overloaded Constructor
template <typename T>
List<T>::List(int size)
{
numberInList = 0;
listSize = size;
nextIndex = 0;
pList = new T[listSize];
}
//********************************************************************************
// Copy Constructor
template <typename T>
List<T>::List(const List &obj)
{
numberInList = obj.numberInList;
listSize = obj.listSize;
nextIndex = obj.nextIndex;
pList = new T[listSize];
for (int i = 0; i < listSize; i++)
{
pList[i] = obj.pList[i];
}
}
//********************************************************************************
// Destructor
template <typename T>
List<T>::~List()
{
delete[]pList;
}
//********************************************************************************
template <typename T>
void List<T>::insert(T item)
{
int temp = numberInList++;
pList[temp] = item;
}
//********************************************************************************
template <typename T>
T List<T>::getNext()
{
return pList[nextIndex++];
}
//********************************************************************************
template <typename T>
bool List<T>::getMember(T& item)
{
for (int i = 0; i < numberInList; ++i)
{
if (item == pList[i])
{
item = pList[i];
return true;
}
}
return false;
}
//********************************************************************************
template <typename T>
int List<T>::getNumber()
{
return numberInList;
}
#endif
Problem i have is that setInventory function needs to update the checkedIn member of each list element using the formula (CheckedIn + CheckedOut) * ( f /100.0). Can someone guide me how can i update individual element using this function.help i got said" In order to update each element of the List, you need modify the template to include a setItem function that sets the associated element in the List object to the item that is passed to the setItem function. HINT: This function should only contain one C++ statement."
if someone can guide me syntax of how i can update individual elements.
this is something i wrote for setInventory()
void setInventory(List<Movie> WebsterMovies , double f)
{
Movie m = WebsterMovies.getNext();
cout << m << endl;
cout << "Check again" << endl << endl;
int size = WebsterMovies.getNumber();
int increment = 0;
for (int i = 0 ; i < size; ++i)
{
cout << m << endl;
increment = trunc(((m.checkedIn + m.checkedOut) * f )/ 100);
m.checkedIn = m.checkedIn + increment;
cout << "updated checkin is : " << m.checkedIn << endl;
WebsterMovies.setItem(m);
Movie m = WebsterMovies.getNext();
}
}
this is setItem i wrote
template <typename T>
void List<T>::setItem(T item)
{
pList[numberInList] = item;
}
p.s beginner here so sorry for bad English or any other mistake.
To update an element in a container, such as std::list, you need to find the element, then update the fields.
An example:
std::list<Movie> database;
// Search by title
std::list<Movie>::iterator iter;
const std::list<Movie>::iterator end_iter = database.end();
for (iter = database.begin();
iter != end_iter;
++iter)
{
if (iter->title == search_title)
{
Update_Movie(*iter);
}
}
The destructor for List appears to work, but having trouble with the destructor for Element and List_iter:
Unhandled exception : 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x002E2F78).
List:
#ifndef GUARD_List_h
#define GUARD_List_h
#include "Element.h"
#include "List_iter.h"
template <typename T>
class List {
public:
List() : begins(new Element<T>), ends(new Element<T>), Element_count(0) {
begins->t_flag = 'b';
ends->t_flag = 'e';
// double link: begins & ends
begins->next = ends;
ends->prev = begins;
}
virtual ~List() {
while (begins->next != ends) {
begins->prev = begins->next;
begins->next = begins->next->next;
delete begins->prev;
}
delete begins;
delete ends;
}
typedef List_iter<T> iterator;
iterator begin(void) const {
iterator it(begins);
return it;
}
iterator end(void) const {
iterator it(ends);
return it;
}
void push_back(const T val) {
Element<T>* elem = new Element<T>; // create: new-elem
elem->data = val; // set data
elem->prev = ends->prev; // link: new-elem to last-data-elem
ends->prev->next = elem; // link: last-data-elem to new-Element
elem->next = ends; // link: new-elem to List-end
ends->prev = elem; // link: List-end to new-elem
Element_count++; // update: when List grows
}
T at(const size_t pos) const {
return get_Element(pos)->data;
}
void del(const size_t pos) const {
Element<T>* elem = get_Element(pos); // get: Element for deletion
elem->prev->next = elem->next; // rejoin: double link
elem->next->prev = elem->prev; // rejoin: double link
delete elem;
Element_count--; // update: when List shrinks
}
void clear(void) {
Element<T>* ep = begins->next;
Element<T>* ep_next = ep->next;
while (ep->t_flag != 'e'){
delete ep;
ep = ep_next;
ep_next = ep->next;
}
begins->next = ends;
ends->prev = begins;
//begins->data = 0r;
//ends->elem_ID = 0;
Element_count = 0;
}
size_t size(void) const {
return Element_count;
}
bool empty(void) const {
if (Element_count == 0){ return true; }
else { return false; }
}
private:
Element<T>* begins; // List begins
Element<T>* ends; // List ends
size_t Element_count; // List size
Element<T>* get_Element(const size_t pos) const {
if (empty()) {
std::cerr << "No Element - Empty List";
throw;
}
if (pos < 0 || pos >= Element_count){
std::cerr << "No Element - Out of Range";
throw;
}
iterator it;
// Determine the more efficent iteration direction(forward or reverse) ?
if ((Element_count / 2) > pos) {
it = begin();
for (size_t i = 0; i <= pos; i++){
it++;
}
}
else {
it = end();
for (size_t i = size() - pos; i > 0; i--){
it--;
}
}
return it.elem;
}
};
#endif
Element:
#ifndef GUARD_Element_h
#define GUARD_Element_h
template <class T>
class List;
template <class T>
class List_iter;
template <class T>
class Element {
public:
Element() : prev(nullptr), next(nullptr), data(), t_flag(' ') {}
virtual ~Element() {
delete prev;
delete next;
}
friend List<T>;
friend List_iter<T>;
private:
Element<T> *prev;
Element<T> *next;
T data;
int elem_ID;
char t_flag;
};
#endif
List_iter:
#ifndef GUARD_List_iter_h
#define GUARD_List_iter_h
template <class T>
class List;
template <class T>
class List_iter {
public:
List_iter(Element<T>* e = nullptr) : elem(e) {}
virtual ~List_iter() {
delete elem;
}
friend List<T>;
T operator*(void){
if (elem->t_flag == 'e'){
elem = elem->prev;
}
else if (elem->t_flag == 'b'){
elem = elem->next;
}
return elem->data;
}
Element<T>* operator++(void) {
if (elem->next->t_flag == 'e'){
return nullptr;
}
elem = elem->next;
return elem;
}
Element<T>* operator--(void) {
if (elem->prev->t_flag == 'b'){
return nullptr;
}
elem = elem->prev;
return elem;
}
List_iter operator+(const int val) {
for (int i = 0; i < val; i++){
this->elem = this->elem->next;
}
return *this;
}
List_iter operator-(const int val) {
for (int i = 0; i < val; i++){
this->elem = this->elem->prev;
}
return *this;
}
bool operator!=(const List_iter& rhs) const {
return rhs.elem != elem;
}
bool operator>(const List_iter& rhs) const {
return (this->elem->elem_ID > rhs.elem->elem_ID);
}
bool operator<(const List_iter& rhs) const {
return (this->elem->elem_ID < rhs.elem->elem_ID);
}
bool operator>=(const List_iter& rhs) const {
return (this->elem->elem_ID >= rhs.elem->elem_ID);
}
bool operator<=(const List_iter& rhs) const {
return (this->elem->elem_ID <= rhs.elem->elem_ID);
}
private:
Element<T>* elem;
};
#endif
main:
#include <iostream>
#include "List.h"
int main() {
List<int> ls;
List<int>::iterator begin = ls.begin();
List<int>::iterator end = ls.end();
List<int>::iterator iter = begin;
std::cout << "Attempt to retrieve data from empty list: ls.at(3)" << std::endl;
std::cout << "--------------------------------------------------" << std::endl;
//std::cout << ls.at(3) << std::endl << std::endl;
std::cout << "Test: growing list does not invalidate iter" << std::endl;
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Empty list" << std::endl << std::endl;
std::cout << "begin addr: " << &begin << " " << std::endl;
std::cout << "end addr: " << &end << " " << std::endl;
std::cout << std::endl << "Add data to list: 33 " << std::endl << std::endl;
ls.push_back(33);
std::cout << "begin addr: " << &begin << " " << std::endl;
std::cout << "end addr: " << &end << " " << std::endl;
std::cout << std::endl << "Add data to list: 856 " << std::endl << std::endl;
ls.push_back(856);
std::cout << "begin addr: " << &begin << " " << std::endl;
std::cout << "end addr: " << &end << " " << std::endl;
std::cout << "clear() " << std::endl << std::endl;
ls.clear();
std::cout << std::endl << std::endl;
std::cout << "Add data to list: 0 1 2 3 4 5 6 7 8 9" << std::endl;
std::cout << "-------------------------------------------------" << std::endl;
for (int i = 0; i != 10; i++){
ls.push_back(i);
}
std::cout << std::endl << std::endl;
std::cout << "data# begin+4" << std::endl;
std::cout << "-------------" << std::endl;
std::cout << *(iter + 4) << std::endl;
std::cout << std::endl << std::endl;
std::cout << "data# begin->end" << std::endl;
std::cout << "----------------" << std::endl;
iter = begin;
while (iter++){
std::cout << *iter << " ";
}
std::cout << std::endl << std::endl << std::endl;
std::cout << "data# end->begin" << std::endl;
std::cout << "----------------" << std::endl;
iter = end;
while (iter--){
std::cout << *iter << " ";
}
std::cout << std::endl << std::endl << std::endl;
std::cout << "for/iter: begin->end" << std::endl;
std::cout << "----------------" << std::endl;
for (iter = begin; iter++;){
std::cout << *iter << " ";
}
std::cout << std::endl << std::endl << std::endl;
std::cout << "iter arith: +4 +1 -1" << std::endl;
std::cout << "--------------------" << std::endl;
iter = ls.begin();
iter = iter + 4;
std::cout << *iter << " ";
std::cout << *(iter + 1) << " ";
std::cout << *(iter - 1) << " ";
std::cout << std::endl << std::endl << std::endl;
std::cout << "data#: (0)(1)(2)(3)(4)(5)(6)(7)(8)(9)" << std::endl;
std::cout << "-------------------------------------" << std::endl;
for (int i = 0; i != 10; i++){
std::cout << ls.at(i) << " ";
}
//ls.clear();
List<std::string> ls_str;
ls_str.push_back("Hello");
ls_str.push_back("World");
return 0; // breakpoint
}
new Element called, therefore owned by List, so only List can delete Element. List_iter doesn't require a destructor because it only contains a pointer.
I am using a linked list to store information on binary bits. Degree tells which power to raise an integer, 2, to.
The problem occurs in my set_bit method. It is supposed to delete the node pointer "currentSet" once the "target" node pointer is found. However instead of setting "currentSet" to null/releasing the memory, currentSet is being given a different, lower memory address. Why is this? What am I doing wrong? The program works when I explicitly sell currentSet to nullptr but shouldn't delete currentSet do this as well?
Here is the implementation of header
//file is "binary.cpp"
#include <iostream>
#include "binary.h"
//using std::cout;
Binary::Binary(int x) {
firstTerm = nullptr;
while (x > 0) {
unsigned int degree = (unsigned int) (log(float(x)) / log(float(2)));
set_bit(1, degree);
x -= (int) pow(float(2), float(degree));
}
}
Binary::~Binary() {
BinaryNode *temp;
while (firstTerm != nullptr) {
temp = firstTerm->next;
delete firstTerm;
firstTerm = temp;
}
}
void Binary::set_bit(int bit, int degree) {
BinaryNode *currentSet = firstTerm;
BinaryNode *target;
std::cout << "get_bit returns " << get_bit(degree) << std::endl;
if (bit == 0 && get_bit(degree)) {
std::cout << "bit = 0 " << std::endl;
std::cout << "currentSet->degree " << currentSet->degree << std::endl;
if (currentSet->degree == degree) {
std::cout << "in if" << std::endl;
firstTerm = currentSet->next;
delete currentSet;
std::cout << "end if" << std::endl;
}
else {
target = currentSet;
std::cout << "in else" << std::endl;
while (currentSet != nullptr) {
if (currentSet->degree == degree) {
std::cout << "in nested if" << std::endl;
//std::cout << "currentSet->degree = " << currentSet->degree << std::endl;
target->next = currentSet->next;
std::cout << "currentSet before delete " << currentSet << std::endl;
delete currentSet;
std::cout << "currentSet " << currentSet << "\nend nested if" << std::endl;
}
else {
std::cout << "in nested else" << std::endl;
std::cout << "firstTerm->next = " << firstTerm->next << std::endl;
std::cout << "currentSet->next = " << currentSet->next << std::endl;
target = currentSet;
currentSet = currentSet->next;
std::cout << "currentSet->next = " << currentSet->next << std::endl;
std::cout << "end nested else\n";
}
}
}
}
else if (bit == 1 && get_bit(degree) == 0) {
std::cout << "bit = 1" << std::endl;
firstTerm = new BinaryNode(degree, firstTerm);
/*if (firstTerm->next nullptr) {
currentSet = firstTerm;
}*/
std::cout << "firstTerm = " << firstTerm << std::endl;
std::cout << "firstTerm->degree = " << firstTerm->degree << std::endl;
std::cout << "firstTerm->next = " << firstTerm->next << std::endl;
}
}
int Binary::get_bit(int degree) const {
BinaryNode *currentGet = firstTerm;
while (currentGet != nullptr) {
//std::cout << "currentGet != nullptr";
if (currentGet->degree == degree) {
return 1;
}
currentGet = currentGet->next;
}
return 0;
}
Here is the header
//file is "binary.h"
#ifndef _BINARY_H_
#define _BINARY_H_
#include <iostream>
class Binary {
private:
struct BinaryNode {
int degree;
BinaryNode* next;
BinaryNode(int d, BinaryNode* n): degree(d),next(n) {}
};
BinaryNode *firstTerm;
public:
// default constructor
Binary() {
firstTerm = nullptr;
}
void set_bit(int b, int d);
int get_bit(int d) const;
#endif
Here is the tester file
//file is "binary_main.cpp
#include <iostream>
#include "binary.h"
using namespace std;
int main (void)
{
cout << "\nTESTING GET AND SET METHODS" << endl;
b1.set_bit(1, 2);
b1.set_bit(1, 5);
b1.set_bit(1, 0);
b1.set_bit(0, 2);
}
edited
Explicitly set currentSet to nullptr,
answer was found using information from n.m.
Ok, after failing to read a polynomial, I'm trying first a basic approach to this.
So i have class polinom with function read and print:
#ifndef _polinom_h
#define _polinom_h
#include <iostream>
#include <list>
#include <cstdlib>
#include <conio.h>
using namespace std;
class polinom
{
class term
{
public:
double coef;
int pow;
term(){
coef = 0;
pow = 0;
}
};
list<term> poly;
list<term>::iterator i;
public:
void read(int id)
{
term t;
double coef = 1;
int pow = 0;
int nr_term = 1;
cout << "P" << id << ":\n";
while (coef != 0) {
cout << "Term" << nr_term << ": ";
cout << "coef = ";
cin >> coef;
if (coef == 0) break;
cout << " grade = ";
cin >> pow;
t.coef = coef;
t.pow = pow;
if (t.coef != 0) poly.push_back(t);
nr_term++;
}
}
void print(char var)
{
for (i=poly.begin() ; i != poly.end(); i++ ) { //going through the entire list to retrieve the terms and print them
if (poly.size() < 2) {
if (i->pow == 0) //if the last term's power is 0 we print only it's coefficient
cout << i->coef;
else if (i->pow == 1) {
if (i->coef == 1)
cout << var;
else if (i->coef == -1)
cout << "-" << var;
else
cout << i->coef << var;
}
else
cout << i->coef << var << "^" << i->pow; //otherwise we print both
}
else {
if (i == poly.end()) { // if we reached the last term
if (i->pow == 0) //if the last term's power is 0 we print only it's coefficient
cout << i->coef;
else if (i->pow == 1)
cout << i->coef << var;
else
cout << i->coef << var << "^" << i->pow; //otherwise we print both
}
else {
if (i->coef > 0) {
if (i->pow == 1)//if the coef value is positive
cout << i->coef << var << " + "; //we also add the '+' sign
else
cout << cout << i->coef << var << "^" << i->pow << " + ";
}
else {
if (i->pow == 1)//if the coef value is positive
cout << i->coef << var << " + "; //we also add the '+' sign
else
cout << cout << i->coef << var << "^" << i->pow << " + ";
}
}
}
}
}
};
#endif
Well, it works when reading only one term but when reading more the printed coefficients are some random values and also after the last term it print '+' or '-' when it shouldn't.
So any idea what's wrong?
Thanks!
FINAL UPDATE
Ok, i made it work perfectly by modifying Bill's code so thanks a lot Bill and everyone else who commented or answered!
Here's the final print function:
void print(char var)
{
list<term>::iterator endCheckIter;
for (i=poly.begin() ; i != poly.end(); i++ )
{
//going through the entire list to retrieve the terms and print them
endCheckIter = i;
++endCheckIter;
if (i->pow == 0)
cout << i->coef;
else if (i->pow == 1)
cout << i->coef << var;
else
cout << i->coef << var << "^" << i->pow;
if (endCheckIter != poly.end()) {
if (endCheckIter->coef > 0)
cout << " + ";
else {
cout << " - ";
endCheckIter->coef *= -1;
}
}
}
}
if (i == poly.end()) { // if we reached the last term
This comment shows your error. For any given collection of items, items.end() returns the entry after the last item.
For instance, say I have a 5-item std::vector:
[0] [1] [2] [3] [4]
Then begin() points to:
[0] [1] [2] [3] [4]
/\
And end() points to:
[0] [1] [2] [3] [4] []
/\
Your for loop, it looks like:
for (i=poly.begin() ; i != poly.end(); i++ )
Note that comparing i to poly.end() happens before iter is used. As soon as i == poly.end(), you're done.
Your code inside of if (i == poly.end()) { will never be executed because this can never be true.
You can test for the end using the following:
// get access to the advance function
#include <iterator>
....
std::list<term>::iterator endCheckIter = i;
std::advance(endCheckIter, 1);
if (endCheckIter == poly.end())
{
...
}
But a simpler way might be:
std::list<term>::iterator endCheckIter = i;
++endCheckIter;
if (endCheckIter == poly.end())
{
...
}
Edit:
I'm not sure why you're getting garbage. Add in your missing braces and handle the non-end case, and everything works here:
void print(char var)
{
list<term>::iterator endCheckIter;
for (i=poly.begin() ; i != poly.end(); i++ )
{ // <- MISSING BRACE
//going through the entire list to retrieve the terms and print them
endCheckIter = i;
++endCheckIter;
cout << i->coef << var << "^" << i->pow; // <- MISSING OUTPUT
if (endCheckIter != poly.end()) {
if (i->coef > 0)
cout << " + ";
else
cout << " - ";
}
} // <- MISSING BRACE
}
Okay, now that Vlad has decided how he's going to do it, here's how I'd do it:
#ifndef _polinom_h
#define _polinom_h
#include <iostream>
#include <list>
#include <cstdlib>
#include <cmath>
#include "infix_iterator.h"
using namespace std;
char var;
class polinom {
class term {
double coef;
int power;
ostream &write(ostream &os) const {
// At least to me, the logic is easier to follow if we
// handle one piece at a time.
// It may be longer, but I think it's easier to understand.
// First, if the coefficient is negative, subtract the term instead of adding it.
if (coef < 0)
// backspace over the "+ " and print '- ' in its place.
os << "\b\b- ";
// Then print the absolute value of the coefficient (if needed).
if (fabs(coef) != 1)
os << fabs(coef);
// Then print the var (if needed)
if (power != 0)
os << var;
// then print the power (if needed)
if (abs(power) > 1)
os << "^" << power;
// And we're done.
return os;
}
// support inserting a term into a stream.
friend std::ostream &operator<<(std::ostream &os, term const &t) {
return t.write(os);
}
public:
term(double c=0.0, int p=0) : coef(c), power(p) {}
bool read(std::ostream &os, std::istream &is, int num) {
// This is only slightly modified from the originally posted question
os << "\nTerm " << num << ": coef = ";
is >> coef;
if (coef == 0.0)
return false;
if (coef != 0.0) {
os << " grade = ";
is >> power;
}
return true;
}
bool operator<(term const &other) const {
// order by descending powers.
return other.power < power;
}
};
list<term> poly;
public:
void read(int id) {
term t;
int nr_term = 1;
std::cout << "P: " << id;
// Read and save individual terms:
while (t.read(std::cout, std::cin, nr_term++))
poly.push_back(t);
}
void write(char var) {
// sort the polynomial so the highest powers come first.
poly.sort();
// save the variable name for later use.
::var = var;
// Print out all the terms:
std::copy(poly.begin(), poly.end(), infix_ostream_iterator<term>(std::cout, " + "));
}
};
#endif
Using this is pretty trivial:
#include "polynom.h"
int main() {
polinom p;
p.read(1);
p.write('x');
return 0;
}
void print(char var)
{
for (list<term>::const_iterator i = poly.begin(), e = poly.end(); i != e; ++i) {
if (i != poly.begin() || i->coef < 0) {
cout << (i->coef > 0 ? '+' : '-');
}
if (abs(i->coef) != 1) {
cout << abs(i->coef);
}
if (i->pow == 0) {
if (abs(i->coef) == 1) {
cout << 1;
}
} else {
cout << var;
if (i->pow != 1) {
cout << '^' << i->pow;
}
}
}
}