Lista jednokierunkowa - jak się zabrać za pisanie?

0

Cześć wszystkim :)
Mam za zadanie zrobić prostą bazę danych w Delphi.
Ogólnie mam już dużo materiałów gotowych odnośnie listy jednokierunkowej, poza tym tutaj też był artykuł odnośnie implementacji.
Jednakże za każdym razem gdy próbuję coś napisać to nie ma to składu.
Moje pytanko czy możecie dać jakieś podpowiedzi jak się za to zabrać, co robić krok po kroku, jakieś przydatne strony.
Dużo jest suchych poradników a mi by się przydał typu jakiegoś łatwego zadania żeby na jego podstawie zobaczyć o co chodzi w temacie.
Jak już pisałem kodów jest dużo ale zastosowań brak, możecie wytłumaczyć jak zaimplementować te kody :https://4programmers.net/Delphi/Lista_jednokierunkowa do bazy danych o takich parametrach

 TAddress = packed record
    Name : String[30];
    Tel1 : Integer;
    Tel2 : Integer;
    Mail : String[30];
  end;

Tematu nie rozumiem za bardzo, samo wklejanie kodów za wiele mi nie da bo trzeba to jeszcze jakoś ogarnąć żeby taka lista została wypisana w Memo, ListBoxie czy Listview itp.
Może ktoś wytłumaczy dokładnie od podstaw co i jak?

0

Pisz czego nie rozumiesz, a postaram się pomóc;

PS: Podaj nazwę środowiska, którego używasz do pisania i kompilowania kodu.

0

Program pisany jest w Delphi, w formie vcl czyli no jakoś musi to wyglądać. Powiem tak, nie rozumiem całego założenie listy jednkierunkowej. Są gotowce na procedury typu dodaj, usuń, wczytaj itp. Ale zacznijmy od początku, jak mam zadeklarować wartości które będę mi potrzebne, jak podane wyzej, nazwa, nr tel. Idąc dalej jak używać tych gotowcow, coś trzeba od siebie dopisywać, i jeszcze jedno, jak zrobić to w ten sposób aby po odpaleniu programu od razu otwierał się plik z listą a jeśli go nie ma to żeby z automatu się tworzył. Próbując tych wszystkich kodów i je sklejając to niby program się kompiluje ale nie mam pojęcia jak zmodyfikować gotowce żeby rekordy wyswietlaly się w jakiejs formatce, jaka będzie najlepsza tak wgl? Sprawy typu stworzenia nowego formularza przy dodawaniu.

0

Program pisany jest w Delphi, w formie vcl czyli no jakoś musi to wyglądać.

W którym Delphi? Podaj dokładną wersję;

jak mam zadeklarować wartości które będę mi potrzebne, jak podane wyzej, nazwa, nr tel.

Dane masz już zadeklarowane, więc nie rozumiem czego tutaj nie wiesz; Podstawa przy listach to deklaracja typu danych, które będą w węzłach przechowywane, a także struktury samego węzła; Przykład:

TAddress = record
  Name: String;
  Mail: String;
  Tel1: String;
  Tel2: String;
end;

Wszystkie pola spokojnie moga być łańcuchami znaków, o długości nieograniczonej, bo samo ograniczanie nie jest nikomu potrzebne; Taki rekord też da się zapisać do pliku (dowolnego, również binarnego); Poza tym numer telefonu lepiej aby był ciągiem znaków - będzie możliwe przechowywanie w nim dowolnego numeru, łącznie ze znakami dodatkowymi, jak + czy ();

Druga rzecz to deklaracja rekordu z danymi pojedynczego węzła oraz wskaźnika na taki rekord:

type
  PListNode = ^TListNode;
  TListNode = record
    NextNode: PListNode;
    Address: TAddress;
  end;

Pole Address przechowywać będzie dane, natomiast NextNode zawierać będzie wskaźnik na kolejny węzeł listy;

Jeśli Twoje przyszłe funkcje/procedury nie będą używać w parametrach typu TAddress, deklaracja jego jako oddzielnego również nie jest wymagana, dzięki czemu całość sprowadzi się do poniższego:

type
  PListNode = ^TListNode;
  TListNode = record
    NextNode: PListNode;
    Address: record
      Name: String;
      Mail: String;
      Tel1: String;
      Tel2: String;
    end;
  end;

