/*
Linked List exercise
*/
class node {
public:
node * next;
int * data;
data
на самом деле не обязательно быть указателем (если только в вашем классе не указано, что так и должно быть). Вы можете изменить это значение на int
, а затем изменить ссылки с *(t->data)
на t->data
. Точно так же вам не нужно будет использовать new
и delete
в ctor / dtor.
node(const int i) {
data = new int;
*data = i;
}
node& operator=(node n) {
*data = *(n.data);
}
~node() {
delete data;
}
};
class linkedList {
public:
node * head;
node * tail;
int nodeCount;
linkedList() {
head = NULL;
tail = NULL;
Вы должны инициализировать всех ваших членов данных здесь. nodeCount
будет иметь какое-то случайное значение, если вы не установите его здесь на ноль.
}
~linkedList() {
while (head) {
node* t = head->next;
delete head;
if (t)
head = t;
Это похоже на ошибку. Вам необходимо всегда назначать head = t
, даже когда t равно NULL
, иначе ваш цикл не завершится (но удаление одного и того же узла несколько раз может вызвать исключение).
}
}
void add(node * n) {
if (!head) {
head = n;
head->next = NULL;
tail = head;
nodeCount = 0;
Я думаю, что все это утверждение if
не нужно. Обе ветви делают одно и то же, когда связанный список пуст, поэтому вы всегда можете использовать вторую ( else ) ветку.
Кроме того, установка nodeCount
на 0
в конце кажется ошибкой; не должно ли это быть 1
?
} else {
node * t = head;
while (t->next)
t = t->next;
t->next = n;
n->next = NULL;
nodeCount++;
}
}
node * operator[](const int &i) {
Незначительная гнида, но аргумент const int &
не имеет никакого смысла. Вы ничего не получите, просто пройдя тип int
.
if ((i >= 0) && (i < nodeCount))
throw new exception("ERROR: Invalid index on linked list.", -1);
Вышеуказанное состояние смотрит назад на меня; вы всегда будете выдавать исключение с допустимыми параметрами.
node *t = head;
for (int x = i; x < nodeCount; x++)
t = t->next;
Цикл выше кажется мне немного подозрительным. Если i
- это нулевой индекс нужного вам узла, не должен ли ваш счетчик перейти с 0
на i-1
?
return t;
}
void print() {
if (!head)
return;
Опять же, вы должны заставить этот метод работать без необходимости защиты от пустого списка. Я ожидаю, что пустой список напечатает что-то вроде []
, но с указанным выше защитным кодом вы ничего не напечатаете.
node * t = head;
string collection;
int c = 0;
cout << "[";
if (!t->next) {
cout << *(t->data);
Как и другое условие выше, я думаю, что ветвь выше не нужна. Вторая ( else ) ветвь должна нормально обрабатывать случай NULL
.
} else {
while (t->next) {
Я думаю, вы хотите while (t)
выше, а не while (t->next)
cout << *(t->data);
c++;
if (t->next)
t = t->next;
Я думаю, что это ошибка, подобная той, что была ранее. Вы должны всегда назначать `t = t-> next ', иначе ваш цикл не завершится.
if (c < nodeCount)
cout << ", ";
}
}
cout << "]" << endl;
}
};
int main (const int & argc, const char * argv[]) { // const int& ?
const int &
снова ...
try {
linkedList * myList = new linkedList;
for (int x = 0; x < 10; x++)
myList->add(new node(x));
myList->print();
} catch(exception &ex) {
cout << ex.what() << endl;
return -1;
}
Вероятно, это хорошо для домашнего задания, но перехват всех возможных исключений (как вы делаете выше), вероятно, не приносит особой пользы и обычно считается плохой практикой.
Если вы пропустите эту попытку / уловку выше, я подозреваю, что всякий раз, когда ваша программа завершает работу с исключением, обработчик исключений верхнего уровня по умолчанию, предоставляемый компилятором, будет в любом случае выгружать информацию об исключении и трассировке стека (зависит от вашего компилятор).
return 0;
}