Merge remote-tracking branch 'EOOPVarious/branch' into main

This commit is contained in:
PolishPigeon 2022-06-18 00:44:20 +02:00
commit e1e4737c7f
8 changed files with 1508 additions and 0 deletions

21
EOOP/Various/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Krzysztof Rudnicki
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,94 @@
/**
Unit tests for 2nd EOOP assignment.
Currency - aggregate 2 doubles (monetary value, exchange rate to dollars)
CurrencyView - view the given currency with different exchange rate
(e.g. view PLN value in GBP), store the reference to the Currency.
Note that this is in a big part "code reading" exercise.
Based on this file you should implement two classes mentioned above,
with proper interface, and in the right header file.
Make sure that you use proper method composition in your code.
Please make sure that you compile your solution with warnings enabled and that there are no warnings during compilation. You can do this via the following command:
g++ -Wall -Wextra -Werror -pedantic lab_2.cpp currency.hpp
*/
#include "currency2.hpp"
#include <iostream>
int main() {
double monetary_value = 8;
double usd_exchange_rate = 0.23;
Currency pln(monetary_value, usd_exchange_rate);
if (pln.getValue() != 8) {
std::cerr << "Error in getValue()" << std::endl;
}
if (pln.getUSDExchangeRate() != 0.23) {
std::cerr << pln.getUSDExchangeRate() << std::endl;
std::cerr << "Error in getUSDExchangeRate()" << std::endl;
}
pln.setValue(42);
pln.setUSDExchangeRate(0.24);
if (pln.getValue() != 42) {
std::cerr << "Error in setValue()" << std::endl;
}
if (pln.getUSDExchangeRate() != 0.24) {
std::cerr << "Error in setUSDExchangeRate()" << std::endl;
}
Currency gbp(1336, 1.2);
Currency usd(78, 1);
if (gbp.toDollars() != 1603.2) {
std::cerr << "Error in toDollars() 1" << std::endl;
}
if (usd.toDollars() != 78) {
std::cerr << "Error in toDollars() 2" << std::endl;
}
gbp.setValueFromDollars(1800);
usd.setValueFromDollars(120);
pln.setValueFromDollars(180);
if (gbp.getValue() != 1500) {
std::cerr << "Error in setValueFromDollars() 1" << std::endl;
}
if (usd.getValue() != 120) {
std::cerr << "Error in setValueFromDollars() 2" << std::endl;
}
if (pln.getValue() != 750) {
std::cerr << "Error in setValueFromDollars() 3" << std::endl;
}
usd.addValue(gbp);
if (usd.getValue() != 1920) {
std::cerr << "Error in addValue() 1" << std::endl;
}
gbp.addValue(pln);
if (gbp.getValue() != 1650) {
std::cerr << "Error in addValue() 2" << std::endl;
}
pln.addValue(usd);
if (pln.getValue() != 8750) {
std::cerr << "Error in addValue() 3" << std::endl;
}
CurrencyView in_gbp(pln, 1.2);
if (in_gbp.getValue() != 1750) {
std::cerr << "Error in CurrencyView::getValue() 1" << std::endl;
}
pln.setValue(100);
if (in_gbp.getValue() != 20) {
std::cerr << "Error in CurrencyView::getValue() 2" << std::endl;
}
std::cerr << "End of tests." << std::endl;
return 0;
}

View File

@ -0,0 +1,72 @@
#include <iostream>
class Currency
{
private:
double monetary_value;
double usd_exchange_rate;
public:
Currency()
{
monetary_value = 0;
usd_exchange_rate = 1;
}
Currency(double value, double rate)
{
monetary_value = value;
usd_exchange_rate = rate;
}
double getValue() const { return monetary_value; };
double getUSDExchangeRate() const { return usd_exchange_rate; };
void setValue(double value)
{
monetary_value = value;
return;
};
void setUSDExchangeRate(double rate)
{
usd_exchange_rate = rate;
return;
};
double toDollars() const { return monetary_value * usd_exchange_rate; };
void setValueFromDollars(double dollarsValue)
{
monetary_value = dollarsValue / usd_exchange_rate;
return;
}
void addValue(Currency whichWeAdd)
{
monetary_value = (toDollars() + whichWeAdd.toDollars()) / usd_exchange_rate;
}
};
class CurrencyView
{
private:
Currency& original;
double exchangeRate;
public:
CurrencyView(Currency& og, double rate);
double getValue() const;
};
CurrencyView::CurrencyView(Currency& reference, double rate) : original(reference)
{
exchangeRate = rate;
}
double CurrencyView::getValue() const
{
return original.toDollars() / exchangeRate;
}

