Własna implementacja listy - gdzie tu jest błąd?

0

Witam, chcę zaimplementować własną listę, gdzie ja tutaj mam błąd, że podany niżej kod nie działa. Chodzi głównie o to, że np. jak mam w konstruktorze "first->..." to IDE nie wykrywa składników first, czyli "next" i "value". Gdy zamieniam klasę z szablonu na normalną, jest ok, ale gdy jest szablonem, to jest powyższy problem.

 

#include <iostream>
using namespace std;

template <typename value_type>
class List
{
private:
	// typy
	struct Node	{int value; struct Node * next;};
public:
	// konstruktory, destruktor
	List(int n=0);
	// metody publiczne
	void print();
private:
	// atrybuty
	int size;
	Node * first;
	struct Node * last;
};

template <typename value_type>
List<value_type>::List(int n=0)
{
	first=NULL;
	last=NULL;

	if (n>0)
	{
		first=new Node;
		**first->next=NULL;**
		last=first;
		for (int i=0;i<n;++i)
		{
			last->next=new Node;
			last=last->next;
		}
	}
}

template <typename value_type>
void List<value_type>::print()
{
	Node * temp=first;
	while (temp!=NULL)
	{
		cout<<temp->value<<" ";
		temp=temp->next;
	}
}

Z góry wielkie dzięki za pomoc! :)

0
matieti napisał(a):

IDE nie wykrywa składników first
Hmm... niech zgadnę, Dev-Cpp?

0

Visual Studio 2010 :P

0

A co, wam wyskakują te propozycje składników?

0

Ale to masz problem z programem, że coś nie działa, czy z tym, że środowisko nie wyświetla podpowiedzi?

0

Nie no wydaje mi się, że problem jest gdzieś w składni mojego "programu" :P

0

Jeżeli używasz VS2010 i C++, to problem może leżeć po stronie środowiska. Bo ja Twój kod skopiowałem i się ładnie kompiluje (wysypuje się w print() podczas działania, ale to zaraz popatrzę co jest nie tak). Natomiast to że środowisko nie pokazuje podpowiedzi (u mnie również) nie oznacza, że coś skopałeś (tym bardziej że się kompiluje). A w tym wypadku jest trochę winą Microsoftu, bo właśnie w VS2010 odpuścili sobie IntelliSense w C++ i są problemy w niektórych momentach z pokazywaniem co jaka klasa zawiera. To sam MS się przyznał do błędu, więc to nie wina kodu.

0

teraz już niestety przy funkcji "operator[]" wyskakuje błąd kompilacji, wiecie może co jest nie tak?

 
#include <iostream>
using namespace std;

template <typename value_type>
class List
{
public:
	// typy
	struct Node	{int value; struct Node * next;};
	// konstruktory, destruktor
	List(int n=0);
	// metody publiczne
	void print();
	Node * operator[](int n);
private:
	// atrybuty
	int size;
	Node * first;
	struct Node * last;
};

template <typename value_type>
List<value_type>::List(int n=0)
{
	first=NULL;
	last=NULL;

	if (n>0)
	{
		first=new Node;
		first->next=NULL;
		last=first;
		for (int i=0;i<n;++i)
		{
			last->next=new Node;
			last=last->next;
		}
	}
}

template <typename value_type>
void List<value_type>::print()
{
	Node * temp=first;
	while (temp!=NULL)
	{
		cout<<temp->value<<" ";
		temp=temp->next;
	}
}

template <typename value_type>
List<value_type>::Node * List<value_type>::operator[](int n)
{
	Node * temp=first;
	for (int i=1;i<n;++i)
		temp=temp->next;
	return temp;
}

0

Błąd wysypywania się przy print jest spowodowany tym, że jeżeli do konstruktora przekażesz n > 0 to ostatni element nie będzie miał ustawionego pola next na NULL, tylko na jakieś śmieci. Musi dać last->next = NULL; zaraz za tą pętlą tworzącą elementy.

Co do podpowiadania składni to się nie przejmuj. Intelisense nie zawsze sobie radzi z szablonami, przynajmniej jak jeszcze nie istnieje żadna ich konkretyzacja(chociaż to nie do końca tak jest).

@lena(R): MS odpuścił sobie intelisense nie tyle w c++ co w c++/cli

0

No to masz klasyczny błąd przy tworzeniu nowych elementów w liście. Tu nie chodzi o print(), ale o konstruktor i pętle. Mój konstruktor wygląda tak:

template <typename value_type>
List<value_type>::List(int n=0)
{
        first=NULL;
        last=NULL;
 
        if (n>0)
        {
                first=new Node;
                first->next=NULL;
                last=first;
                for (int i=1;i<n;++i)	// i=0  =>  i=1 , nie ma sensu gdy i==0, bo wtedy tworzy pierwszy (zerowy) element listy, a to zrobiłeś powyżej. Więc jeżeli n > 1, to petla się obróci i doda nowe elementy, w przeciwnym wypadku jest to niepotrzebne.
                {
                    last->next=new Node;
					last->next->next = NULL;	// nigdzie nie NULLowałeś nexta nowo utworzonego elementu, przez co warunek w print nigdy sie nie zakonczyl i program sie wysypywal bo probowal dostac sie do nie zainicjalizowanej pamieci.
                    last=last->next;
                }
        }
}

Chodziło o nullowanie elementu, aby zapewnić sobie koniec listy.

Rozumiem że ten kod, to jest taki test. Bo jak na razie, nie mozesz ani wstawiać, ani usuwać nic. Nie zwalniasz też pamięci w destruktorze (którego w ogóle tutaj nie masz).

0

Co do błędu kompilacji związanym z tym operatorem [] to zmień tą linijkę:
List<value_type>::Node * List<value_type>::operator[](int n)
na
typename List<value_type>::Node * List<value_type>::operator[](int n)

0

Pamiętaj też, żeby jakoś zabezpieczyć tą funkcję "operator[]", przed podaniem indeksu który wykracza poza zakres listy. Bo znowu się sypnie.

0

A mam do was prośbę. Moglibyście mi wytłumaczyć, czemu przed każdą inną metoda, nie potrzebowałem tego słówka typename, a w tej "operator[]" potrzebuję "typename" ?

0

Myślałem, że już składnię C++ mam mniej więcej opanowaną, a tu ciągle takie "nielogiczne" rzeczy wychodza zawsze, jak teraz z tym typename, przecież typename używa się pomiedzy <> aby wskazać, że jest to typ generyczny, a nie typ stały jak int :P Przynajmniej jak tak myślałem.

0

Tak, ale mógłby mi ktoś wytłumaczyć to z tym dziwnie użytym "typename"?

0

Niestety szablony w C++ są mocno zagmatwane, zresztą jak połowa tego języka. Ta sytuacja jest związana z gramatyką tego języka.
Tu jest to wyjaśnione: http://blogs.msdn.com/b/slippman/archive/2004/08/11/212768.aspx, artykuł jest o C++/CLI, ale myślę, że w równym stopniu odnosi się do natywnego C++.

1 użytkowników online, w tym zalogowanych: 0, gości: 1