Introduction
I'm learning C++ (Coming from Haskell, C, and Assembly - and other languages sparsely) and this was my practice with classes and templates. It's a linked list that you can call in this fashion:
#include "list.hpp"
int main(void){
linked_list<char> test;
char c;
while(c != '\n') //
test.prepend(c = fgetc(stdin));
std::cout << test;
std::cout << std::endl;
return 0;
}
Topic
I am here to ask if some more experienced coders would point out my mistakes (mainly about classes) so I can break the habits. Thanks for your help!
Here is the source code: (Btw, it isn't optimized on purpose, I was only playing with classes/templates)
(I do notice the inefficient and potentially dangerous tail() call, but considering the trivial nature of the project - I decided to leave it for later, simply make it a deque. I also naively checked it with memcheck. No leaks and no errors in my library, seemingly.) Ideone Link
//Compile with "g++ -std=C++11 -O2 -o list main.cpp list.hpp"
#ifndef LIST_H
#define LIST_H
#include <iostream>
template <typename T>
class linked_list {
private:
int empty = 1;
struct node {
T data;
struct node * next;
} * head;
struct node * get_add(int index);
public:
linked_list(){head = new node;};
linked_list(T data){head = new node; head = data; empty = 0;}
~linked_list();
int size();
inline int nsize(){return sizeof(struct node);};
inline struct node * lhead() {return head;};
inline struct node * tail() {return get_add(size()-1);};
int search(T key);
void prepend(T data);
void append(T data);
int insert(T data, int index);
int del(int index);
int set(T data, int index);
T get(int index);
T& operator[](int i);
};
template<typename T>
std::ostream& operator<< (std::ostream &out, linked_list<T> &list);
//////////////IMPLEMENTATION//////////////
//////////////////////////////////////////
template <typename T>
T& linked_list<T>::operator[](int i){
return (get_add(i)->data);
}
template <typename T>
std::ostream& operator<< (std::ostream &out, linked_list<T> &list){
int i;
for(i = 0; i < list.size(); i++)
out << list.get(i);
return out;
}
template <typename T>
int linked_list<T>::size(){
int i;
struct node * tmp = head;
for(i = 1; tmp->next != NULL; i++)
tmp = tmp->next;
return i;
}
template <typename T>
int linked_list<T>::set(T data, int index){
if(index >= size())
return -1;
get_add(index)->data = data;
return data;
}
template <typename T>
void linked_list<T>::prepend(T data){
if(empty){
head->data = data;
empty = 0;
} else {
struct node * tmp = new node;
tmp->data = head->data;
tmp->next = head->next;
head->data = data;
head->next = tmp;
}
}
template <typename T>
void linked_list<T>::append(T data){
if(empty){
head->data = data;
empty = 0;
} else {
struct node * tmp = new node;
tmp->data = data;
tmp->next = NULL;
tail()->next = tmp;
}
}
template <typename T>
int linked_list<T>::insert(T data, int index){
if(index >= size())
return -1;
if(empty){
head->data = data;
empty = 0;
} else {
struct node * tmp = new node;
struct node * location = get_add(index);
struct node * prev = get_add(index-1);
tmp->data = data;
tmp->next = location;
prev->next = tmp;
}
return 0;
}
template <typename T>
int linked_list<T>::del(int index){
if(index >= size())
return -1;
struct node * prev = get_add(index-1);
struct node * tmp = prev->next->next;
delete prev->next;
prev->next = tmp;
return 0;
}
template <typename T>
int linked_list<T>::search(T key){
int i;
struct node * tmp = head;
for(i = 0; key != tmp->data; i++)
tmp = tmp->next;
return i;
}
template <typename T>
T linked_list<T>::get(int index){
if(index >= size())
return 0;
int i;
struct node * tmp = head;
for(i = 0; tmp->next != NULL && i < index; i++)
tmp = tmp->next;
return tmp->data;
}
template <typename T>
struct linked_list<T>::node * linked_list<T>::get_add(int index){
if(index >= size())
return 0;
int i = 0;
struct node * tmp = head;
while(i++ < index)
tmp = tmp->next;
return tmp;
}
template <typename T>
linked_list<T>::~linked_list(){
struct node * tmp = head->next;
for(; head->next != NULL; tmp = head->next){
head->next = head->next->next;
delete tmp;
}
delete head;
}
#endif
Thanks again.
#ifndef LIST_H
). I'd recommend#ifndef LINKED_LIST_H
if you don't use namespaces, just to be consistent with the actual template class name. \$\endgroup\$