282
EOOP/Various/node/node.cpp Executable file
View File

@ -0,0 +1,282 @@
#include <iostream>
struct list_node
{
int value;
list_node *next;
list_node(int v, list_node* nxt = nullptr)
{
value = v;
next = nxt;
}
};
class list
{
list_node *head;
int listSize;
public:
list()
{
head = nullptr;
listSize = 0;
}
bool is_empty() const;
int size() const;
void push_front(int val);
void pop_front();
void clear();
// removes first occurence of `val` in the list
// returns true if removal occured
bool remove(int val);
list_node *get_head();
void printValues() const;
};
bool list::is_empty() const
{
return head == nullptr;
}
int list::size() const
{
return listSize;
}
void list::push_front(int val)
{
list_node *pNewNode = new list_node(val);
pNewNode -> next = head;
head = pNewNode;
listSize++;
return;
}
void list::pop_front()
{
if(is_empty())
{
std::cout << "There are no elements to be popped!" << std::endl;
return;
}
list_node *pTemp = head;
pTemp = pTemp -> next;
delete head;
head = pTemp;
listSize--;
return;
}
void list::printValues() const
{
if(head == nullptr)
{
std::cout << "There are no values to be printed!" << std::endl;
return;
}
list_node *pNodes = head;
int i = 1;
while(pNodes)
{
std::cout << i << " value is: " << pNodes -> value << std::endl;
pNodes = pNodes -> next;
i++;
}
return;
}
void list::clear()
{
if(head == nullptr)
{
std::cout << "The list is already empty! " << std::endl;
return;
}
while(head) pop_front();
listSize = 0;
return;
}
bool list::remove(int val)
{
list_node *current = head;
list_node *previous = nullptr;
bool valueFound = 0;
while (current != nullptr)
{
if(current -> value == val)
{
valueFound = 1;
break;
}
previous = current;
current = current -> next;
}
if(!valueFound) return false;
if(previous == nullptr) head = head -> next; // THIS ELEMENT IS FIRST ELEMENT
else previous -> next = current -> next;
delete current;
listSize--;
return true;
}
list_node *list::get_head()
{
return head;
}
void printIsEmptyValue(list printedList)
{
std::cout << "is_empty() method value: " << printedList.is_empty() << std::endl;
return;
}
void isEmptyTest()
{
std::cout << "TESTING is_empty() METHOD" << std::endl;
list testIsEmpty;
std::cout << "Testing for 0 elements" << std::endl;
printIsEmptyValue(testIsEmpty);
std::cout << "Testing for 1 element" << std::endl;
testIsEmpty.push_front(1);
printIsEmptyValue(testIsEmpty);
std::cout <<"Testing after deleting 1 element" << std::endl;
testIsEmpty.pop_front();
printIsEmptyValue(testIsEmpty);
return;
}
void printSize(list printList)
{
std::cout << "Size of this list is: " << printList.size() << std::endl;
return;
}
void sizeTest()
{
std::cout << "TESTING size() METHOD" << std::endl;
list testSize;
std::cout << "Testing for empty list: " << std::endl;
printSize(testSize);
std::cout << "Testing for 1 element list: " << std::endl;
testSize.push_front(1);
printSize(testSize);
std::cout << "Testing after removing one element from 1 element list: " << std::endl;
testSize.pop_front();
printSize(testSize);
std::cout << "Testing for 5 elements list: " << std::endl;
for(int i = 0; i < 5; i++) testSize.push_front(i);
printSize(testSize);
return;
}
void pop_frontTest()
{
std::cout << "TESTING pop_front() METHOD" << std::endl;
list testPopFront;
std::cout << "Trying to pop empty list" << std::endl;
testPopFront.pop_front();
printIsEmptyValue(testPopFront);
printSize(testPopFront);
testPopFront.push_front(2137);
std::cout << "Poping one element list" << std::endl;
testPopFront.pop_front();
printIsEmptyValue(testPopFront);
printSize(testPopFront);
std::cout << "Poping two element list" << std::endl;
testPopFront.push_front(1);
testPopFront.push_front(2);
testPopFront.pop_front();
printIsEmptyValue(testPopFront);
printSize(testPopFront);
testPopFront.printValues();
return;
}
void clearTest()
{
std::cout << "TESTING clear() METHOD" << std::endl;
list testClear;
std::cout << "Trying to clear empty list: " << std::endl;
testClear.clear();
printIsEmptyValue(testClear);
printSize(testClear);
testClear.printValues();
std::cout << "Clearing one element list: " << std::endl;
testClear.push_front(1);
testClear.clear();
printIsEmptyValue(testClear);
printSize(testClear);
testClear.printValues();
std::cout << "Clearing two element list: " << std::endl;
testClear.push_front(1);
testClear.push_front(2);
testClear.clear();
printIsEmptyValue(testClear);
printSize(testClear);
testClear.printValues();
std::cout << "Clearing five element list: " << std::endl;
for(int i = 0; i < 5; i++) testClear.push_front(i);
testClear.clear();
printIsEmptyValue(testClear);
printSize(testClear);
testClear.printValues();
return;
}
void printRemoveResult(list fromWhichRemove, int value)
{
if(fromWhichRemove.remove(value)) std::cout << "Removal of value: " << value << " Successful!" << std::endl;
else std::cout << "Removal of value: " << value << " Failed! " << std::endl;
}
void removeTest()
{
std::cout << "TESTING remove() METHOD " << std::endl;
list testRemove;
std::cout << "Trying to remove element from empty list: " << std::endl;
printRemoveResult(testRemove, 0);
std::cout << "Trying to remove wrong element from 1 element list: " << std::endl;
testRemove.push_front(1);
printRemoveResult(testRemove, 2);
std::cout << "Trying to remove right element from 1 element list: " << std::endl;
testRemove.push_front(1);
printRemoveResult(testRemove, 1);
return;
}
void getHeadTest()
{
list testHead;
std::cout << "Testing getHead for empty list: " << std::endl;
std::cout << "getHead value: " << testHead.get_head() << std::endl;
testHead.push_front(5);
std::cout << "Testing getHead for non empty list: " << std::endl;
std::cout << "getHead value: " << testHead.get_head() << std::endl;
return;
}
void runTests()
{
isEmptyTest();
sizeTest();
pop_frontTest();
clearTest();
removeTest();
getHeadTest();
return;
}
int main()
{
runTests();
return 0;
}

