Список в С++: где ошибка?
Пользователи, просматривающие топик: none
|
Зашли как: Guest
|
Имя |
Сообщение |
<< Старые топики Новые топики >> |
|
|
Список в С++: где ошибка? - 2008-12-21 13:13:48.380000
|
|
|
t3rmin41
Сообщений: 245
Оценки: 0
Присоединился: 2007-11-12 14:06:01.393333
|
Написал программу с помощью классов, которая составляет структуру списка. Всё вроде должно работать, но в одной функции выкидывает ошибку. Вот код:
#include <assert.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
class Item
{
friend class List;
private:
Item(double value, Item *item=0) {val=value; next=item; };
double val;
Item *next;
};
class List
{
public:
List(double a=0);
List(double *, int);
List(List&);
void out(char *);
~List() { remove(); };
int length() {return im; };
void remove();
void remove(int);
void append(double);
void append(double *, int);
void add(List,double);
void addvalues(List, double *, int);
void cut(int);
double &operator [](int);
private:
Item *findEnd();
Item *first;
int im;
};
List::List(double a)
{
Item *curr=new Item(a);
assert(curr!=0);
first=curr;
im=1;
}
List::List(double *mas, int num)
{
int i; Item *prev,*curr;
curr=new Item(mas[0]);
assert(curr!=0);
prev=first=curr;
for(i=1; i<num; i++)
{
curr = new Item(mas[i]);
assert(curr!=0);
prev->next=curr;
prev=curr;
}
im=num;
}
List::List(List &lem)
{
int i; Item *curr,*prev,*pt;
pt=lem.first;
curr = new Item(pt-> val);
assert(curr!=0);
prev=first=curr;
for(i=1; i<lem.im; i++)
{
pt=pt->next;
curr=new Item(pt->val);
assert(curr!=0);
prev->next=curr;
prev=curr;
}
im=lem.im;
}
void List::remove()
{
Item *pt=first;
while(pt)
{
Item *pnt=pt;
pt=pt->next;
delete pnt;
}
im=0;
}
Item *findEnd()
{
Item *curr;
curr=first;
while(curr->next);
curr=curr->next;
return curr;
}
void List::remove(int num)
{
assert(num<im);
int i=0;
Item *prev,*curr;
im-=num;
prev=curr=first;
while (i<im)
{
prev=curr;
curr=curr->next;
i++;
}
while(curr)
{
Item *pnt=curr;
curr=curr->next;
delete pnt;
}
prev->next=0;
}
void List::out(char *name)
{
printf("%s im=%d\n",name,im);
Item *curr; int num=0; curr=first;
while (curr)
{
printf("%3.f ",curr->val);
curr=curr->next;
num++;
if ((num%5)==0)
printf("\n");
}
printf("\n");
}
void List::append(double value)
{
Item *curr;
Item *pt=new Item(value);
assert(pt!=0);
curr=findEnd();
curr->next=pt;
im++;
}
void List::append(double *mas, int num)
{
if (num<=0) {return; }
int i; Item *curr,*prev;
prev=findEnd();
for(i=0; i<num; i++)
{
curr=new Item(mas[i]);
assert(curr!=0);
prev->next=curr;
prev=curr;
}
im+=num;
}
double &List::operator [](int num)
{
Item *curr, *prev;
int i,ifin;
assert(num>=0);
if (num<im)
{
prev=first;
while(num>0)
{
prev=prev->next;
num--;
}
}
else
{
prev=findEnd();
ifin=num-im+1;
for(i=0; i<ifin; i++)
{
curr=new Item(0.0);
assert(curr!=0);
prev->next=curr;
prev=curr;
}
im=num+1;
}
return prev->val;
}
void List::add(List a,double value)
{
Item *curr;
Item *pt=new Item(value);
a.first=curr;
pt->next=curr;
a.first=pt;
a.im++;
}
void List::addvalues(List a, double *mas, int n)
{
int i;
for (i=0; i<n; i++)
{
a.add(a,mas[i]);
}
}
void List::cut(int num)
{
assert(num<im);
Item *curr;
for(int i=0; i<num; i++)
{
curr=first;
curr=curr->next;
delete first;
first=curr;
im--;
}
}
main()
{
double a[]={1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
double b[]={11.0, 12.0, 13.0, 14.0, 15.0};
List list1(a, 8);
list1.out("list1");
list1.remove(3);
list1.out("list1 after truncation");
list1.append(b, 3);
list1.out("list1 after append(b,3)");
getch();
return 0;
}
Текст ошибки такой: quote:
Error 24task.CPP 107: Undefined symbol 'first' Error 24task.CPP 109: 'Item::next' is not accessible Error 24task.CPP 110: 'Item::next' is not accessible Все ошибки находятся в функции Item *findEnd() Видимо, функция не получает доступ к атрибуту класса List::first и атрибуту класса Item::next, но почему, я не понимаю.
|
|
|
RE: Список в С++: где ошибка? - 2008-12-21 15:38:52.146666
|
|
|
_SaZ_
Сообщений: 4329
Оценки: 398
Присоединился: 2008-01-30 02:18:05.553333
|
А с чего ты решил, что левая функция должна получать в ним доступ?
|
|
|
RE: Список в С++: где ошибка? - 2008-12-21 19:03:25.740000
|
|
|
t3rmin41
Сообщений: 245
Оценки: 0
Присоединился: 2007-11-12 14:06:01.393333
|
в каком смысле левая? Что в ней плохого?
|
|
|
RE: Список в С++: где ошибка? - 2008-12-21 19:57:41.770000
|
|
|
_SaZ_
Сообщений: 4329
Оценки: 398
Присоединился: 2008-01-30 02:18:05.553333
|
Ну какого х она должна иметь права доступа к членам твоего класса?… Рано ты за ООП взялся, начни с теории лучше. Без неё только мозги себе покалечишь.
|
|
|
RE: Список в С++: где ошибка? - 2008-12-21 23:09:30.460000
|
|
|
t3rmin41
Сообщений: 245
Оценки: 0
Присоединился: 2007-11-12 14:06:01.393333
|
Ну а как сделать чтоб имела доступ? К теме о "Рано ты за ООП взялся, начни с теории лучше": не ошибается только тот, кто ничего не делает.
|
|
|
RE: Список в С++: где ошибка? - 2008-12-22 02:08:50.476666
|
|
|
Archivarius
Сообщений: 164
Оценки: 0
Присоединился: 2008-10-26 00:16:25.630000
|
quote:
ORIGINAL: t3rmin41 Ну а как сделать чтоб имела доступ? { Так это ты вобще написал? Ничего подозрительного в своем коде не замечаешь? Конкретно тут: class List { ….. private: Item *findEnd(); Item *first; } Item *findEnd() { Item *curr; curr=first; ….. }
|
|
|
RE: Список в С++: где ошибка? - 2008-12-22 03:42:35.180000
|
|
|
_SaZ_
Сообщений: 4329
Оценки: 398
Присоединился: 2008-01-30 02:18:05.553333
|
quote:
ORIGINAL: t3rmin41 К теме о "Рано ты за ООП взялся, начни с теории лучше": не ошибается только тот, кто ничего не делает. С твоим подходом ты будешь очень долго ошибаться. Не стоит изобретать велосипед, когда есть отлаженные методики обучения. Думаю ты не Крис Касперски, который с помощью одной лишь debug.com за 3 месяца освоил язык ассемблера. В общем лучше почитать книжки, чем лишний раз грузить нас глупыми вопросами.
|
|
|
RE: Список в С++: где ошибка? - 2008-12-22 12:23:31.013333
|
|
|
t3rmin41
Сообщений: 245
Оценки: 0
Присоединился: 2007-11-12 14:06:01.393333
|
quote:
ORIGINAL: Archivarius quote:
ORIGINAL: t3rmin41 Ну а как сделать чтоб имела доступ? { Так это ты вобще написал? Ничего подозрительного в своем коде не замечаешь? Конкретно тут: class List { ….. private: Item *findEnd(); Item *first; } Item *findEnd() { Item *curr; curr=first; ….. } по-моему, надо в функцию *findEnd() давать какой-то параметр класса List [например *findEnd(List a)], а потом уже curr=a.first. Это единственное, что вызывает у меня подозрения. Но вообще-то я эту функцию у препода списал, поэтому не думал, что где-то тут серьёзная ошибка. quote:
ORIGINAL: _SaZ_ quote:
ORIGINAL: t3rmin41 К теме о "Рано ты за ООП взялся, начни с теории лучше": не ошибается только тот, кто ничего не делает. С твоим подходом ты будешь очень долго ошибаться. Не стоит изобретать велосипед, когда есть отлаженные методики обучения. Думаю ты не Крис Касперски, который с помощью одной лишь debug.com за 3 месяца освоил язык ассемблера. В общем лучше почитать книжки, чем лишний раз грузить нас глупыми вопросами. Не стану полемизировать насчёт глупых вопросов и чтения книжек, скажу только, что я редко повторяю одну и ту же ошибку дважды.
|
|
|
RE: Список в С++: где ошибка? - 2008-12-22 13:45:09.233333
|
|
|
Archivarius
Сообщений: 164
Оценки: 0
Присоединился: 2008-10-26 00:16:25.630000
|
quote:
ORIGINAL: t3rmin41 по-моему, надо в функцию *findEnd() ….. Вот именно, что это у тебя получается не метод класса, а функция. Абсолютно никаким образом не связанная с классом List. Посмотри на другие методы, чем их объявление отличается?
|
|
|
RE: Список в С++: где ошибка? - 2008-12-22 14:31:43.580000
|
|
|
t3rmin41
Сообщений: 245
Оценки: 0
Присоединился: 2007-11-12 14:06:01.393333
|
Да, точно. Item* List::findEnd(); надо объявлять. Только теперь почему-то программа не может корректно завершиться
|
|
|
RE: Список в С++: где ошибка? - 2008-12-22 15:12:08.030000
|
|
|
_SaZ_
Сообщений: 4329
Оценки: 398
Присоединился: 2008-01-30 02:18:05.553333
|
Потому что надо с памятью нормально работать.
|
|
|
RE: Список в С++: где ошибка? - 2008-12-22 22:32:35.456666
|
|
|
t3rmin41
Сообщений: 245
Оценки: 0
Присоединился: 2007-11-12 14:06:01.393333
|
Вот, переписал по-другому структуру списка. Мои функции-методы только cut, addvalues и add, всё остальное писал препод, но всё равно функции-методы append не работают. В принципе, непринципиально, 9 (по 10 бальной системе) я уже получил, но всё же, почему они не работают? С первого взгляда всё так, как надо написано… препод наверно, где-то совершил ошибку, только вот где? Вот код:
#include <assert.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
class Item
{
friend class List;
private:
Item(double value, Item *item=0) {val=value; next=item; };
double val;
Item *next;
};
class List
{
public:
List(double a=0);
List(double *, int);
List(List&);
void out(char *);
~List() { remove(); };
int length() {return im; };
void remove();
void remove(int);
void append(double);
void append(double *, int);
void add(double);
void addvalues(double *, int);
void cut(int);
double &operator [](int);
private:
Item *findEnd();
Item *first;
int im;
};
List::List(double a)
{
Item *curr=new Item(a);
assert(curr!=0);
first=curr;
im=1;
}
List::List(double *mas, int num)
{
int i; Item *prev,*curr;
curr=new Item(mas[0]);
assert(curr!=0);
prev=first=curr;
for(i=1; i<num; i++)
{
curr = new Item(mas[i]);
assert(curr!=0);
prev->next=curr;
prev=curr;
}
im=num;
}
List::List(List &lem)
{
int i; Item *curr,*prev,*pt;
pt=lem.first;
curr = new Item(pt-> val);
assert(curr!=0);
prev=first=curr;
for(i=1; i<lem.im; i++)
{
pt=pt->next;
curr=new Item(pt->val);
assert(curr!=0);
prev->next=curr;
prev=curr;
}
im=lem.im;
}
void List::remove()
{
Item *pt=first;
while(pt)
{
Item *pnt=pt;
pt=pt->next;
delete pnt;
}
im=0;
}
Item* List::findEnd()
{
Item *curr;
curr=first;
while(curr->next);
curr=curr->next;
return curr;
}
void List::remove(int num)
{
assert(num<im);
int i=0;
Item *prev,*curr;
im-=num;
prev=curr=first;
while (i<im)
{
prev=curr;
curr=curr->next;
i++;
}
while(curr)
{
Item *pnt=curr;
curr=curr->next;
delete pnt;
}
prev->next=0;
}
void List::out(char *name)
{
printf("%s im=%d\n",name,im);
Item *curr; int num=0; curr=first;
while (curr)
{
printf("%3.f ",curr->val);
curr=curr->next;
num++;
if ((num%5)==0)
printf("\n");
}
printf("\n");
}
void List::append(double value)
{
Item *curr;
Item *pt=new Item(value);
assert(pt!=0);
curr=findEnd();
curr->next=pt;
im++;
}
void List::append(double *mas, int num)
{
if (num<=0) return;
int i; Item *curr,*prev;
prev=findEnd();
for(i=0; i<num; i++)
{
curr=new Item(mas[i]);
assert(curr!=0);
prev->next=curr;
prev=curr;
}
im+=num;
}
double &List::operator [](int num)
{
Item *curr, *prev;
int i,ifin;
assert(num>=0);
if (num<im)
{
prev=first;
while(num>0)
{
prev=prev->next;
num--;
}
}
else
{
prev=findEnd();
ifin=num-im+1;
for(i=0; i<ifin; i++)
{
curr=new Item(0.0);
assert(curr!=0);
prev->next=curr;
prev=curr;
}
im=num+1;
}
return prev->val;
}
void List::add(double value)
{
Item *curr;
Item *pt=new Item(value);
curr=first;
pt->next=curr;
this->first=pt;
this->im++;
}
void List::addvalues(double *mas, int n)
{
int i;
for (i=n-1; i>=0; i--)
{
this->add(mas[i]);
}
}
void List::cut(int num)
{
assert(num<im);
Item *curr;
for(int i=0; i<num; i++)
{
curr=first;
curr=curr->next;
delete first;
first=curr;
im--;
}
}
main()
{
double a[]={1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
double b[]={11.0, 12.0, 13.0, 14.0, 15.0};
clrscr();
List list1(a, 8);
list1.out("list1");
list1.remove(3);
list1.out("list1 after truncation");
//list1.append(3.0);
//list1.out("list1 after append(3.0)");
list1.cut(2);
list1.out("list1 after cut(2)");
list1.addvalues(b,3);
list1.out("list1 after addvalues(b,3)");
getch();
return 0;
}
|
|
|
RE: Список в С++: где ошибка? - 2008-12-22 22:38:12.380000
|
|
|
Denaturat
Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
|
quote:
ORIGINAL: t3rmin41 Мои функции-методы только cut, addvalues и add, всё остальное писал препод препода публично четвертовать
|
|
|
RE: Список в С++: где ошибка? - 2008-12-23 00:40:48.410000
|
|
|
t3rmin41
Сообщений: 245
Оценки: 0
Присоединился: 2007-11-12 14:06:01.393333
|
quote:
ORIGINAL: Denaturat quote:
ORIGINAL: t3rmin41 Мои функции-методы только cut, addvalues и add, всё остальное писал препод препода публично четвертовать Если так, то только в следующем семестре это возможно :)
|
|
|
RE: Список в С++: где ошибка? - 2008-12-23 01:05:36.610000
|
|
|
Denaturat
Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
|
quote:
ORIGINAL: t3rmin41 Если так, то только в следующем семестре это возможно :) передай ему что это не C++, не ООП, и, вообще говоря, не список. а ещё не забудь сказать, что (cons 'vsl ('not dead))
|
|
|
RE: Список в С++: где ошибка? - 2008-12-23 14:53:42.883333
|
|
|
t3rmin41
Сообщений: 245
Оценки: 0
Присоединился: 2007-11-12 14:06:01.393333
|
quote:
ORIGINAL: Denaturat quote:
ORIGINAL: t3rmin41 Если так, то только в следующем семестре это возможно :) передай ему что это не C++, не ООП, и, вообще говоря, не список. а ещё не забудь сказать, что (cons 'vsl ('not dead)) Я предпочитаю подкреплять свои слова аргументами. Поэтому попрошу и тебя тоже самое сделать :) Почему это не С++, не ООП? И что такое cons 'vsl ('not dead))?
|
|
|
RE: Список в С++: где ошибка? - 2008-12-23 16:02:12.180000
|
|
|
Denaturat
Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
|
quote:
ORIGINAL: t3rmin41 Почему это не С++ например потому, что в C++ есть ключевое слово const, а используемый оператор new никогда не возвращает нулевого указателя (он кидает исключение). кроме того в этом языке есть, например, список инициализации, и ключевое слово explicit для одноаргументных конструкторов. достаточно? то, что используется исключительно C STDLib (а не C++ STDLib) может ещё и оправдано учебными целями, но вот вышеперечисленное - никоим образом quote:
ORIGINAL: t3rmin41 не ООП? ну, честно говоря ООП здесь не нужно вообще; здесь нужно ОБП, объектно-базированное программирование - тебе нужно описать абстрактный тип данных "список". средств для этого у тебя не так уж и много, но ключевое - инкапсуляция - здесь нарушается. Item не должен быть friend-классом, это не тот уровень абстракции - он должен быть локальным классом, объявленный в private-секции List (а лучше - структурой, на кой чёрт там вообще класс, это же cons-ячейка). интерфейс не соответствует списочной структуре: что за operator[]? нет у списка такого селектора, он неэффективен и поэтому не нужен. всё остальное - в том же духе quote:
ORIGINAL: t3rmin41 И что такое cons 'vsl ('not dead))? а это ты либо сам со временем поймёшь, либо оно тебе и не надо
|
|
|
RE: Список в С++: где ошибка? - 2008-12-23 18:12:00.120000
|
|
|
t3rmin41
Сообщений: 245
Оценки: 0
Присоединился: 2007-11-12 14:06:01.393333
|
quote:
ORIGINAL: Denaturat quote:
ORIGINAL: t3rmin41 Почему это не С++ например потому, что в C++ есть ключевое слово const, а используемый оператор new никогда не возвращает нулевого указателя (он кидает исключение). кроме того в этом языке есть, например, список инициализации, и ключевое слово explicit для одноаргументных конструкторов. достаточно? то, что используется исключительно C STDLib (а не C++ STDLib) может ещё и оправдано учебными целями, но вот вышеперечисленное - никоим образом Может, не const, а constructor? const вроде как для константы используется (наряду с #define). Если ты это имел в виду. Это первое. Во-вторых, я не знаю что там возвращает new, препод объяснял, что new создаёт новый (или указатель) объект в памяти, называемой HEAP, если не удалось создать, то указатель будет указывать в NULL. За что купил, за то и продаю (эт я про себя :)). quote:
quote:
ORIGINAL: t3rmin41 не ООП? ну, честно говоря ООП здесь не нужно вообще; здесь нужно ОБП, объектно-базированное программирование - тебе нужно описать абстрактный тип данных "список". средств для этого у тебя не так уж и много, но ключевое - инкапсуляция - здесь нарушается. Item не должен быть friend-классом, это не тот уровень абстракции - он должен быть локальным классом, объявленный в private-секции List (а лучше - структурой, на кой чёрт там вообще класс, это же cons-ячейка). интерфейс не соответствует списочной структуре: что за operator[]? нет у списка такого селектора, он неэффективен и поэтому не нужен. всё остальное - в том же духе Ну со структурой-то понятно, в принципе, и в самом деле класс Item не имеет никаких методов (имеет правда, один конструктор, но по идее можно и без него обойтись), тут ты прав. А operator [] я могу объяснить, зачем нужен. Он нужен для того, чтобы продлить массив, как-то: если в списке 5 элементов, а пишешь например list1[7]=9.0, то будет сделано как MathCAD или где-там, не помню: 5 элементов останутся, а вместо 6-ого запишется 0.0, а 7-ой как раз будет равен 9.0. Такая идея. quote:
quote:
ORIGINAL: t3rmin41 И что такое cons 'vsl ('not dead))? а это ты либо сам со временем поймёшь, либо оно тебе и не надо ОК, как скажешь :) Только мы честно говоря, от темы отошли. Есть конкретный вопрос - почему не работает ни один из append'ов?
|
|
|
RE: Список в С++: где ошибка? - 2008-12-23 18:40:25.276666
|
|
|
Denaturat
Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
|
quote:
ORIGINAL: t3rmin41 const вроде как для константы используется (наряду с #define). Если ты это имел в виду. Это первое можно было просто сказать что ты не знаешь, для чего в C++ квалификатор const. ну так почитай, про константные аргументы функций почитай, про константные указатели, указатели на константу; про константные методы и квалификатор mutable (физическую и логическую константность); если не надоест - про идемпотентность и мутабельные данные вообще quote:
ORIGINAL: t3rmin41 Во-вторых, я не знаю что там возвращает new, препод объяснял, что new создаёт новый (или указатель) объект в памяти, называемой HEAP, если не удалось создать, то указатель будет указывать в NULL. За что купил, за то и продаю (эт я про себя :)). итого как работает new ты тоже не знаешь. позволь немного поясню…обычный operator new выполняет несколько последовательных операций - вызывает operator operator new (да, так всё страшно), который возвращает ему указатель на область выделенной памяти (может сделать это с помощью malloc, но вообще говоря не обязан); конструирует объект в соответствии с аргументами вызванного конструктора; размещает объект в выделенной под него области, и возвращает указатель, приведённый к типу размещённого объекта. в случае, если память выделить не удалось (или конструктор объекта бросил исключение), operator new сам бросает исключение - нормальная работа программы прерывается. нулевого указателя new не возвращает никогда вообще говоря это не единственная форма работы operator new - есть ещё new, не бросающий исключений, размещающий new (который не выделяет память, т.е. не вызывает operator operator new); есть new для массивов, который работает ещё более иначе - по всем этим увлекательным темам читай Страуструпа и Саттера. вы используете в коде самый обычный, классический new, поэтому имейте в виду - он себя будет вести именно классически, т.е. по стандарту кстати, совсем не обязательно new выделяет память именно в куче (heap): operator operator new можно перегрузить под свои нужды; как, впрочем, и сам operator new quote:
ORIGINAL: t3rmin41 Ну со структурой-то понятно, в принципе, и в самом деле класс Item не имеет никаких методов (имеет правда, один конструктор, но по идее можно и без него обойтись), тут ты прав. А operator [] я могу объяснить, зачем нужен. Он нужен для того, чтобы продлить массив, как-то: если в списке 5 элементов, а пишешь например list1[7]=9.0, то будет сделано как MathCAD или где-там, не помню: 5 элементов останутся, а вместо 6-ого запишется 0.0, а 7-ой как раз будет равен 9.0. Такая идея. интерфейс должен быть таким, чтобы объект было легко использовать правильно, и трудно - неправильно; operator[] есть оператор индексирования, он просто-таки напрашивается для выборки элементов из списка - а это есть зло. то, о чём ты говоришь - это уже более сложная структура данных чем список, и по-хорошему её интерфейс должен быть весьма отличен от имеющегося quote:
ORIGINAL: t3rmin41 Только мы честно говоря, от темы отошли. Есть конкретный вопрос - почему не работает ни один из append'ов? понятия не имею. тебя не научили отлаживать код? так самое время научиться!
|
|
|
RE: Список в С++: где ошибка? - 2008-12-23 19:00:04.010000
|
|
|
t3rmin41
Сообщений: 245
Оценки: 0
Присоединился: 2007-11-12 14:06:01.393333
|
Ладно, раз никто не может и не хочет найти ошибку, я сам её нашёл - в функции Item* List::findEnd() есть такое
while(curr->next);
curr=curr->next;
т.е. надо после while убрать точку с запятой и всё пойдёт как надо. Ура :)
|
|
|
|
|