I would like some guidance on a program I am working on currently, I have successfully created a pair of integers and handled exception if the user were to enter the same values twice. I am stuck on doing the same process of creating pairs but instead of ints it has to be strings.
One suggestion that I have is changing the random generation of ordered pairs with:
string empty = "";
myList2[i].setFirst(empty + char('a' + rand() % 26));
myList2[i].setSecond(empty + char('A' + rand() % 26));
Any suggestions in the right direction would be appreciated.
Client File:
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <exception>
#include "orderedpair.h"
using namespace std;
using namespace cs_pairs;
int main() {
int num1, num2;
OrderedPair<int> myList[10];
srand(static_cast<unsigned>(time(0)));
cout << "default value: ";
myList[0].print();
cout << endl;
for (int i = 0; i < 10; i++) {
myList[i].setFirst(rand() % 50);
myList[i].setSecond(rand() % 50 + 50);
}
myList[2] = myList[0] + myList[1];
if (myList[0] < myList[1]) {
myList[0].print();
cout << " is less than ";
myList[1].print();
cout << endl;
}
for (int i = 0; i < 10; i++) {
myList[i].print();
cout << endl;
}
cout << "Enter two numbers to use in an OrderedPair. Make sure they are different numbers: ";
cin >> num1 >> num2;
OrderedPair<int> x;
/* use this before you've implemented the exception handling in the class:
x.setFirst(num1);
x.setSecond(num2);
*/
/* use this after you've implemented the exception handling in the class: */
try {
x.setFirst(num1);
x.setSecond(num2);
/*if (x.setFirst(num1) == x.setSecond(num2))
{
throw OrderedPair<int>::DuplicateMemberError;
} */
}
catch (OrderedPair<int>::DuplicateMemberError e) {
cout << "YOU ENTERED TWO OF THE SAME VALUES!" << endl;
x.setFirst(OrderedPair<int>::DEFAULT_VALUE);
x.setSecond(OrderedPair<int>::DEFAULT_VALUE);
}
cout << "The resulting OrderedPair: ";
x.print();
cout << endl;
}
Header File:
#ifndef ORDEREDPAIR_H
#define ORDEREDPAIR_H
#include <iostream>
namespace cs_pairs
{
template <class T>
class OrderedPair
{
public:
typedef std::size_t size_type;
typedef T value_type; // changed int to T
static const int DEFAULT_VALUE = 0;
class DuplicateMemberError
{
};
OrderedPair(T newFirst = DEFAULT_VALUE, T newSecond = DEFAULT_VALUE);
void setFirst(T newFirst);
void setSecond(T newSecond);
T getFirst() const;
T getSecond() const;
OrderedPair<T> operator+(const OrderedPair<T>& right) const;
bool operator<(const OrderedPair<T>& right) const;
void print() const;
private:
T first;
T second;
};
}
#include "orderedpair.cpp"
#endif // !ORDEREDPAIR_H
Implementation File:
#include <iostream>
#include <exception>
using namespace std;
namespace cs_pairs
{
template <class T>
OrderedPair<T>::OrderedPair(T newFirst, T newSecond) {
setFirst(newFirst);
setSecond(newSecond);
}
template <class T>
void OrderedPair<T>::setFirst(T newFirst) {
if ((newFirst == second) && (newFirst != 0))
{
throw DuplicateMemberError();
}
first = newFirst;
}
template <class T>
void OrderedPair<T>::setSecond(T newSecond) {
if ((newSecond == first) && (newSecond != 0))
{
throw DuplicateMemberError();
}
second = newSecond;
}
template <class T>
T OrderedPair<T>::getFirst() const {
return first;
}
template <class T>
T OrderedPair<T>::getSecond() const {
return second;
}
template <class T>
OrderedPair<T> OrderedPair<T>::operator+(const OrderedPair<T>& right) const {
return OrderedPair(first + right.first, second + right.second);
}
template <class T>
bool OrderedPair<T>::operator<(const OrderedPair<T>& right) const {
return first + second < right.first + right.second;
}
template <class T>
void OrderedPair<T>::print() const {
std::cout << "(" << first << ", " << second << ")";
}
}
To be generic, get rid of static const int DEFAULT_VALUE = 0;
Get rid of default constructor which doesn't respect your invariant
I would get rid of individual setter which might be problematic when uses together:
void swap_order(OrderedPair<int>& op)
{
const auto first = op.getFirst();
op.setFirst(op.getSecond()); // Oups... throw exception
op.setSecond(first);
}
So:
template <class T>
class OrderedPair
{
public:
using size_type = std::size_t;
using value_type = T;
class DuplicateMemberError{};
OrderedPair(const T& newFirst, const T& newSecond) : first(newFirst), second(newSecond) { check(); }
const T& getFirst() const { return first; }
const T& getSecond() const { return second; }
OrderedPair<T> operator+(const OrderedPair<T>& right) const;
bool operator<(const OrderedPair<T>& rhs) const;
void print() const;
private:
void check() { if (first == second) throw DuplicateMemberError{}; }
private:
T first;
T second;
};
As no longer default constructible, you have to change
OrderedPair<int> myList[10]; by
std::vector<OrderedPair<int>> myList; /*myList.reserve(10);*/
and generation would be:
//const std::string empty;
const char lower_alphabet = "abcdefghijklmnopqrstuvwxyz"; // 'a'-'z' is not guaranty to be contiguous (EBCDIC)
const char upper_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 'A'-'Z' is not guaranty to be contiguous (EBCDIC)
for (int i = 0; i < 10; i++) {
myList.emplace_back(rand() % 50, rand() % 50 + 50);
// myList.emplace_back(empty + char(lower_alphabet[rand() % 26], empty + char(upper_alphabet[rand() % 26]);
}
Related
I'm currently making a simulation of an autonomous car for my AI class. The car's constructor receives the board as a parameter so it can set the position of the car and add the first node to the search tree, so it can search an optimum path from the Starting Position to the Finishing Position. The thing is, the board generates without any problem, but when I try to pass it to the car's constructor, it results in a Segmentation fault (core dumped) error.
I used a debugger (gdb), ran the code in it and made a back-trace; and the problem came from here:
void node_c::add_child(node_c* chld)
{ int i;
for (i = 0; i < MAX_CHILDREN; i++)
{ if (children_[i] == NULL) //This line's the problem
break;
}
if (children_[i] != NULL)
{ cout << endl << "You can't add any more children." << endl;
return;
}
else children_[i] = chld;
}
Note: 'children_' contains a maximum of 4 children of a search_tree's node, and is a custom vector_c class I had to make.
This is the operator that fails and the function it calls:
template <typename TDato>
TDato& vector_c<TDato>::operator [](int position) { return get_data(position); }
template <typename TDato>
TDato& vector_c<TDato>::get_data(int a) const { return data_[a]; }
I thought that it might be a type error in the comparison if (children_[i] == NULL) so I made a custom operator that returned an object (TDato), not a reference to an object (TDato&), but it didn't work.
I can't imagine what could be causing this and/or how to solve it.
Thanks in advance.
Edit 1: Here's a google drive link to the project as even a minimal reproducible example would be too large to be easy to read in a Stack Overflow question. It's not very big, I promise (less than 1 MB).
Edit 2: Here's the most I could do to make the reproducible example minimal, as the question got closed for not including it.
main.cpp
#include "../include/board_s.hpp"
#include "../include/car_c.hpp"
using namespace std;
int main(void)
{ board_s<int> board(20, 20);
board.file_depiction();
car_c car(board);
board.write(cout);
return 0;
}
Here, the problem comes when the constructor of car_c is called. It should create an car_c object.
board_c.hpp
#ifndef __BOARD_S__
#define __BOARD_S__
#include <cstdio>
#include <iostream>
#include <cstring>
#include <random>
#include <fstream>
#include <utility>
#include "matrix_c.hpp"
#include "tree_c.hpp"
using namespace std;
template <typename TDato = int>
class board_s: public matrix_c<TDato>
{ private:
pair<int, int> starting_pos;
pair<int, int> finishing_pos;
public:
board_s(int, int);
~board_s(void);
pair<int, int> get_start(void);
void file_depiction(void); //Generates obstacles and starting/finishing points as depicted in board_depiction.txt.
virtual ostream& write(ostream&);
int distance(pair<int, int>&) const; //Returns the distance from a given position to the finishing point
private:
bool object_setter(string, int&, int&);
int object_identifier(string&) const; //Given the name of the object ("NEW OBSTACLE" [1], "STARTING POSITION" [2] or "FINISHING POSITION" [3]) returns it's code
};
template class board_s<int>;
#endif
board_c.cpp
#include "../include/board_s.hpp"
#include "matrix_c.cpp"
using namespace std;
//The constructor fills the board with empty boxes.
template <typename TDato>
board_s<TDato>::board_s(int m, int n):
matrix_c<TDato>::matrix_c(m + 2, n + 2)
{ for(int i = 1; i < m; i++)
for(int j = 1; j < n; j++)
matrix_c<TDato>::at(i, j) = 0;
for(int i = 0; i < n + 2; i++)
{ matrix_c<TDato>::at(0, i) = 1;
matrix_c<TDato>::at(m + 1, i) = 1;
}
for(int i = 0; i < m + 2; i++)
{ matrix_c<TDato>::at(i, 0) = 1;
matrix_c<TDato>::at(i, n + 1) = 1;
}
starting_pos.first = 0;
starting_pos.second = 0;
finishing_pos.first = 0;
finishing_pos.second = 0;
}
template <typename TDato>
board_s<TDato>::~board_s(void){}
template <typename TDato>
pair<int, int> board_s<TDato>::get_start(void) { return starting_pos; }
template <typename TDato>
void board_s<TDato>::file_depiction(void)
{ string line;
int x, y, i;
std::ifstream bd;
bd.open("board_depiction.txt");
if (bd.is_open())
{ getline(bd, line);
getline(bd, line);
i = line.size() - 1;
y = matrix_c<TDato>::strtoi(line, i);
i--;
x = matrix_c<TDato>::strtoi(line, i);
matrix_c<TDato>::resize(x + 2, y + 2);
getline(bd, line);
getline(bd, line);
i = line.size() - 1;
y = matrix_c<TDato>::strtoi(line, i);
i--;
x = matrix_c<TDato>::strtoi(line, i);
object_setter("STARTING POSITION", x, y);
getline(bd, line);
getline(bd, line);
i = line.size() - 1;
y = matrix_c<TDato>::strtoi(line, i);
i--;
x = matrix_c<TDato>::strtoi(line, i);
object_setter("FINISHING POSITION", x, y);
while (getline(bd, line))
if (line[0] != 'O')
{ i = line.size() - 1;
y = matrix_c<TDato>::strtoi(line, i);
i--;
x = matrix_c<TDato>::strtoi(line, i);
object_setter("NEW OBSTACLE", x, y);
}
}
else cout << "ERROR";
}
template <typename TDato>
ostream& board_s<TDato>::write(ostream& os)
{ int temp = matrix_c<TDato>::get_n() - 2 + (4 * (matrix_c<TDato>::get_n() - 2));
os << " ";
for (int i = 1; i < temp; i++)
os << "_";
os << " " << endl << "|";
for (int i = 1; i < matrix_c<TDato>::get_m() - 1; i++)
{ for (int j = 0; j < 2; j++)
{ for (int k = 1; k < matrix_c<TDato>::get_n() - 1; k++)
switch (matrix_c<TDato>::at(i, k))
{ case 1:
os << "████|";
break;
case 2:
if (j == 0)
os << " CC |";
else os << "_CC_|";
break;
case 3:
if (j == 0)
os << " FF |";
else os << "_FF_|";
break;
default:
if (j == 0)
os << " |";
else os << "____|";
}
os << endl;
if (j == 0) os << "|";
}
if (i < matrix_c<TDato>::get_m() - 2) os << "|";
}
os << endl;
return os;
}
template <typename TDato>
int board_s<TDato>::distance(pair<int, int>& pos) const
{ int d = (finishing_pos.first - pos.first) + (finishing_pos.second - pos.second);
if (d < 0) return (d * (-1));
else return d;
}
template <typename TDato>
bool board_s<TDato>::object_setter(string name, int &x, int &y)
{ if((x > 0) && (x < matrix_c<TDato>::get_m() - 1) && (y > 0) && (y < matrix_c<TDato>::get_n() - 1) && (matrix_c<TDato>::at(x, y) == 0))
{ matrix_c<TDato>::at(x, y) = object_identifier(name);
cout << endl << endl << "The " << name << " has been set in (" << x << ", " << y << ")" << endl;
if (name == "STARTING POSITION")
{ starting_pos.first = x;
starting_pos.second = y;
}
else if (name == "FINISHING POSITION")
{ finishing_pos.first = x;
finishing_pos.second = y;
}
return true;
}
else
{ cout << endl << "The coordinates that you intriduced were out of reach or the position wasn't free." << endl;
return false;
}
}
template <typename TDato>
int board_s<TDato>::object_identifier(string &name) const
{ if (name == "NEW OBSTACLE")
return 1;
else if (name == "STARTING POSITION")
return 2;
else if (name == "FINISHING POSITION")
return 3;
else return 0;
}
matrix_c.hpp
#ifndef __MATRIX_C__
#define __MATRIX_C__
#include <cstdio>
#include <iostream>
#include <iomanip>
#include <cstring>
#include "vector_c.hpp"
using namespace std;
template <typename TDato>
class matrix_c //Template matrix class implemented with a vector.
{ private:
int m_;
int n_;
vector_c<TDato> v_;
public:
matrix_c(void); //Empty constructor
matrix_c(int, int); //Constructor with dimensions
~matrix_c(void);
void resize(int, int);
TDato& at (int, int); //Redirects to position (x, y)
virtual TDato& operator()(int, int); //Operator for at(int, int)
int get_m(void) const;
int get_n(void) const;
private:
int pos(int, int);
protected:
int ctoi(char&) const;
int strtoi(string&, int&) const;
};
#endif
matrix_c.cpp
#include "../include/matrix_c.hpp"
using namespace std;
template <typename TDato>
matrix_c<TDato>::matrix_c(void):
m_(0),
n_(0),
v_() {}
template <typename TDato>
matrix_c<TDato>::matrix_c(int m, int n):
m_(m),
n_(n),
v_(m * n) {}
template <typename TDato>
matrix_c<TDato>::~matrix_c(void) {}
template <typename TDato>
void matrix_c<TDato>::resize(int m, int n)
{ v_.resize(m * n);
m_ = m;
n_ = n;
}
template <typename TDato>
TDato& matrix_c<TDato>::at(int i, int j) { return v_[(pos(i,j))]; }
template <typename TDato>
TDato& matrix_c<TDato>::operator()(int i, int j) { return at(i,j); }
template <typename TDato>
int matrix_c<TDato>::get_m(void) const { return m_; }
template <typename TDato>
int matrix_c<TDato>::get_n(void) const { return n_; }
template <typename TDato>
int matrix_c<TDato>::pos(int i, int j) { return ((n_ * i) + j); }
template <typename TDato>
int matrix_c<TDato>::ctoi(char &c) const
{ int n = c;
return n - 48;
}
template <typename TDato>
int matrix_c<TDato>::strtoi(string &s, int& i) const
{ int n = 0;
int mult = 1;
while ((s[i] != ' ') && (i >= 0))
{ n += ctoi(s[i]) * mult;
mult *= 10;
i--;
}
return n;
}
template class matrix_c<int>;
vector_c.hpp
#ifndef __VECTOR_C__
#define __VECTOR_C__
#include <iostream>
#include <cstdio>
#include <cassert>
using namespace std;
template <typename TDato>
class vector_c
{ private:
int sz_;
TDato* data_;
public:
vector_c(void); //Empty constructor
vector_c(int); //Constructor with size
~vector_c(void);
TDato& get_data(int) const;
void set_data(TDato&, int);
ostream& write(ostream&) const;
TDato& operator [](int);
void resize(int);
private:
void new_vector(void);
void del_vector(void);
};
#endif
vector_c.cpp
#include "../include/vector_c.hpp"
#include "../include/node_c.hpp"
using namespace std;
template <typename TDato>
vector_c<TDato>::vector_c(void):
sz_(0),
data_(NULL) {}
template <typename TDato>
vector_c<TDato>::vector_c(int size):
sz_(size),
data_(new TDato[sz_]) {}
template <typename TDato>
vector_c<TDato>::~vector_c(void)
{ delete[] data_;
data_ = NULL;
}
template <typename TDato>
TDato& vector_c<TDato>::get_data(int a) const { return data_[a]; }
template <typename TDato>
void vector_c<TDato>::set_data(TDato& dat, int a) { data_[a] = dat;}
template <typename TDato>
TDato& vector_c<TDato>::operator [](int position) { return get_data(position); }
template <typename TDato>
void vector_c<TDato>::resize(int sz)
{ del_vector();
sz_ = sz;
new_vector();
}
template <typename TDato>
void vector_c<TDato>::new_vector(void){
data_ = new TDato[sz_];
}
template <typename TDato>
void vector_c<TDato>::del_vector(void)
{ if (data_ != NULL){
delete [] data_;
data_ = NULL;
}
}
template class vector_c<int>;
template class vector_c<node_c*>;
node_c.hpp
#define MAX_CHILDREN 4
#ifndef __NODE_C__
#define __NODE_C__
#include <iostream>
#include <cstdio>
#include <cassert>
#include "vector_c.hpp"
using namespace std;
class node_c
{ private:
node_c* parent_;
vector_c< node_c* > children_;
pair<pair<int, int>, int> data_;
public:
node_c(void);
node_c(int &x, int &y, int &cost);
node_c(pair<pair<int, int>, int>&);
~node_c(void);
void add_child(node_c*);
};
#endif
node_c.cpp
#include "../include/node_c.hpp"
using namespace std;
node_c::node_c(void):
parent_(NULL)
{ for (int i = 0; i < MAX_CHILDREN; i++)
children_[i] = NULL;
data_.first.first = 0;
data_.first.second = 0;
data_.second = 0;
}
node_c::node_c(int &x, int &y, int &cost):
parent_(NULL)
{ for (int i = 0; i < MAX_CHILDREN; i++)
children_[i] = NULL;
data_.first.first = x;
data_.first.second = y;
data_.second = cost;
}
node_c::node_c(pair<pair<int, int>, int> &dat):
parent_(NULL),
data_(dat)
{ for (int i = 0; i < MAX_CHILDREN; i++)
children_[i] = NULL;
}
node_c::~node_c(void)
{ parent_ = NULL;
for (int i = 0; i < MAX_CHILDREN; i++)
children_[i] = NULL;
data_.first.first = 0;
data_.first.second = 0;
data_.second = 0;
}
void node_c::add_child(node_c* chld)
{ int i;
for (i = 0; i < MAX_CHILDREN; i++)
{ if (children_[i] == NULL)
break;
}
if (children_[i] != NULL)
{ cout << endl << "You can't add any more children." << endl;
return;
}
else children_[i] = chld;
}
tree_c.hpp
#ifndef __TREE_C__
#define __TREE_C__
#include "node_c.hpp"
using namespace std;
class tree_c
{ private:
node_c* root_;
int depth_;
public:
tree_c(void);
tree_c(node_c*);
node_c* add_node(node_c*, int&, int&, int);
};
#endif
tree_c.cpp
#include "../include/tree_c.hpp"
using namespace std;
tree_c::tree_c(void):
root_(NULL),
depth_(0) {}
tree_c::tree_c(node_c* root):
root_(root),
depth_(1) {}
node_c* tree_c::add_node(node_c* parent, int& x, int& y, int cost)
{ node_c* node = new node_c(x, y, cost);
parent->add_child(node);
}
car_c.hpp
#ifndef __CAR_C__
#define __CAR_C__
#include <iostream>
#include <cstdio>
#include <cassert>
#include "tree_c.hpp"
#include "board_s.hpp"
using namespace std;
class car_c
{ private:
tree_c tree_;
pair<int, int> pos_;
matrix_c<int> visited_;
public:
car_c(void);
car_c(board_s<int>&);
~car_c(void);
};
#endif
car_c.cpp
#include "../include/car_c.hpp"
using namespace std;
car_c::car_c(void):
tree_(NULL)
{ pos_.first = 0;
pos_.second = 0;
}
car_c::car_c(board_s<int>& board):
pos_(board.get_start()),
tree_(tree_.add_node(NULL, pos_.first, pos_.second, 0))
{ visited_(pos_.first, pos_.second) = 1; }
car_c::~car_c(void) {}
Debugging information:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401cc2 in node_c::node_c (this=0x6187d0, x=#0x7ffffffeddf0: 8, y=#0x7ffffffeddf4: 0,
cost=#0x7ffffffedd2c: 0) at src/node_c.cpp:20
20 children_[i] = NULL;
(gdb) bt
#0 0x0000000000401cc2 in node_c::node_c (this=0x6187d0, x=#0x7ffffffeddf0: 8, y=#0x7ffffffeddf4: 0,
cost=#0x7ffffffedd2c: 0) at src/node_c.cpp:20
#1 0x0000000000402007 in tree_c::add_node (this=0x7ffffffedde0, parent=0x0, x=#0x7ffffffeddf0: 8,
y=#0x7ffffffeddf4: 0, cost=0) at src/tree_c.cpp:16
#2 0x0000000000402df6 in car_c::car_c (this=0x7ffffffedde0, board=...) at src/car_c.cpp:15
#3 0x0000000000401403 in main () at src/main.cpp:11
Sorry for the length of my question, but this is the minimal reproducible example I was able to make. If you know another way to recreate my error, let me know so I can improve this.
In the code shown below, in the function void printExpensiveThanT(..) i'm supposed to print out the destination, distance and the price for the offers which are more expensive than the offer T in the function, sorted in ascending order by the distance value.
I'm not sure what should i use to sort them, i experimented something with vectors but it didn't work out so i deleted it.
Any help would be appreciated.
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
class Transport {
protected:
char destination[100];
int basePrice;
int distance;
public:
Transport() {}
Transport(char *destination, int basePrice, int distance) {
strcpy(this->destination, destination);
this->basePrice = basePrice;
this->distance = distance;
}
virtual ~Transport() {}
virtual int priceTransport() = 0;
friend bool operator<(const Transport &t1, const Transport &t2) {
return t1.distance<t2.distance;
}
int getDistance(){ return distance; }
char *getDestination() { return destination; }
int getPrice() { return basePrice; }
};
class AutomobileTransport : public Transport {
private:
bool ifDriver;
public:
AutomobileTransport() {}
AutomobileTransport(char *destination, int basePrice,int distance, bool ifDriver) : Transport(destination,basePrice,distance) {
this->ifDriver = ifDriver;
}
void setIfDriver(bool ifDriver) {
this->ifDriver = ifDriver;
}
bool getIfDriver() {
return ifDriver;
}
int priceTransport() {
if(ifDriver) {
basePrice+=basePrice*20/100;
}
return basePrice;
}
friend bool operator<(const AutomobileTransport &a1, const AutomobileTransport &a2) {
return a1.distance<a2.distance;
}
};
class VanTransport: public Transport {
private:
int passengers;
public:
VanTransport() {}
VanTransport(char *destination, int basePrice, int distance, int passengers) : Transport(destination, basePrice, distance) {
this->passengers = passengers;
}
void setPassengers(int passengers) {
this->passengers = passengers;
}
int getPassengers() {
return passengers;
}
int priceTransport() {
for(int i = 0; i < passengers; i++) {
basePrice-=200;
}
return basePrice;
}
friend bool operator<(const VanTransport &k1, const VanTransport &k2) {
return k1.distance<k2.distance;
}
};
void printExpensiveThanT(Transport **offers,int n,AutomobileTransport &T) {
Transport *tmp;
for(int i = 0; i <= n; i++){
if(offers[i]->priceTransport() > T.priceTransport())
cout<<offers[i]->getDestination()<<" "<<offers[i]->getDistance()<<" "<<offers[i]->getPrice()<<endl;
}
}
int main() {
char destination[20];
int type,price,distance,passengers;
bool driver;
int n;
cin>>n;
Transport **offers;
offers=new Transport *[n];
for (int i=0; i<n; i++) {
cin>>type>>destination>>price>>distance;
if (type==1) {
cin>>driver;
offers[i]=new AutomobileTransport(destination,price,distance,driver);
} else {
cin>>passengers;
offers[i]=new VanTransport(destination,price,distance,passengers);
}
}
AutomobileTransport at("Ohrid",2000,600,false);
printExpensiveThanT(offers,n,at);
for (int i=0; i<n; i++) delete offers[i];
delete [] offers;
return 0;
}
Since you're dealing with pointers, the easiest thing to do is to use std::vector and std::sort:
#include <vector>
//...
void printExpensiveThanT(Transport **offers, int n, AutomobileTransport &T)
{
std::vector<Transport*> sortedVect;
for (int i = 0; i < n; i++)
{
if (offers[i]->priceTransport() > T.priceTransport())
sortedVect.push_back(offers[i]); // add this item to the vector
}
// sort the vector based on the dereferenced pointers and their respective
// operator <
std::sort(sortedVect.begin(), sortedVect.end(),
[](Transport* left, Transport* right) { return *left < *right; });
// print out the values
for (auto it : sortedVect)
cout << (*it).getDestination() << " " << (*it).getDistance() << " " << (*it).getPrice() << "\n";
}
Also, your original code looped one more than it should (i <= n was wrong).
Edit:
If your compiler doesn't support the C++ 11 syntax, here is an alternate solution:
#include <vector>
//...
bool Sorter(Transport* left, Transport* right)
{ return *left < *right; }
void printExpensiveThanT(Transport **offers, int n, AutomobileTransport &T)
{
std::vector<Transport*> sortedVect;
for (int i = 0; i < n; i++)
{
if (offers[i]->priceTransport() > T.priceTransport())
sortedVect.push_back(offers[i]); // add this item to the vector
}
// sort the vector based on the dereferenced pointers and their respective
// operator <
std::sort(sortedVect.begin(), sortedVect.end(), Sorter);
// print out the values
std::vector<Transport*>::iterator it = sortedVect.begin();
while (it != sortedVect.end())
{
cout << (*it).getDestination() << " " << (*it).getDistance() << " " << (*it).getPrice() << "\n";
++it;
}
}
The program compiles just fine but when the output window comes up, it shows the elements i've outputed and then i hear a windows sound, and then it just stops.
I'm trying to enqueue elements into the circular queue, and it appears that they are being input just fine since the display function prints them out. Everything seems to make sense, but the program just sorta crashes, could anybody elaborate on why exactly it might be doing this? My code is below :
#include <iostream>
#include <algorithm>
using namespace std;
template<class QueueElement>
class dynamic_queue
{
public:
dynamic_queue(int = 10);
dynamic_queue(const dynamic_queue &);
~dynamic_queue();
QueueElement *getHead();
int getSize() const;
bool isEmpty()const;
int getCapacity();
void display(ostream &out) const;
void enqueue(const QueueElement &value);
void dequeue();
bool swap(dynamic_queue &, dynamic_queue &);
void clear();
const dynamic_queue & operator=(const dynamic_queue &);
friend ostream & operator<< <> (ostream &, const
dynamic_queue<dynamic_queue> &);
private:
int ihead;
int itail;
int initial_capacity;
int array_capacity;
int array_size;
QueueElement *myarray;
};
template<class QueueElement>
dynamic_queue<QueueElement>::dynamic_queue(int n)
:ihead(0),itail(0)
{
if (n <= 0)
{
initial_capacity = 1;
}
else
{
initial_capacity = max(n, 1);
}
array_capacity = initial_capacity;
myarray = new QueueElement(initial_capacity);
array_size = initial_capacity;
}
template<class QueueElement>
dynamic_queue<QueueElement>::~dynamic_queue()
{
delete[]myarray;
}
template<class QueueElement>
void dynamic_queue<QueueElement>::enqueue(const QueueElement &inserted_value
)
{
int newTail = (itail + 1) % array_capacity;
if (newTail != ihead)
{
myarray[itail] = inserted_value;
itail = newTail;
}
else
{
cout << "Queue is full" << endl;
exit(1);
}
cout << "itail: " << itail << endl;
cout << "array size" << array_size << endl;
}
template<class QueueElement>
ostream & operator<<(ostream & o, const dynamic_queue<QueueElement> &output_elements)
{
o << output_elements;
return o;
}
template<class QueueElement>
void dynamic_queue<QueueElement>::display(ostream &out) const
{
for (int i = ihead;i != itail;i = (i + 1) % array_capacity)
{
out << myarray[i] << " ";
cout << endl;
}
}
template<class QueueElement>
int dynamic_queue<QueueElement>::getSize() const
{
int count = 0;
for (int i = 0;i <= array_capacity;i++)
{
count++;
}
return count;
}
main function:
#include <iostream>
#include "DynamicCircularQueue.h"
using namespace std;
int main()
{
dynamic_queue<int> queue1(5);
queue1.enqueue(10);
queue1.enqueue(11);
queue1.getSize();
queue1.display(cout);
}
myarray = new QueueElement(initial_capacity);
should be:
myarray = new QueueElement[initial_capacity];
Since queue-element is int, you were allocating an array of just one element, that is why your code crashed at the second call to enqueue.
So I have such definition on map class on vector, it works good except for post-incrementation, which doesn't work as it should. You can see in example that variable a should be equal to 10 (post-incremented after assignment). But it's equal to 11. I have no idea how to fix that.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
template<class T>
class Map {
class Cref {
friend class Map;
Map& m;
string key;
T value;
public:
operator double() {
return m.read(key);
};
Map::Cref & operator=(double num) {
m.write(key, num);
return *this;
};
Map::Cref & operator++(int) {
Cref c(*this);
m.increment(key, value);
return c;
}
Cref(Map& m, string a)
: m(m),
key(a) {};
};
public:
class Unitialized {};
struct Record {
string key;
T value;
};
vector<Record> data;
Map() {}
~Map() {}
bool ifexist(string k) {
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == k)
return 1;
}
return 0;
}
Cref operator[](string key) {
return Map::Cref( * this, key);
}
private:
void increment(string key, T value) {
if (ifexist(key) == 0) {
throw Unitialized();
}
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == key)
data.at(i).value += 1;
}
}
void write(string key, T value) {
if (ifexist(key) == 1) {
cout << "Element already exist" << endl;
return;
}
Record r;
r.key = key;
r.value = value;
data.push_back(r);
}
double read(string key) {
if (ifexist(key) == 0) {
throw Unitialized();
}
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == key)
return data.at(i).value;
}
return 0;
}
};
int main(int argc, char** argv) {
Map<int> m;
m["ala"] = 10;
int a = 0;
a = m["ala"]++;
cout << a << endl;
try {
cout << m["ala"] << endl;
cout << m["ola"] << endl;
} catch (Map<int>::Unitialized&) {
cout << "Unitialized element" << endl;
}
return 0;
}
Yes, I already fixed that, overloading of ++ operator should look like that :
T operator ++(int)
{
T ret = m.read(this->key);
m.increment(key, value);
return ret;
}
This fixes everything.
I would like to add compare++ to this code in order to count how many compares are done by this algorithm. Does the count of compare need to be incremented on each execution of the first while loop in Merge(...) and in the if and else inside the while? Are these the only locations where compare should be incremented? (I added this increment where I thought it belonged and commented out. Please ignore the swap function)
#include "MergeSort.h"
template<class ItemType>
void MergeClass<ItemType>::sort(ItemType values[], int first, int last)
// Post: The elements in values are sorted by key.
{
if (first < last)
{
int middle = (first + last) / 2;
sort(values, first, middle);
sort(values, middle + 1, last);
Merge(values, first, middle, middle + 1, last);
}
}
template<class ItemType>
void MergeClass<ItemType>::Merge(ItemType values[], int leftFirst, int leftLast,
int rightFirst, int rightLast)
// Post: values[leftFirst]..values[leftLast] and
// values[rightFirst]..values[rightLast] have been merged.
// values[leftFirst]..values[rightLast] are now sorted.
{
ItemType tempArray[5];
int index = leftFirst;
int saveFirst = leftFirst;
while ((leftFirst <= leftLast) && (rightFirst <= rightLast))
{
if (values[leftFirst] < values[rightFirst])
{
tempArray[index] = values[leftFirst];
leftFirst++;
//compare++;
}
else
{
tempArray[index] = values[rightFirst];
rightFirst++;
//compare++;
}
index++;
//compare++;
}
while (leftFirst <= leftLast)
// Copy remaining items from left half.
{
tempArray[index] = values[leftFirst];
leftFirst++;
index++;
}
while (rightFirst <= rightLast)
// Copy remaining items from right half.
{
tempArray[index] = values[rightFirst];
rightFirst++;
index++;
}
for (index = saveFirst; index <= rightLast; index++)
values[index] = tempArray[index];
}
template<class ItemType>
inline void MergeClass<ItemType>::Swap(ItemType& item1, ItemType& item2)
// Post: Contents of item1 and item2 have been swapped.
{
ItemType tempItem;
tempItem = item1;
item1 = item2;
item2 = tempItem;
}
template<class ItemType>
MergeClass<ItemType>::MergeClass()
{
compare = 0;
swap = 0;
}
template<class ItemType>
void MergeClass<ItemType>::sortPreformance()
{
cout << "Comparisons made: " << compare <<endl;
cout << "Swaps made: "<< swap <<endl;
}
If it's meant strictly for profiling, I'd put the counting logic outside of the sorting class. That is something like the following (which just counts the number of comparisons and swaps used by std::sort):
#include <iostream>
#include <algorithm>
#include <cstdlib>
using namespace std;
template<typename T>
struct CountingItem {
CountingItem(const T& val = T()) : val_(val) {}
bool operator<(const CountingItem<T>& rhs) const {
++compares;
return val_ < rhs.val_;
}
static size_t compares;
static size_t swaps;
T val_;
};
template<typename T>
size_t CountingItem<T>::compares = 0;
template<typename T>
size_t CountingItem<T>::swaps = 0;
template<typename T>
void swap(CountingItem<T>& a, CountingItem<T>& b) {
++CountingItem<T>::swaps;
std::swap(a, b);
}
int main()
{
const size_t num_items = 10000;
CountingItem<int> items[num_items];
for(int i = 0; i < num_items; i++) items[i] = rand() % 100;
sort(items, items+num_items);
cout << "Compares = " << CountingItem<int>::compares << endl;
cout << "Swaps = " << CountingItem<int>::swaps << endl;
// Reset CountingItem<int>::compares and swaps here if you're running another test
}