View File

@ -0,0 +1,161 @@
#include "ring_buffer.hpp"
#include <array>
#include <iostream>
#include <stdexcept>
void error_message(const std::string& message, int value, int expected) {
std::cerr << "Error - " << message << ", got: " << value << " expected " << expected << std::endl;
}
void error_message(const std::string& message) {
std::cerr << "Error - " << message << "!" << std::endl;
}
void check_buffer(const RingBuffer& buffer, unsigned int expected_size, unsigned int expected_capacity) {
bool is_empty = buffer.isEmpty();
bool is_full = buffer.isFull();
if (expected_size == 0) {
if (!is_empty) {
error_message("buffer should be empty");
}
if (is_full) {
error_message("buffer shouldn't be full");
}
} else {
if (is_empty) {
error_message("buffer shouldn't be empty");
}
if ((expected_size == expected_capacity) && !is_full) {
error_message("buffer should be full");
}
}
unsigned int size = buffer.size();
if (size != expected_size) {
error_message("wrong buffer size", static_cast<int>(size), static_cast<int>(expected_size));
}
unsigned int capacity = buffer.capacity();
if (capacity != expected_capacity) {
error_message("wrong buffer capacity", static_cast<int>(capacity), static_cast<int>(expected_capacity));
}
}
void check_empty_buffer() {
unsigned int capacity = 4;
RingBuffer buffer(capacity);
check_buffer(buffer, 0, capacity);
}
void check_write_without_overwriting() {
unsigned int capacity = 6;
RingBuffer buffer(capacity);
buffer.write(7);
check_buffer(buffer, 1, capacity);
buffer.write(42);
check_buffer(buffer, 2, capacity);
}
void check_read_without_overwriting() {
RingBuffer buffer(3);
buffer.write(7);
buffer.write(42);
int read_number = buffer.read();
if (read_number != 7) {
error_message("read", read_number, 7);
}
read_number = buffer.read();
if (read_number != 42) {
error_message("read", read_number, 42);
}
check_buffer(buffer, 0, 3);
}
void _check_reading_after_overwrite(RingBuffer& buffer, unsigned int capacity) {
for ( unsigned int i = 2; i <= capacity + 1; ++i ) {
int read_number = buffer.read();
if (read_number != static_cast<int>(i)) {
error_message("read with overwrite", read_number, static_cast<int>(i));
}
}
check_buffer(buffer, 0, capacity);
}
void check_overwriting() {
unsigned int capacity = 4;
RingBuffer buffer(capacity);
for (unsigned int i = 0; i <= capacity + 1; ++i) {
buffer.write(static_cast<int>(i));
}
check_buffer(buffer, capacity, capacity);
_check_reading_after_overwrite(buffer, capacity);
}
void check_copy_constructor() {
unsigned int capacity = 5;
RingBuffer buffer(capacity);
for (unsigned int i = 0; i <= capacity + 1; ++i) {
buffer.write(static_cast<int>(i));
}
check_buffer(buffer, capacity, capacity);
RingBuffer copied(buffer);
check_buffer(copied, capacity, capacity);
_check_reading_after_overwrite(buffer, capacity);
_check_reading_after_overwrite(copied, capacity);
}
void check_assignment_operator() {
unsigned int capacity = 5;
RingBuffer buffer(capacity);
RingBuffer other(capacity);
for (unsigned int i = 0; i <= capacity + 1; ++i) {
buffer.write(static_cast<int>(i));
}
check_buffer(buffer, capacity, capacity);
check_buffer(other, 0, capacity);
other = buffer;
check_buffer(other, capacity, capacity);
_check_reading_after_overwrite(buffer, capacity);
_check_reading_after_overwrite(other, capacity);
}
void check_exceptions() {
unsigned int capacity = 5;
RingBuffer buffer(capacity);
RingBuffer other(capacity - 1);
try {
buffer.read();
error_message("missing exception while reading from empty buffer");
} catch(std::exception& e) { }
try {
buffer = other;
error_message("missing exception in copy constructor");
} catch(std::exception& e) { }
}
int main() {
check_empty_buffer();
check_write_without_overwriting();
check_read_without_overwriting();
check_overwriting();
check_copy_constructor();
check_assignment_operator();
check_exceptions();
std::cout << "End of tests." << std::endl;
return 0;
}