Idąc dalej jak używać tych gotowcow, coś trzeba od siebie dopisywać

Normalnie - czytać ze zrozumieniem i przystosowywać kod pod własne wymagania;

i jeszcze jedno, jak zrobić to w ten sposób aby po odpaleniu programu od razu otwierał się plik z listą a jeśli go nie ma to żeby z automatu się tworzył.

Powoli, najpierw napisz sobie procedurę tworzące listę w pamięci, dodającą i usuwającą węzeł, a także zwalniającą listę z pamięci, a dopiero później myśl o plikach i innych dodatkowych funkcjach;

Próbując tych wszystkich kodów i je sklejając to niby program się kompiluje ale nie mam pojęcia jak zmodyfikować gotowce żeby rekordy wyswietlaly się w jakiejs formatce

Jak nie rozumiesz danego kodu to nic Ci nie da wklejenie go do edytora kodu i skompilowanie.

0

Wersja to Delphi XE8. Z racji tego ze póki co brak mi trochę czasu to chciałbym ogarnąć to chociaż teoretycznie. Powiedzmy ze wykorzystuje deklaracje, które mi podales za co dziękuję, teraz przystosowuje implementację listy pod swoje deklaracje, robię zgodnie z tym co na stronie podanej wcześniej i co robię dalej? Procedury i funkcje zrobione, działają. Teraz trzeba się zabrać za stworzenie listy, wczytanie jej w okienko

1

Skoro to ma być napisane przy użyciu VCL to zapoznaj się ze StringGrid bo może ci się przydać.

Mój artykuł znalazłeś sam więc jak zrobić listę jednokierunkową już wiesz.

Ten program pod względem wyglądu można napisać na milion sposobów, ale wnioskując po twoich pytaniach zainteresuj się też z PageControl żeby nie bawić się w program z milionem form.

Prosta "baza danych" czyli pewnie "dodaj", "usuń", "wyszukaj" i "wyświetl". Wszystko masz zaimplementowane w liście z artykułu, no może wyszukiwanie trzeba by poprawić by wyszukało wszystkie elementy pasujące a nie pierwszy napotkany.

Jeśli chcesz szczegółowe wskazówki to musisz pokazać co już zrobiłeś i wtedy ewentualnie możemy ocenić twój kod i naprowadzić cię na optymalne rozwiązanie.

0
Andrzej_Kowalski

Z racji tego ze póki co brak mi trochę czasu to chciałbym ogarnąć to chociaż teoretycznie.

Teoria znajduje się np. na wikipedii, zagadnienie jest dobrze opisane (wersja angielska), więc nie powinieneś mieć problemu ze zrozumieniem; Teoria to wiedza na temat tego czym jest lista jednokierunkowa, z czego się składa (jaka jest jej budowa), jak się ją tworzy, zwalnia z pamięci, iteruje po węzłach; Wszystko jest ładnie opisane, więc poczytaj;

Procedury i funkcje zrobione, działają. Teraz trzeba się zabrać za stworzenie listy, wczytanie jej w okienko

Do stworzenia listy i jej uzupełnienia też musisz mieć odpowiednie metody/procedury; Natomiast wyświetlenie zawartości listy to nic innego jak przeiterowanie po wszystkich węzłach, sukcesywne pobieranie danych z węzłów i dodawanie do jakiegoś komponentu za pomocą odpowiedniej metody tego komponentu (np. ListBox.Items.Add);

Żeby napisać ten program, pasuje mieć opanowane przynajmniej podstawy programowania strukturalnego i obiektowego; Bez tego nic nie zrobisz.

0

Zabrałem się za tą listę, oczywiście korzystam z przykładowych implementacji.
Powiedzcie mi, mam procedure, i przycisk do którego jest przypisana ta procedura. Gdy chcę skompilować program wywala błąd E2035 Not enough actual parameters.
Część kodu:

 type
  Puczen = ^uczen;
  uczen = record
    imie : string[30];
    nazwisko: string[30];
    next : Puczen;
  end;

var
  Form1: TForm1;
  tmp  : Puczen;
  nowa : Puczen;

implementation

{$R *.dfm}

procedure wczytaj_liste_txt(var head : Puczen);
var
  tmp, pom: Puczen;
  plik : text;
