[pascal] wskazniki, tablice dynamiczne

0

Jak utworzyc liste na bazie rekordu, odwolac sie do dowolnego elementu, a na koniec wywalic to wszystko z pamieci.
[???]

slimy
piotrexxx@pf.pl

0

Nie dam głowy, że dobrze, ale coś takiego powinno być:

type TElement = record
ID: Word;
Przed, Po: Pointer;
{jakieś inne właściowści}
end;

PElement = TElement;

function DodajElement(Lista: PElement): PElement;
var
Nowy: PElement;
begin
New(Nowy);
Lista</sup>.Po := Nowy;
Nowy.ID := Lista.ID + 1;
DodajElement := Nowy;
end;

function ZnajdzElement(Lista: PElement; Nr: Word): PElement;
var
i: Word;
Pom: PElement;
begin
New(Pom);
Pom := Lista;
if Pom.ID &gt Nr then
for i := Pom
.ID downto Nr do
Pom := Pom.Przed
else
for i := Pom
.ID o Nr do
Pom := Pom^.Po;
ZnajdzElement := Pom;
end;

var
Lista: PElement;
begin
New(Lista);
Lista.Przed := nil;
Lista.Po := nil;
Lista.ID := 0;
{Dodawanie elementów}
Lista := DodajElement(Lista);
ZnajdzElement(Lista, Nr);
end;
--Jest jeszcze jeden błąd ... :)

Apel: Piszcie w tematach o jaki język programowania chodzi np. : [Delphi], [C++], itp.

0

Fragment referatu pisałem na zaliczenie o zmiennych wskaźnikowych

Dostępem programów do pamięci steruje system operacyjny (DOS lub windows). W momencie uruchomienia programu system operacyjny przydziela pamięć (alokuje) na jego kod i zmienne statyczne,(czyli np. var x:integer;y:real). Jeżeli braknie nam pamięci na te zmienne program po prostu się nie uruchomi. Pamięć przydzielona na zmienne statyczne pozostaje przez nie zajęta aż do końca ich pracy. I nic z tym nie możemy zrobić.
         Nakłada to na programistę poważne ograniczenia. Już w momencie pisania programu musimy przewidzieć maksymalne zapotrzebowanie na pamięć(np. chcemy umieścić w tablicy dane naszych znajomych, musimy z góry założyć ilu będzie w niej znajomych, gdyż w trakcie trwania nie możemy zmienić rozmiaru tablicy statycznej). Oczywiście możemy to obejść podając bardzo duże rozmiary tablicy, lecz nie jest to zbyt dobry pomysł. Jeśli jeden rekord danych o znajomych zajmie np. 1kB, a tablice określimy na milion rekordów to program przy starcie poprosi 1 GB pamięci:). Aby uniknąć takich ograniczeń wymyślono zmienne dynamiczne. Nie alokują się w pamięci programu zaraz przy starcie programu, lecz proszą o pamięć tylko w tym momencie, kiedy jest to potrzebne. Kiedy skończymy korzystać z takiej zmiennej możemy ją usunąć z pamięci. Do zmiennych dynamicznych mamy dostęp jedynie przez ich adres, nazywany powszechnie wskaźnikiem.

Wskaźnik(ang.pointer), czyli inaczej zmienna wskazująca, to nie jest ani liczba, ani tekst, a nie też wartość logiczna. Wskaźnik to wskaźnik, czyli na coś wskazuje:). A na co wskazuje? Otóż wskazuje na inne zmienne np. na zmienne typu integer, real, array.
Inaczej mówiąc: wskaźnik to komórka w pamięci, w której będzie przechowywany adres do zmiennej, na którą wskazuje wskaźnik.
Przykład
var
p:pointer; {wskanik=nil}
c:integer;
begin
c:=-1313;
p:=@c; {p wskazuje miejsce zmiennej c w pamięci}

Writeln(integer(p));
{również można podać inny typ}
Writeln(word(p
));
{to już wyświetli co innego..}
end.

Początkowo wskaźnik przyjmuje wartość nil co oznacza że na nic nie wskazuje.
Aby uzyskać miejsce w którym znajduje się zmienna a nie jej wartość należy dodać przed nią małpkę. Jeśli chcemy odczytać wartość wskazaną przez zmienną wskaźnikową dodajemy po wskaźniku znak Writeln(integer(p));

Jako, że wskaźnik typu pointer nie zawiera informacji na temat typu zmiennej na którą wskazuje powinieneś powiedzieć pascalowi jaki typ chcesz odczytać. Po prostu pisze się typ(wskaźnik).

Oprócz wskaźników ogólnych, które mogą wskazywać na dowolny typ istnieją także wskaźniki wskazujące na jakiś konkretny typ.Tworzy się je dodając przed nazwą typu znak </sup>:

var p:^integer;
c:integer;
begin
c:=-1313;
p:=@c;

Mają one między innymi tą zaletę, że nie trzeba już informować pascala, na co wskazują:

writeln(p);
end.

Jeśli chcemy wykorzystać zmienne dynamiczne do innych celów niż wskazywanie miejsca w pamięci zmiennych statycznych należy przydzielić jej miejsce w pamięci, które możemy wykorzystywać. Robi się to następująco. New(nazwa_zmiennej);

Przykład

Program wskaznik;

var
wsk : </sup>integer;

begin
New(wsk); {przydzielenie pamięci dla zmiennej }
wsk:=7;
writeln(wsk
);
Dispose(wsk); {zwolnienie pamieci}
end.

W momencie zakończenia pracy na zmiennych wskaźnikowych należy zwolnić miejsce w pamięci zajmowane przez daną. Służy do tego polecenie Dispose(nazwa_zmiennej);

W pascalu kompilator przydziela na zmienne 64kB. Aby uzyskać informacje o ilości wolnej pamięci używamy funkcji MemAvail

Poniższy przykład pokazuje jak zadeklarować dane o rozmiarze większym niż 64 kB.

type X = array[1..300] of byte; {OK}
pola = array[1..300] of X; {I wszystko jasne :-}
var pole:pola;
i:integer;
begin
if MemAvail&lt90000 then {sprawdza czy jest wystarczająca ilość pamięci}
begin
writeln('Brak Pamięci');
halt(1); {kończy program}
end;
for i:=1 to 300 do
new(pole[i]); {przydzielanie pamięci}
pole[100]
.[100]:=2; {odwołanie do jednej z komórek}
for i:=1 to 300 do
dispose(pole[i]); {zwalnianie pamięci}
end.

Pamięć, podobnie jak twardy dysk, może być zfragmentowana. Jeśli zajmiemy pamięć kilkoma zmiennymi, a następnie zwolnimy część z nich może dojść do sytuacji, w której pamięć konwencjonalna będzie wyglądać jak ser szwajcarski: zmienna-wolne miejsce-zmienna-zmienna-wolne miejsce... Będzie to
dosyć kłopotliwe, gdyż mimo, ze wolnej pamięci będzie np. 400 kB to największy blok wolnej pamięci może być wiele mniejszy, a co za tym idzie możemy nie mieć miejsca na zmienna. Funkcja MemAvail podaje sumę wszystkich wolnych bloków pamięci, wiec istnieje prawdopodobieństwo, ze nasza duża zmienna może nie zmieścić się w pamięci, mimo, ze MemAvail zwraca wartość większa niż jej objętość. Jeśli chcesz odczytać wielkość największego bloku pamięci konwencjonalnej powinieneś użyć funkcji MaxAvail

O to program na listy 2 kierunkowe który był do tego dołączony
program lista;
uses crt;
type elisty = Welisty; {wskaznik do ogniwa listy}

 Welisty = record
   nastepny : elisty;  {wskaznik na el nastepny}
   dana     : integer;
 end;

var
poczatek : elisty;
klawisz : char;
liczba : integer;

procedure dodaj(cos: integer);
var
nowy: elisty;
begin
new(nowy);
nowy</sup>.dana:=cos;
nowy.nastepny:=poczatek.nastepny;
poczatek.nastepny:=nowy;
end;

procedure wypisz;
var
element : elisty;
dana : integer;
begin
while poczatek</sup>.nastepny &lt&gt nil do
begin
element:=poczatek^.nastepny; {element pobierany - pierwszy el listy}
dana:=element^.dana;
write(dana,' ');
poczatek.nastepny:=element.nastepny; {2 element staje sie pierwszym}
end;
writeln('To juz koniec listy :(' );
end;

procedure usun; {usuwa cala liste z pamieci komputera}
var
bierzacy,usuwany : elisty ;
begin
bierzacy:=poczatek; {zaczynamy od poczatku }
while bierzacy &lt&gt nil do { i idziemy do konca}
begin
usuwany:=bierzacy; {usuwany = element do usuniecia}
bierzacy:=bierzacy^.nastepny;
dispose(usuwany);
end;
end;

begin

clrscr;

writeln('d- dodaj element do listy');
writeln('w- wypisz elementy listy');
writeln('u- usun liste');
writeln('q- wyjscie');

poczatek:=nil; {lista jest pusta}

repeat klawisz:=upcase(readkey);
case klawisz of
'D' : begin
write('Podaj liczbe '); readln(liczba);
dodaj(liczba);
end;
'W' : wypisz;
'U' : usun;
end
until
klawisz='Q';
halt(2);
end.

Powinno pomóc
--Pozdrowienia [cya]
Waldi Koronowo
goldcar1@wp.pl
Zdarza sie że pisze e przed i nie zwracajcie uwagi na to:D

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