View File

@ -0,0 +1,113 @@
#ifndef RINGBUFFER_HPP
#define RINGBUFFER_HPP
#include <stdlib.h>
#include <iostream>
class RingBuffer {
public:
explicit RingBuffer(unsigned int capacity): capacity_ (capacity)
{
head_ = 0;
tail_ = 0;
size_ = 0;
overwritten = 0;
data_ = (int *)malloc(capacity_);
}
RingBuffer(const RingBuffer& other);
RingBuffer& operator=(const RingBuffer& other)
{
if(capacity_ != other.capacity_) throw std::exception();
head_ = other.head_;
tail_ = other.tail_;
size_ = other.size_;
overwritten = other.overwritten;
data_ = (int *)malloc(capacity_);
for(unsigned int i = 0; i < other.size_; i++)
{
data_[head_] = other.data_[head_];
if(overwritten)
{
tail_ = (tail_ + 1) % capacity_;
size_ = capacity_ - 1;
}
head_ = (head_ + 1) % capacity_;
overwritten = (head_ == tail_);
size_++;
}
}
~RingBuffer();
unsigned int size() const { return size_; }
unsigned int capacity() const { return capacity_; }
bool isEmpty() const { return size_ == 0; }
bool isFull() const { return size_ == capacity_; }
int& read();
void write(int value);
private:
const unsigned int capacity_;
unsigned int size_;
unsigned int head_;
unsigned int tail_;
int* data_;
bool overwritten;
};
RingBuffer::~RingBuffer()
{
if(data_)
{
delete data_;
data_ = nullptr;
}
}
void RingBuffer::write(int value)
{
data_[head_] = value;
if(overwritten)
{
tail_ = (tail_ + 1) % capacity_;
size_ = capacity_ - 1;
}
head_ = (head_ + 1) % capacity_;
overwritten = (head_ == tail_);
size_++;
}
int& RingBuffer::read()
{
if(size_ == 0) throw std::exception();
int& answer = data_[tail_];
overwritten = false;
tail_ = (tail_ + 1) % capacity_;
size_--;
return answer;
}
RingBuffer::RingBuffer(const RingBuffer& other): capacity_ (other.capacity_)
{
head_ = other.head_;
tail_ = other.tail_;
size_ = other.size_;
overwritten = other.overwritten;
data_ = (int *)malloc(capacity_);
for(unsigned int i = 0; i < other.size_; i++)
{
data_[head_] = other.data_[head_];
if(overwritten)
{
tail_ = (tail_ + 1) % capacity_;
size_ = capacity_ - 1;
}
head_ = (head_ + 1) % capacity_;
overwritten = (head_ == tail_);
size_++;
}
}
#endif // RINGBUFFER_HPP