begin
  assign(plik, 'uczniowie.txt');
  {$I-}
       reset(plik);
  {$I+}
  if IOResult <> 0 then
    write('blad')
  else
    begin
     while SeekEof(plik) = false do
          begin
            new(tmp);
            readln(plik, tmp^.imie);
            readln(plik, tmp^.nazwisko);
            if head = nil then
              begin
                 tmp^.next := nil;
                 head := tmp;
              end
            else
                begin
                     pom := head;
                     while pom^.next <> nil do
                         pom := pom^.next;
                     tmp^.next := nil;
                     pom^.next := tmp;
                end;
          end;
    end;
  close(plik);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  wczytaj_liste_txt;
end;
0

wywala błąd E2035 Not enough actual parameters.

Uwielbiam taki opis problemu...

wywala błąd, nie obchodzi mnie jak go znajdziesz i jak go naprawisz, ale masz go znaleźć, poprawić i podać mi prawidłowe rozwiązanie.

Tak to wygląda na ekranie kogoś, kto mógłby pomóc.

0

Możesz chociaż nakierować?

0

A możesz napisać której linijki kodu dotyczy ten błąd?

0
procedure TForm1.Button1Click(Sender: TObject);
begin
  wczytaj_liste_txt;
end; 

Wyświetla przy end; w powyższym kodzie.
Może to być spowodowane tym że jest to kod z aplikacji konsolowej i nie zadeklarowałem jeszcze, że Imie i Nazwisko będzie pobierane z Tedit?

0

Może to być spowodowane tym że jest to kod z aplikacji konsolowej i nie zadeklarowałem jeszcze, że Imie i Nazwisko będzie pobierane z Tedit?

Nie, błąd spowodowany jest (tak jak jego treść informuje) zbyt małą liczbą podanych parametrów - tylko i wyłącznie tym; Zwróć uwagę na to, w jaki sposób zadeklarowana jest procedura wczytaj_liste_txt (popraw tę nazwę na sensowną!):

procedure wczytaj_liste_txt(var head : Puczen);

Jak widać, procedura ta pobiera jeden parametr, a w jej wywołaniu nie podajesz żadnego:

procedure TForm1.Button1Click(Sender: TObject);
begin
  wczytaj_liste_txt;  // brak parametrów...
end; 

Tak więc nie powinieneś się dziwić, że kod nie może zostać skompilowany.

0

Dzięki, faktycznie błąd był banalny w rozwiązaniu, ech te braki w wiedzy.
Możecie podpowiedzieć jak ogarnąć wypisywanie listy do Listbox lub Memo? Wiem jak to się robi ze zwykłym plikiem w programie typu Notatnik ale tu jest sprawa troszkę bardziej skomplikowana lub mi się tylko wydaje. Mianowicie lista obsługująca imię i nazwisko w pliku zapisuje sie w następujący sposób:
Andrzej
Kowalski
Jan
Kowalski
itd.
Fragment kodu na wyświetlenie wygląda tak

  begin
    while head <> nil do
        begin
         writeln(head^.imie, ' ', head^.nazwisko);
         head := head^.next;
        end;
  end; 

Jak to ugryźć ze względu na te wskaźniki przy wypisywaniu?

0

Zamień tę linijkę:

writeln(head^.imie, ' ', head^.nazwisko);

na tę:

ListBox.Items.Add(head^.Imie + ' ' + head^.nazwisko);

To wszystko.

0

Błąd leci dokładnie w tej linijce co podałeś żebym zamienił, drugi błąd dotyczy tego samego * missing operator or semicolon*

0

Wklej cały kod metody, w której dokonałeś zmian, a coś się pomyśli.

0
 procedure wyswietl(head : Puczen);
begin
  if head = nil then
     write('brak elementow')
  else
  begin
    while head <> nil do
    begin
         TForm1.ListBox1.Items.Add(head^.Imie + ' ' + head^.nazwisko);
         head := head^.next;
    end;
  end;
  readln;
end;

Próbowałem sposobem na zwykłe wyswietlenie w memo zawartosci pliku txt i było to samo

0
TForm1.ListBox1.Items.Add(head^.Imie + ' ' + head^.nazwisko);

Brak fundamentalnej wiedzy się kłania - podałeś nazwę klasy formularza, a nie nazwę jego obiektu... Tak ma być:

