Cześć,
W ramach odświeżenia wiedzy na temat tworzenia listy i zaznajomienia się z templatami postanowiłem połączyć te 2 rzeczy i stworzyć listę na templatach. Ogólnie wyszło OK, jeszcze nie przychodzi mi wszystko intuicyjnie, ale obyło się bez większych problemów. Piszę ten post odnośnie dwóch spraw:
1) Ocena kodu. Czego nie powinienem robić? Co można poprawić? Czy konceptualnie projekt jest poprawny? Konwencja pisowni jest poprawna? To tylko taki teaser, planuję dodać kilka przydatnych funkcji, ale zanim to zrobię, chcę się upewnić, że idę w dobrym kierunku.
2) Chciałbym za pomocą takiej listy zrobić zrobić np. Strukturę "Książka", która będzie przechowywała listę jej parametrów jak np. Tytuł jako łańcuch znaków, ID jako liczbę całkowitą itp. Niestety w chwili obecnej nie mogę stworzyć listy, która nie będzie miała z góry określonego typu. Mogę zrobić listę int'ów, która przechowa mi np. cenę i ID, ale już tytułu tam nie wrzucę i vice versa. Da się to jakoś obejść? Może istnieje jakieś inne podejście niż templata w takim wypadku?
Poniżej wrzucam kod:
Plik nagłówkowy:
#pragma once
#include "pch.h"
#include <iostream>
template <class T>
class Element //AKA Node
{
private:
Element<T> *next;
char * name; //name of our data container
T value; //stored value
public:
Element(const char *_name, T _value, Element<T> *_next);
~Element();
const char * getName();
T getValue();
void setName(const char *_name);
void setValue(T _value);
void setNext(Element<T> *_next);
Element<T>* getNext();
void deleteElement();
};
template <class T>
class ElementList
{
private:
Element<T> *head;
public:
ElementList();
~ElementList();
void addElement(const char *name, T value);
void deleteList();
void printList();
};
Plik źródłowy + test
#include "pch.h"
#include "LinkedList.h"
using namespace std;
template <class T>
Element<T>::Element(const char *_name, T _value, Element<T> *_next)
{
setName(_name);
value = _value;
setNext(_next);
}
template <class T>
Element<T>::~Element()
{
deleteElement();
delete this;
}
template <class T>
const char *Element<T>::getName()
{
return name;
}
template <class T>
T Element<T>::getValue()
{
return value;
}
template <class T>
void Element<T>::setName(const char *_name)
{
delete[] name; //better safe than sorry
name = new char[strlen(_name) + 1]; //let's allocate some memory for our string
strcpy_s(name, strlen(_name) + 1, _name); //time to copy
}
template <class T>
void Element<T>::setValue(T _value)
{
if (isdigit(_value))
value = _value;
else //if inserted value is not a digit, it's apparently a string of characters
{
delete[] value;
value = new char(strlen(_value) + 1);
strcpy_s(value, strlen(_value) + 1, _value);
}
}
template <class T>
void Element<T>::setNext(Element<T> *_next)
{
next = _next;
}
template <class T>
Element<T>* Element<T>::getNext()
{
return next;
}
template <class T>
void Element<T>::deleteElement()
{
delete[] name;
//if (!isdigit(value))
//delete[] value;
}
/*List's methods from now on*/
template <class T>
ElementList<T>::ElementList()
{
head = nullptr;
}
template <class T>
ElementList<T>::~ElementList()
{
deleteList();
}
template <class T>
void ElementList<T>::addElement(const char *name, T value)
{
if (!head) //No elements in the list
{
head = new Element<T>(name, value, nullptr);
}
else //Allright, list is not empty, thus we're throwing the element to the last position
{
Element<T> *current = head;
while (current->getNext())
{
current = current->getNext();
}
Element<T> *temp = new Element<T>(name, value, nullptr);
current->setNext(temp);
}
}
template <class T>
void ElementList<T>::deleteList()
{
if (!head->getNext() && head) //just one element in the list
head->deleteElement();
else if (head->getNext()) //more then one element in the list
{
Element<T> *current = head->getNext();
Element<T> *previous = head;
while (current)
{
previous->deleteElement();
previous = current;
current = current->getNext();
}
previous->deleteElement();
}
}
template <class T>
void ElementList<T>::printList()
{
Element<T> *current = head; //Just to keep track
while (current->getNext())
{
cout << current->getName() << endl;
cout << current->getValue() << endl;
cout << endl;
current = current->getNext();
}
cout << current->getName() << endl;
cout << current->getValue() << endl;
cout << endl;
}
int main()
{
ElementList<double> Book1;
Book1.addElement("Price in zl", 28.50);
Book1.addElement("ID", 12345);
Book1.addElement("Height", 15.3);
Book1.addElement("Width", 8.4);
//Book1.addElement("Title", "C++ programming");//I'd like it to work this way as well
Book1.printList();
}