View File

@ -0,0 +1,359 @@
// Krzysztof Rudnicki, 307585, EADS 2
#include <iostream>
void print(const std::string s)
{
std::cout << s << std::endl;
}
template<typename Key, typename Info>
class Ring{
private:
struct Node{
Key key;
Info info;
Node* next;
Node* prev;
};
Node* any;
public:
class Iterator
{
private:
Node* pNode;
public:
Iterator() { pNode = nullptr; }
~Iterator() { pNode = nullptr; }
Iterator(Node* ptr) : pNode(ptr) {}
bool operator!=(const Iterator& other) const
{
return pNode != other.pNode;
}
Iterator& operator++()
{
pNode = pNode -> next;
return *this;
}
Iterator operator++(int)
{
Iterator it = *this;
pNode = pNode -> next;
return it;
}
Iterator& operator--()
{
pNode = pNode -> prev;
return *this;
}
Iterator operator--(int)
{
Iterator it = *this;
pNode = pNode -> prev;
return it;
}
Node& operator[](int index)
{
Node* indexedNode = pNode;
for(int i = 0; i < index; i++)
{
indexedNode = indexedNode -> next;
}
return *indexedNode;
}
Node* operator->()
{
return pNode;
}
Node& operator*()
{
return *pNode;
}
bool operator==(const Iterator& other) const
{
return pNode == other.pNode;
}
};
Ring();
~Ring();
void clearRing();
void print() const;
void addAtEnd(Key newKey, Info newInfo);
int size() const;
Iterator begin() const // I will treat "any" Node as a "begining" of a ring
{
return Iterator(any);
}
Iterator end() const // I will treat a Node just before "any" node as an "end" of a ring
{
if(any == nullptr) return nullptr;
return any -> prev;
}
};
template<typename Key, typename Info>
Ring<Key, Info>::Ring()
{
any = nullptr;
}
template<typename Key, typename Info>
void Ring<Key, Info>::clearRing()
{
if(any == nullptr) return;
Node* curr = any;
Node* temp = any;
do{
temp = curr;
curr = curr->next;
delete temp;
}while(curr != any);
delete any;
}
template<typename Key, typename Info>
Ring<Key, Info>::~Ring()
{
this -> clearRing();
}
template<typename Key, typename Info>
void Ring<Key, Info>::print() const
{
Node* curr = any;
do{
std::cout << curr -> key << "; " << curr->info << std::endl;
curr = curr->next;
}while (curr != any);
}
template<typename Key, typename Info>
void Ring<Key, Info>::addAtEnd(Key newKey, Info newInfo)
{
Node* newNode = new Node();
newNode -> key = newKey;
newNode -> info = newInfo;
if(any == nullptr)
{
any = newNode;
any -> next = any;
any -> prev = any;
return;
}
if(any -> next == nullptr)
{
any -> next = newNode;
any -> prev = newNode;
newNode -> next = any;
newNode -> prev = any;
return;
}
Node* curr = any;
while(curr -> next != any) curr = curr -> next;
any->prev = newNode;
curr->next = newNode;
newNode -> prev = curr;
newNode -> next = any;
}
template<typename Key, typename Info>
int Ring<Key, Info>::size() const
{
Node* curr = any;
int size = 0;
do{
size++;
curr = curr -> next;
}while (curr != any);
return size;
}
template <typename Key, typename Info>
void printPair(const Key key, const Info info)
{
std::cout << "Key: " << key << "; Info: " << info << std::endl;
}
bool testForEmpty()
{
Ring<int, int> marcel;
Ring<int, int>::Iterator it = marcel.begin();
if(it != nullptr)
{
print("testForEmpty");
return false;
}
return true;
}
bool testOneElement()
{
Ring<int, int> marcel;
marcel.addAtEnd(1, 1);
Ring<int, int>::Iterator it = marcel.begin();
if(it -> key != 1 || it -> info != 1)
{
print("testForwardIncrementingOneElement");
return false;
}
return true;
}
bool testForwardIncrementing()
{
Ring<int, int> marcel;
marcel.addAtEnd(1, 1);
marcel.addAtEnd(2, 2);
marcel.addAtEnd(3, 3);
marcel.addAtEnd(4, 4);
marcel.addAtEnd(5, 5);
int i = 0;
for( Ring<int, int>::Iterator it = marcel.begin();
it != marcel.end(); it++, i++)
{
if(it -> key != i + 1 || it -> info != i + 1)
{
print("testForwardIncrementingNormal");
return false;
}
}
if(marcel.end() -> key != 5 || marcel.end() -> info != 5)
{
print("testForwardIncrementingNormal");
return false;
}
return true;
}
bool testBackwardDecrementing()
{
Ring<int, int> marcel;
marcel.addAtEnd(1, 1);
marcel.addAtEnd(2, 2);
marcel.addAtEnd(3, 3);
marcel.addAtEnd(4, 4);
marcel.addAtEnd(5, 5);
int i = 0;
for( Ring<int, int>::Iterator it = marcel.end();
it != marcel.begin(); it++, i++)
{
if(it -> key != 5 - i || it -> info != 5 - i)
{
print("testBackwardDecrementing");
return false;
}
}
if(marcel.begin() -> key != 1 || marcel.begin() -> info != 1)
{
print("testBackwardDecrementing");
return false;
}
return true;
}
bool testForwardSquareBracket()
{
Ring<int, int> marcel;
marcel.addAtEnd(1, 1);
marcel.addAtEnd(2, 2);
marcel.addAtEnd(3, 3);
marcel.addAtEnd(4, 4);
marcel.addAtEnd(5, 5);
Ring<int, int>::Iterator it = marcel.begin();
for(int i = 0; i < marcel.size(); i++)
{
if(it[i].key != i + 1 || it[i].info != i + 1)
{
print("testForwardSquareBracket");
return false;
}
}
return true;
}
bool testBackwardSquareBracket()
{
Ring<int, int> marcel;
marcel.addAtEnd(1, 1);
marcel.addAtEnd(2, 2);
marcel.addAtEnd(3, 3);
marcel.addAtEnd(4, 4);
marcel.addAtEnd(5, 5);
Ring<int, int>::Iterator it = marcel.end();
for(int i = marcel.size(); i > 0; i--)
{
if(it[i].key != i || it[i].info != i)
{
print("testBackwardSquareBracket");
return false;
}
}
return true;
}
bool testSquareBracketRandomOverflow()
{
Ring<int, int> marcel;
marcel.addAtEnd(1, 1);
marcel.addAtEnd(2, 2);
marcel.addAtEnd(3, 3);
marcel.addAtEnd(4, 4);
marcel.addAtEnd(5, 5);
Ring<int, int>::Iterator it = marcel.begin();
//Checking for some random places in ring:
if(it[2].key != 3)
{
print("testSquareBracketRandomOverflow");
return false;
}
if(it[4].key != 5)
{
print("testSquareBracketRandomOverflow");
return false;
}
if(it[0].key != 1)
{
print("testSquareBracketRandomOverflow");
return false;
}
//Checking for overflow:
if(it[10].key != 1)
{
print("testSquareBracketRandomOverflow");
return false;
}
return true;
}
bool tests()
{
return testForEmpty()&&testOneElement()&&testForwardIncrementing()
&&testBackwardDecrementing()&&testForwardSquareBracket()&&testBackwardSquareBracket()
&&testSquareBracketRandomOverflow();
}
int main()
{
std::cout << "Result of tests is: " << tests() << std::endl;
return 1;
}