Form1.ListBox1.Items.Add(head^.Imie + ' ' + head^.nazwisko);
0

Kompletnie już tu nic nie rozumiem. Program działa w aplikacji konsolowej co cieszy ale w VCL już nie, niby wszystko jest okej, ale podczas wczytywania pliku.txt wyskakują błędy typu access violation, nie wiem co jest nie tak.

0

Ja też nie wiem - wróżenie z fusów mi ostatnio nie wychodzi (czyt. bez kodu nic nie podpowiem).

0

Kod podany był wcześniej ale już wklejam

procedure wczytaj_liste_txt(var head : Puczen);
var
  tmp, pom: Puczen;
  plik : text;
begin
  assign(plik, 'uczniowie.txt');
  {$I-}
       reset(plik);
  {$I+}
  if IOResult <> 0 then
    write('blad')
  else
    begin
     while SeekEof(plik) = false do
          begin
            new(tmp);
            readln(plik, tmp^.imie);
            readln(plik, tmp^.nazwisko);
            if head = nil then
              begin
                 tmp^.next := nil;
                 head := tmp;
              end
            else
                begin
                     pom := head;
                     while pom^.next <> nil do
                         pom := pom^.next;
                     tmp^.next := nil;
                     pom^.next := tmp;
                end;
          end;
    end;
  close(plik);
end;

Jeśli będzie łatwiej cokolwiek wymysleć to moge podac kod całego programu

0

Cały kod
http://pastebin.com/9PHqUK6P

Program sie kompiluje, nie wywala żadnych błędów podczas kompilacji, dopiero gdy odpalam procedure wczytaj wsykakuja błędy * access violation*, co dalej nie wiem bo to podstawowa procedura zeby cokolwiek zrobic.

0

Jedyne do czego nadaje się ten kod to do usunięcia i napisania od początku. Czemu nie możesz wziąć kodu z artykułu i dostosować go do swoich potrzeb tylko próbujesz wymyślić koło od nowa? Jeszcze spoko by było jak by chociaż koło, a nie kwadrat wychodziło.

Polecam użycie debuggera. Poszukaj czegoś takiego jak "watches" i zamiast F9 to naciskaj F8 lub F7 (w zależności jak "głęboko" potrzebujesz wejść).

0

Kod podany był wcześniej ale już wklejam

Nie było sensu wcześniej go analizować, dlatego że problemem nie była zawartość tej procedury, a sposób jej wywołania (w którym to brakowało podania argumentu);

Jeśli o problem chodzi - poniżej przykładowy kod ładujący listę z pliku o podanej w parametrze nazwie i zwracający głowę na listę w drugim parametrze; Użyłem własnych identyfikatorów, więc swój kod przystosuj do nich; A jak wolisz swoje, brzydki (polskie) nazwy to poniższy kod przystosuj do nich;

procedure LoadListFromFile(var AHead: PStudent; const AFileName: String);
var
  LInput: TextFile;
  LHead, LNew, LLast: PStudent;
begin
  AssignFile(LInput, AFileName);
  Reset(LInput);
  try
    LHead := AHead;
    LLast := LHead;
  
    while not SeekEoF(LInput) do
    begin
      New(LNew);
      LNew^.Next := nil;
      
      ReadLn(LInput, LNew^.Name);
      ReadLn(LInput, LNew^.Surename);
      
      if LLast = nil then
      begin
        LLast := LNew;
        LHead := LNew;
      end
      else
      begin
        LLast^.Next := LNew;
        LLast := LNew;
      end;
    end;
    
    AHead := LHead;
  finally
    CloseFile(LInput);
  end;
end;
0

Trochę odkopię temat, jeśli chodzi o konstruktor i destruktor w implementacji https://4programmers.net/Delphi/Lista_jednokierunkowa może ktoś trochę rozwinąć o co tam chodzi lub podać jakiś artykuł rozszerzający i wyjasniający bo domyślam się że trzeba uzupełnić jakimiś danymi konstruktor i destruktor

0

Nie, nie musisz nic uzupełniać - artykuł ten zawiera kompletne źródła klasy obsługującej w pełni funkcjonalną listę jednokierunkową; Wystarczy przewinąć stronę na sam koniec, kliknąć w link do pastebin, skopiować cały kod, utworzyć nowy moduł, wkleić kod, przekompilować i tyle.

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