Problem z deklaracją typów, rekordami, wskaźnikami...

0

Witam!
Programuję w Delphi od jakiegoś czasu, ale teraz przyszło mi się zmierzyć z rekordami, nowymi typami i wskaźnikami - nie znam się na tym, oczywiście poczytałam o tym, jednak nadal mam problem - w momencie kompilacji wyskakuje błąd Expected ":" but "=" found w linii TElement = record czyli gdzie deklaruję strukturę.
Oto fragment mojego kodu:

unit MainUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TMainForm = class(TForm)
    PLMemo: TMemo;
    ...
    SzukajButton: TButton;

    TElement = record
      Next : PElement; // wskaznik na nastepny element listy
      PL : String;
      ...
      Rok : Integer;

    PElement = ^Element;   // zadeklarowalam typ wskaznikowy


    procedure Wczytaj(Sender: TObject);
    procedure Zapisz(Sender: TObject; var Action: TCloseAction);
    procedure SzukajButtonClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }



  Root : PElement; // poczatek listy - wskaznik
  Last : PElement; // koniec listy - wskaznik

  end;

var
  MainForm: TMainForm;

implementation

uses SzukajUnit;

{$R *.dfm}

procedure TMainForm.Wczytaj(Sender: TObject);
...
end;

procedure TMainForm.Zapisz(Sender: TObject; var Action: TCloseAction);
begin
  // zapisanie bazy danych

  // posprzatanie listy
end;

procedure TMainForm.SzukajButtonClick(Sender: TObject);
begin
  SzukajForm.Visible := True;
end;

end.

Program to generalnie baza filmów, ma wczytać z pliku txt bazę do listy jednokierunkowej i ją wyświetlić (jak na razie tyle). Niestety wcześniej nie miałam styczności ze wskaźnikami, listami i nowymi typami i dlatego już mam problemy. Jak zmienię znak = na : to występuje następny problem - czyli błąd nie leży w tym znaku, wydaje mi się, że jest gdzieś indziej.
Z góry dziękuję za pomoc i pozdrawiam,
Asia

0
type
  TMainForm = class(TForm)
    PLMemo: TMemo;
    ...
    SzukajButton: TButton;
 
    TElement = record
      Next : PElement; // wskaznik na nastepny element listy
      PL : String;
      ...
      Rok : Integer;
 
    PElement = ^Element;   // zadeklarowalam typ wskaznikowy

1.Gdzieś zgubiłaś "end;".
2.Deklarację rekordu zaczyna się od "type"

Type TElement = record
      Next : PElement; // wskaznik na nastepny element listy
      PL : String;
      ...
      Rok : Integer;
 end;

Tylko tak, jak próbujesz zrobić się nie da.
Musisz wywalić rekord przed klasę lub za nią.
Np:

type TElement = record
      Next : PElement; // wskaznik na nastepny element listy
      PL : String;
      ...
      Rok : Integer;
  end;
type PElement = ^Element;   // zadeklarowalam typ wskaznikowy
type
  TMainForm = class(TForm)
    PLMemo: TMemo;
    ...
    SzukajButton: TButton;
 
 
    procedure Wczytaj(Sender: TObject);
    procedure Zapisz(Sender: TObject; var Action: TCloseAction);
    procedure SzukajButtonClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
 
 
 
  Root : PElement; // poczatek listy - wskaznik
  Last : PElement; // koniec listy - wskaznik
 
  end;

IMHO, byłoby lepiej, jakbyś zaczęła naukę podstaw w Free Pascalu.

0

Ja już ze słowami end i type kombinowałam (jestem dziewczyną).
Wpisałam type przed deklarację struktury. Po kompilacji Delphi krzyczy Expected end but type found w miejscu gdzie to type dopisałam, a więc dopisuję end po deklaracji formy. Kompiluję - Delphi krzyczy, że metoda "wczytaj" nie istnieje, czy skasować referencję. Tylko że ta metoda istnieje.. więc odpowiadam, żeby nie kasował referencji - wtedy wywala na linijkę Next : PElement; // wskaznik na nastepny element listy, że Undeclared identifier "PElement" - a przecież jest zadeklarowany chwilę później - to może być dla niego problem, dlatego przenoszę część kodu z deklaracją struktury za deklarację "PElement". Kompiluję. I teraz błąd jest na linijce kodu z deklaracją "PElement", bo przecież Undeclared identifier "Element, czyli musiałabym przenieść tę linijkę z powrotem. Fragment zmienionego od ostatniego posta kodu wygląda teraz tak:

type
  TMainForm = class(TForm)
    PLMemo: TMemo;
   ...
    SzukajButton: TButton;
    end;

    PElement = ^Element;   // zadeklarowalam typ wskaznikowy

    type TElement = record
      Next : PElement; // wskaznik na nastepny element listy
      PL : String;
      ...
      Rok : Integer;

    procedure Wczytaj(Sender: TObject);

EDIT:
Zrobiłam, najpierw rekord, później wskaźnik, później forma, ale wywala błąd "Undeclared identifier: 'PElement'" przy deklaracji wskaźnika w strukturze. Niestety projekt ma być napisany w Delphi, jakieś podstawy już mam (np. umiem zrobić grę kółko i krzyżyk :D), ale może akurat nie te, które by mi się tu przydały ;) Myślę, że jest w moim programie "zapętlenie" - nie mogę zrobić struktury ze wskaźnikiem przed deklaracją wskaźnika i nie mogę zrobić wskaźnika na rekord bez deklaracji rekordu... Ale jak z tej "pętli" wyjść?

unit MainUnit;

interface

uses
  Windows, ...;

type TElement = record
      Next : PElement; // wskaznik na nastepny element listy
      PL : String;
      ...
      Rok : Integer;
type PElement = ^Element;   // zadeklarowalam typ wskaznikowy

type
  TMainForm = class(TForm)
    PLMemo: TMemo;
    ...
    SzukajButton: TButton;


    procedure Wczytaj(Sender: TObject);
    procedure Zapisz(Sender: TObject; var Action: TCloseAction);
    procedure SzukajButtonClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }



  Root : PElement; // poczatek listy - wskaznik
  Last : PElement; // koniec listy - wskaznik

  end;

var
  MainForm: TMainForm;

implementation

uses SzukajUnit;

{$R *.dfm}

procedure TMainForm.Wczytaj(Sender: TObject);
...
end;

procedure TMainForm.Zapisz(Sender: TObject; var Action: TCloseAction);
begin
  // zapisanie bazy danych

  // posprzatanie listy
end;

procedure TMainForm.SzukajButtonClick(Sender: TObject);
begin
  SzukajForm.Visible := True;
end;

end.
1

chyba tak mozna...:

type PElement=^TElement;
   TElement = record
      Next : PElement; // wskaznik na nastepny element listy
      PL : String;
      Rok : Integer;
end;
0

Faktycznie! Dzięki! Robiłam to na podstawie kursów z 4programmers, więc przepisywałam tak jak tam było. Dlaczego raz trzeba napisać PElement, raz TElement, a czasem samo Element? Rozumiem, że ma to pomóc w odnalezieniu się, czy dane słowo reprezentuje zmienną, czy typ. PElement to pointer czyli wskaźnik, a TElement to struktura. Czyli pisząc type PElement = ^TElement; deklaruję typ wskaźnikowy, który będzie wskazywał na zmienną typu strukturalnego, dobrze rozumiem? Czyli cały problem polegał na tym, że zabrakło tej jednej literki?

1
rajaaa92 napisał(a)

Robiłam to na podstawie kursów z 4programmers, więc przepisywałam tak jak tam było.
Wskaźniki. Listy jedno i dwukierunkowe.
tu jest identycznie wiec albo cos przeoczylas albo korzystalas z innego zrodla w ktorym byl blad.

Dlaczego raz trzeba napisać PElement, raz TElement, a czasem samo Element?
nie ma takiego typu "Element". mozesz co najwyżej nazwac tak sobie zmienna lub pole.

Czyli pisząc type PElement = ^TElement; deklaruję typ wskaźnikowy, który będzie wskazywał na zmienną typu trukturalnego, dobrze rozumiem?
dokladnie (chociaz mozna by sie przyczepic za slowo "zmienna"- bo to nie musi byc zmienna, moze byc np elementem tablicy).

Czyli cały problem polegał na tym, że zabrakło tej jednej literki?
czytaj bledy kompilatora. jesli powiedzial [Error] Undeclared identifier: 'Element' tzn ze nie wie co to jest Element i wtedy faktycznie problemem jest to ze brakuje jednej literki.

0

A więc tak jak wspomniałam, program ma (jak na razie) na starcie wczytać bazę danych z pliku txt do listy jednokierunkowej a następnie ją wyświetlić (używam memo).
W OnCreate() mam procedurę Wczytaj, która wygląda tak:

procedure TMainForm.Wczytaj(Sender: TObject);
var
  Baza : TextFile;
  Linia : String;
  NewOne : PElement;
  AtList : PElement;
begin
  // wczytanie bazy danych z pliku do listy i z listy do memo
  Root := nil;
  Last := nil;
  AtList := Root;
  AssignFile(Baza, 'D:\Dokumenty\Studia\PP\Delphi\02 baza filmów\baza.txt');
  if FileExists('D:\Dokumenty\Studia\PP\Delphi\02 baza filmów\baza.txt') then
    Reset(Baza)
  else
    Rewrite(Baza);
  while not Eof(Baza) do
  begin
    Readln(Baza, Linia);
    New(NewOne);
    NewOne^.Next := nil;
    NewOne^.PL := Copy(Linia, 1, Pos(';', Linia) - 1);    // wycina z linii tektu oddzielonej
    Linia := Copy(Linia, Pos(';', Linia) + 1, 1000);      // srednikami odpowiednie wartosci
    NewOne^.Oryg := Copy(Linia, 1, Pos(';', Linia) - 1);
    Linia := Copy(Linia, Pos(';', Linia) + 1, 1000);
    NewOne^.CzasH := StrToInt(Copy(Linia, 1, Pos(';', Linia) - 1));
    Linia := Copy(Linia, Pos(';', Linia) + 1, 1000);
    NewOne^.CzasM := StrToInt(Copy(Linia, 1, Pos(';', Linia) - 1));
    Linia := Copy(Linia, Pos(';', Linia) + 1, 1000);
    NewOne^.CzasS := StrToInt(Copy(Linia, 1, Pos(';', Linia) - 1));
    Linia := Copy(Linia, Pos(';', Linia) + 1, 1000);
    NewOne^.Jezyk := Copy(Linia, 1, Pos(';', Linia) - 1);
    Linia := Copy(Linia, Pos(';', Linia) + 1, 1000);
    NewOne^.Rok := StrToInt(Linia);
    if Root = nil then
    begin
      Root := NewOne;
      Last := Root;
    end else begin
      Last^.Next := NewOne;
      Last := NewOne;
    end;
  end;
  while AtList <> nil do
  begin
    PLMemo.Lines.Add(AtList^.PL);
    OrygMemo.Lines.Add(AtList^.Oryg);
    CzasMemo.Lines.Add(IntToStr(AtList^.CzasH) + ':' + IntToStr(AtList^.CzasM) + ':' +
                           IntToStr(AtList^.CzasS));
    JezykMemo.Lines.Add(AtList^.Jezyk);
    RokMemo.Lines.Add(IntToStr(AtList^.Rok));
    AtList := AtList^.Next;
  end;
end;

Również na podstawie 4programmers, dostosowane do moich potrzeb. Jednak kiedy forma się tworzy, w moich memo nie pojawia się zupełnie nic...

0

A wywołujesz tę procedurę?

0

Jest wpisana w pole "OnCreate" w zdarzeniach mojej głównej formy - czyli jest wywoływana na starcie, prawda?

0

przede wzystkim rob wieksze wciecia w kodzie, np:

if Root = nil then
   begin
     Root := NewOne;
     Last := Root;
   end
else
   begin
     Last^.Next := NewOne;
     Last := NewOne;
   end;

zupelnie inaczej sie to pozniej czyta.

po drugie: jesli Ci "cos" nie dziala to pomysl jak mozesz sprawdzic w ktorym miejscu wystepuje blad: np jesli odczytujesz cos z pliku to sprawdzaj zwyklym showmessage() jaki tekst zostal odczytany. jesli tniesz tekst na kawalki to sprawdzaj czy wszystko sie zgadza.

druga sprawa: te wszystkie pos(), copy() itd... kazdy robi jak lubi ja preferuje inne rozwiazanie w takich wypadkach:
masz tu kod, mysle ze zrozumiesz jak tego uzywac:

procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
    sl:TStringList;
    s:String;
begin
  sl:=TStringList.Create;
  s:='Jan;Kowalski;19;4;1938;Stefan;Pracownik;0;119287;Jakis inny parametr';
  sl.Text:=StringReplace(s, ';', #13#10, [rfReplaceAll]);

  for i:=0 to sl.Count-1 do
    showmessage(sl[i]);

  sl.Free;
end;

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