View File

@ -0,0 +1,406 @@
#include <iostream>
using namespace std;
template <typename Key, typename Info>
class Ring
{
private:
struct Node
{
Key key;
Info info;
Node *prev;
Node *next;
};
Node *head;
public:
class Iterator
{
private:
Node *ptr;
Node *headPtr;
Iterator(Node*);
friend class Ring<Key, Info>;
public:
Iterator();
Iterator(Ring);
Info getInfo();
Key getKey();
void printData(int);
Info operator*();
Iterator& operator++();//prefix
Iterator operator++(int);//postfix
Iterator& operator--();//prefix
Iterator operator--(int);//postfix
bool operator==(const Iterator&);
bool operator!=(const Iterator&);
bool isFirst();
bool isLast();
};
Ring();
~Ring();
void insertAtBeginning(const Key& k, const Info& inf);
void insertAtEnd(const Key& k, const Info& inf);
void removeAtBeginning();
void removeAtEnd();
void clear();
void printContent();
void printContentReverse();
Iterator begin();
Iterator end();
};
//main function
int main()
{
//test 1 - printing
Ring<char, string> ring;
ring.insertAtEnd('a', "letter 1");
ring.insertAtEnd('b', "letter 2");
ring.insertAtEnd('c', "letter 3");
ring.insertAtEnd('d', "letter 4");
ring.insertAtEnd('e', "letter 5");
cout << "Normal print:" << endl;
ring.printContent();
Ring<char, string>::Iterator *ringIt = new Ring<char, string>::Iterator(ring);
cout << endl << "Iterator print:" << endl;
int number = 0;
while (ringIt->isLast() == false)
{
ringIt->printData(number);
number++;
++ringIt;
}
return 0;
}
//------------------------------Ring functions
template <typename Key, typename Info>
Ring<Key, Info>::Ring()
{
head = nullptr;
}
template <typename Key, typename Info>
Ring<Key, Info>::~Ring()
{
clear();
}
template <typename Key, typename Info>
void Ring<Key, Info>::insertAtBeginning(const Key& k, const Info& inf)
{
if (head == nullptr)
{
Node *newNode = new Node();
newNode->key = k;
newNode->info = inf;
newNode->next = newNode;
newNode->prev = newNode;
head = newNode;
return;
}
Node *last = head->prev;
Node *newNode = new Node();
newNode->key = k;
newNode->info = inf;
newNode->prev = last;
last->next = newNode;
newNode->next = head;
head->prev = newNode;
head = newNode;
}
template <typename Key, typename Info>
void Ring<Key, Info>::insertAtEnd(const Key& k, const Info& inf)
{
if (head == nullptr)
{
Node *newNode = new Node();
newNode->key = k;
newNode->info = inf;
newNode->next = newNode;
newNode->prev = newNode;
head = newNode;
return;
}
Node *last = head->prev;
Node *newNode = new Node();
newNode->key = k;
newNode->info = inf;
newNode->prev = last;
last->next = newNode;
newNode->next = head;
head->prev = newNode;
}
template <typename Key, typename Info>
void Ring<Key, Info>::removeAtBeginning()
{
if (head == nullptr)
return;
if (head->next == head)
{
delete head;
head = nullptr;
return;
}
Node *prev = head->prev;
Node *next = head->next;
prev->next = next;
next->prev = prev;
delete head;
head = next;
}
template <typename Key, typename Info>
void Ring<Key, Info>::removeAtEnd()
{
if (head == nullptr)
return;
if (head->next == head)
{
delete head;
head = nullptr;
return;
}
Node *prev = head->prev->prev;
//Node *next = head;
delete head->prev;
prev->next = head;
head->prev = prev;
}
template <typename Key, typename Info>
void Ring<Key, Info>::clear()
{
while (head != nullptr)
removeAtEnd();
}
template <typename Key, typename Info>
void Ring<Key, Info>::printContent()
{
if (head == nullptr)
return;
Node *current = head;
int number = 0;
do
{
cout << number << "# - Key: " << current->key << ", Info: " << current->info << endl;
number++;
current = current->next;
} while (current != head);
}
template <typename Key, typename Info>
void Ring<Key, Info>::printContentReverse()
{
if (head == nullptr)
return;
if (head->next == head)
{
cout << "0# - Key: " << head->key << ", Info: " << head->info << endl;
}
Node *current = head->prev;
int number = 0;
do
{
cout << number << "# - Key: " << current->key << ", Info: " << current->info << endl;
number++;
current = current->prev;
} while (current != head);
}
template <typename Key, typename Info>
typename Ring<Key, Info>::Iterator Ring<Key, Info>::begin()
{
Ring<Key, Info>::Iterator tempIter = new Ring<Key, Info>::Iterator(head);
return tempIter;
}
template <typename Key, typename Info>
typename Ring<Key, Info>::Iterator Ring<Key, Info>::end()
{
Ring<Key, Info>::Iterator tempIter = new Ring<Key, Info>::Iterator(head->prev);
return tempIter;
}
//------------------------------Ring Iterator functions
template <typename Key, typename Info>
Ring<Key, Info>::Iterator::Iterator()
{
ptr = nullptr;
headPtr = nullptr;
}
template <typename Key, typename Info>
Ring<Key, Info>::Iterator::Iterator(Node* nodePtr)
{
ptr = nodePtr;
headPtr = nodePtr;
}
template <typename Key, typename Info>
Ring<Key, Info>::Iterator::Iterator(Ring<Key, Info> ring)
{
ptr = ring.head;
headPtr = ring.head;
}
template <typename Key, typename Info>
Info Ring<Key, Info>::Iterator::getInfo()
{
if (ptr != nullptr)
return ptr->info;
else
throw "Iterator was nullptr";
}
template <typename Key, typename Info>
Key Ring<Key, Info>::Iterator::getKey()
{
if (ptr != nullptr)
return ptr->key;
else
throw "Iterator was nullptr";
}
template <typename Key, typename Info>
void Ring<Key, Info>::Iterator::printData(int number)
{
if (ptr != nullptr)
cout << number << "# - Key: " << ptr->key << ", Info: " << ptr->info << endl;
else
cout << "Tried to print an empty iterator" << endl;
}
template <typename Key, typename Info>
Info Ring<Key, Info>::Iterator::operator*()
{
if (ptr != nullptr)
return ptr->info;
else
throw "Iterator was nullptr";
}
template <typename Key, typename Info>
typename Ring<Key, Info>::Iterator& Ring<Key, Info>::Iterator::operator++()
{
if (ptr != nullptr && headPtr != nullptr && ptr->next != headPtr)
ptr = ptr->next;
return *this;
}
template <typename Key, typename Info>
typename Ring<Key, Info>::Iterator Ring<Key, Info>::Iterator::operator++(int)
{
Ring<Key, Info>::Iterator incremented = *this;
++(*this);
return incremented;
}
template <typename Key, typename Info>
typename Ring<Key, Info>::Iterator& Ring<Key, Info>::Iterator::operator--()
{
if (ptr != nullptr && headPtr != nullptr && ptr != headPtr)
ptr = ptr->prev;
return *this;
}
template <typename Key, typename Info>
typename Ring<Key, Info>::Iterator Ring<Key, Info>::Iterator::operator--(int)
{
Ring<Key, Info>::Iterator decremented = *this;
--(*this);
return decremented;
}
template <typename Key, typename Info>
bool Ring<Key, Info>::Iterator::operator==(const Ring<Key, Info>::Iterator& iter)
{
if (ptr == iter->ptr)
return true;
else
return false;
}
template <typename Key, typename Info>
bool Ring<Key, Info>::Iterator::operator!=(const Ring<Key, Info>::Iterator& iter)
{
if (operator==(this))
return false;
else
return true;
}
template <typename Key, typename Info>
bool Ring<Key, Info>::Iterator::isLast()
{
cout << (ptr != nullptr) << " " << (headPtr != nullptr) << " " << (ptr->next == headPtr) << endl;
if (ptr != nullptr && headPtr != nullptr && ptr->next == headPtr)
return true;
else
return false;
}
template <typename Key, typename Info>
bool Ring<Key, Info>::Iterator::isFirst()
{
if (ptr != nullptr && headPtr != nullptr && ptr == headPtr)
return true;
else
return false;
}