Program zaliczeniowy na studia

0

Witam, mam do napisania program pt. "Loty"
-Plik wejściowy zawiera dane: numer lotu, numer rezerwacji, numer miejsca, imię i nazwisko.
-Pliki wynikowe (po jednym dla każdego lotu) mają zawierać: numer miejsca, numer rezerwacji,
imię i nazwisko pasażera (posortowane według numerów miejsc.
Utknąłem i nie wiem czemu program nie działa. Prosze o wskazówki :)

Oto treść:

program loty;

uses crt, Sysutils;


{******************************************************************************}
type
  PPasazer= ^TPasazer;
  PLinia= ^TLinia;
  TLinia=record
      Next: PLinia;
      Linia: String;
      Pasazer: PPasazer;
  end;
  TPasazer=record
      Next: PPasazer;
      Miejsce: Integer;
      Dane: string;
  end;
{******************************************************************************}
  procedure Wstaw_pasazera(var Pasazer: PPasazer; WskDoPasazer: PPasazer);
var
  tmpp:PPasazer;
begin
  tmpp:=WskDoPasazer;      {wskaznik pomocniczy pokazuje na pierwszego pasazera w liscie danej Linii samolotowej}
  while (tmpp^.Miejsce< Pasazer^.Miejsce)and(tmpp^.Next<>NIL)do tmpp:=tmpp^.Next;  {porównuje numery miejsc w samolocie i sortuje}
  Pasazer^.Next:=tmpp^.Next;
  tmpp^.Next:=Pasazer;
end;
 {******************************************************************************}

function Pasazer(Nazwa: String; Miejsce: Integer):PPasazer;
var
  tmpp:PPasazer;
begin
  new(tmpp);
  tmpp^.Dane:=Nazwa;
  tmpp^.Miejsce:=Miejsce;
  tmpp^.Next:=NIL;
  Pasazer:=tmpp;
end;

{******************************************************************************}
 procedure Dodaj_linie(var Head: PLinia; Nazwa_linii: String; Nowy_pasazer: PPasazer);
 var
   Nowa_Linia, tmp: PLinia;

 begin
   tmp:=Head;
   if Head = NIL then        {jezeli w strukturze nie ma jeszcze zadnych linii}
   begin
     new(Nowa_Linia);
     Nowa_Linia^.Linia:=Nazwa_linii;
     Nowa_Linia^.Next:=NIL;
     Head:=Nowa_Linia;
     tmp:=Nowa_linia;
     Nowa_Linia^.Pasazer:=Nowy_pasazer;
   end else begin
       while (Nazwa_linii<>tmp^.Linia)and(tmp^.Next<>NIL) do tmp:= tmp^.Next; {sprawdzamy czy linia juz istnieje w naszej strukturze}
       if (Nazwa_linii<>tmp^.Linia) then     {linia nie isnieje, laduje na koncu struktury}
       begin
         new(Nowa_Linia);
         Nowa_Linia^.Linia:=Nazwa_linii;
         Nowa_Linia^.Pasazer:=Nowy_Pasazer;
         tmp^.Next:=Nowa_Linia;
       end else begin
           Wstaw_pasazera(Nowy_pasazer, tmp^.Pasazer);                            {sytuacja, gdy dana linia juz istnieje w strukturze i musimy pasazera wstawić w dobrej kolejnosci}

     end;

   end;

 end;

{******************************************************************************}

procedure WczytajPlik(nazwa_pliku: string; var Head: PLinia);
var
  Plik: text;
  Linijka, Nazwa_linii, Nazwa: String;
  Nowy_pasazer:PPasazer;
  Miejsce: Integer;
begin
  if FileExists(nazwa_pliku) then
  begin
    Assign(Plik, nazwa_pliku);
    Reset(Plik);
    while not eof(Plik) do
    begin
       ReadLn(Plik, Linijka);
       Nazwa_linii:=Copy(Linijka,0,pos(' ',Linijka));   {wrzuc fragmenty stringa do konkretnych}
       Delete(Linijka,1,pos(' ',Linijka));                    {zmiennych, potem usuwaj }
       Val((Copy(Linijka,0,pos(' ',Linijka)-1)),miejsce);    {pamietaj, ze to integer}
       Delete(Linijka,1,pos(' ',Linijka));                       {zmien go ze stringa !}
       nazwa:=Copy(Linijka,0,pos(' ',Linijka)-1);
       Delete(Linijka,1,pos(' ',Linijka));
       nazwa:=nazwa + ' '+ Linijka;
       Delete(Linijka,1,pos(' ',Linijka));
       Nowy_pasazer:=Pasazer(Nazwa, Miejsce);
       Dodaj_linie(Head, Nazwa_linii, Nowy_pasazer);

    end;
  Close(Plik);
  end else
     WriteLn('Plik "',nazwa_pliku,'" nie istnieje!');
end;
{******************************************************************************}
procedure Zakonczenie_dzialania(var Head: PLinia);
var
  tmpp: PPasazer;
  tmp: PLinia;
  P: Text;
begin
  tmp:=Head;
  repeat
     Assign(P, tmp^.Linia);                   {Zapis pasazerow do pliku tekstowego o nazwie tmp^.Linia}
     Rewrite(P);
     tmpp:=tmp^.Pasazer;
     repeat
        WriteLn(P,tmpp^.Miejsce:10,tmpp^.Dane);
        tmpp:=tmpp^.Next;
     until(tmpp^.Next=NIL) ;
     tmp:=tmp^.Next;
     Close(P);
  until (tmp^.Next=NIL);
end;
{******************************************************************************}
procedure Wyczysc_pasazer(var wsk:PPasazer);
begin
  if(wsk^.Next<>NIL) then Wyczysc_pasazer(wsk^.Next);
  dispose(wsk);
end;

procedure Wyczysc(var Head:PLinia);
var tmp:PLinia;
begin
  tmp:=Head;
  if (tmp^.Next<>NIL) then
  begin
    Wyczysc(tmp^.Next);
    Wyczysc_pasazer(tmp^.Pasazer);
  end;
  dispose(tmp);
end;



{******************************************************************************}
var
  Head: PLinia;
  Opcja:byte;
begin
  Head:=NIL;
  WczytajPlik('text.txt', Head);
  Zakonczenie_dzialania(Head);
  Wyczysc(Head);
  readln();

end.

dodanie znacznika <code class="delphi">- fp

1

Czy Was na tych studiach nie uczą obsługi debugera...?

procedure Wstaw_pasazera(var Pasazer: TPasazer; WskDoPasazer: PPasazer);
var
  tmp:PPasazer;
begin
  tmp:=WskDoPasazer;      {wskaznik pomocniczy pokazuje na pierwszego pasazera w liscie danej Linii samolotowej}

  while (tmp^.Miejsce < Pasazer.Miejsce) and (tmp^.Next <> nil) do
    tmp:=tmp^.Next;  {porównuje numery miejsc w samolocie i sortuje}

  Pasazer.Next := tmp^.Next;
  tmp^.Next := @Pasazer;
end;

Dlaczego obsługując listę jednokierunkową nie podajesz w argumentach procedury danych pasażera, tylko rekord (a nawet dwa)? Wskaźnik na rekord nowego pasażera powinieneś tworzyć wewnątrz procedury, a następnie znaleźć dla niego miejsce i go tam wstawić; Jakaś strasznie uboga ta procedura;


procedure Wyczysc(Head:PLinia);
var tmp:PLinia;
begin
  tmp:=Head;
  if (tmp^.Next<>NIL) then
  begin
    Wyczysc(tmp^.Next);
    Wyczysc_pasazer(tmp^.Pasazer);
  end;
  dispose(tmp);
end;

Wiesz co się stanie jeśli argument Head jest pusty (zawiera Nil)? SIGSEGV murowany; Poza tym wskaźnik na głowę listy przekazujesz przez wartość, więc wewnątrz procedury operujesz na jego kopii, a poza procedurą po wyczyszczeniu listy nadal będzie zawierał adres różny od Nil, co jest błędem, bo będzie wskazywał na obszar pamięci, który został zwolniony; Przekaż go przez referencję;


Dane lotu oraz dane pasażera przekazuj do procedur w osobnych argumentach i utwórz sobie funkcję tworzącą nowy rekord w pamięci, uzupełniony od razu danymi i zwracającą do niego wskaźnik - uprościsz i skrócisz istniejący kod; I nazywaj zmienne po ludzku, tak żeby patrząc na nią od razu było wiadomo do czego służy, a tmp czy tmpp kompletnie nic nie mówi...


{wskaznik pomocniczy pokazuje na pierwszego pasazera w liscie danej Linii samolotowej}

Linie są lotnicze, nie samolotowe;

SScanf(Linijka,'%s %d %s %s',[@Nazwa_linii, @Pasazer.Miejsce, @Pasazer.Imie, @Pasazer.Nazwisko]);

This is amazing... Really amazing... o.O

0

Na jednej z najlepszych inf w kraju (AGH) nie ucza obslugi zadnego debuggera xD

a przepraszam raz na asemblerze mielismy go odpalic zeby jakis rejestr podejrzec ot wsio

0

Program troche poprawiłem, ale dalej mam problem przy kończeniu dzialania i zapisie do plików. Z góry dzieki za pomoc

0

@bahama - albo podasz kod, który nie działa prawidłowo i różne inne przydatne informacje, albo ja już do tego wątku zaglądać nie będę; Nie mam zamiaru zgadywać i zastanawiać się za Ciebie.

0

Niestety nie wszystko działa jak powinno. Wrzucam jeszcze raz kod. Otóż mam kłopoty przy zapisie do pliku, musiałem dodać sytuacje, gdy 2 numer miejsca w danym locie jest mniejszy od pierwszego na podwieszonej do tego lotu liscie pasażerów. I w plikach wynikowych dostaje dziwne rzeczy, albo tylko jednego pasażera, albo bez tego o najmniejszym numerze miejsca. Ktoś wie o co może chodzic?

program loty;

uses crt, Sysutils;


{******************************************************************************}
type
  PPasazer= ^TPasazer;
  PLinia= ^TLinia;
  TLinia=record
      Next: PLinia;
      Linia: String;
      Pasazer: PPasazer;
  end;
  TPasazer=record
      Next: PPasazer;
      Miejsce: Integer;
      Dane: string;
  end;
{******************************************************************************}
  procedure Wstaw_pasazera(var Pasazer: PPasazer; WskDoPasazer: PPasazer);
var
 tmpp:PPasazer;
begin
 tmpp:=WskDoPasazer;   {wskaznik pomocniczy pokazuje na pierwszego pasazera w liscie danej Linii samolotowej}
 if(tmpp^.Miejsce>Pasazer^.Miejsce) then begin Pasazer^.Next:=WskDoPasazer; WskDoPasazer:=Pasazer;end else begin {nowy jest wiekszy od pierwszego na liscie}
 while (tmpp^.Next<>NIL) and (tmpp^.Next^.Miejsce< Pasazer^.Miejsce) do tmpp:=tmpp^.Next;  {porównuje numery miejsc w samolocie i sortuje}
 if(tmpp^.Next<>NIL) then
 begin
 Pasazer^.Next:=tmpp^.Next;   {nowy laduje gdzies w srodku listy}
 tmpp^.Next:=Pasazer;
 end else

 tmpp^.Next:=Pasazer;  {nowy ląduje na końcu listy}
end;

end;

 {******************************************************************************}

function Pasazer(Nazwa: String; Miejsce: Integer):PPasazer;
var
  tmpp:PPasazer;
begin
  new(tmpp);
  tmpp^.Dane:=Nazwa;
  tmpp^.Miejsce:=Miejsce;
  tmpp^.Next:=NIL;
  Pasazer:=tmpp;
end;

{******************************************************************************}
 procedure Dodaj_linie(var Head: PLinia; Nazwa_linii: String; Nowy_pasazer: PPasazer);
 var
   Nowa_Linia, tmp: PLinia;

 begin
   tmp:=Head;
   if Head = NIL then        {jezeli w strukturze nie ma jeszcze zadnych linii}
   begin
     new(Nowa_Linia);
     Nowa_Linia^.Linia:=Nazwa_linii;
     Nowa_Linia^.Next:=NIL;
     Head:=Nowa_Linia;
     tmp:=Nowa_linia;
     Nowa_Linia^.Pasazer:=Nowy_pasazer;
   end else begin
       while (Nazwa_linii<>tmp^.Linia)and(tmp^.Next<>NIL) do tmp:= tmp^.Next; {sprawdzamy czy linia juz istnieje w naszej strukturze}
       if (Nazwa_linii<>tmp^.Linia) then     {linia nie isnieje, laduje na koncu struktury}
       begin
         new(Nowa_Linia);
         Nowa_Linia^.Linia:=Nazwa_linii;
         Nowa_Linia^.Pasazer:=Nowy_Pasazer;
         tmp^.Next:=Nowa_Linia;
         Nowa_Linia^.Next:=NIL;
       end else begin
           Wstaw_pasazera(Nowy_pasazer, tmp^.Pasazer);                            {sytuacja, gdy dana linia juz istnieje w strukturze i musimy pasazera wstawić w dobrej kolejnosci}

     end;

   end;

 end;

{******************************************************************************}

procedure WczytajPlik(nazwa_pliku: string; var Head: PLinia);
var
  Plik: text;
  Linijka, Nazwa_linii, Nazwa: String;
  Nowy_pasazer:PPasazer;
  Miejsce: Integer;
begin
  if FileExists(nazwa_pliku) then
  begin
    Assign(Plik, nazwa_pliku);
    Reset(Plik);
    while not eof(Plik) do
    begin
       ReadLn(Plik, Linijka);
       Nazwa_linii:=Copy(Linijka,0,pos(' ',Linijka));   {wrzuc fragmenty stringa do konkretnych}
       Delete(Linijka,1,pos(' ',Linijka));                    {zmiennych, potem usuwaj }
       Val((Copy(Linijka,0,pos(' ',Linijka)-1)),miejsce);    {pamietaj, ze to integer}
       Delete(Linijka,1,pos(' ',Linijka));                       {zmien go ze stringa !}
       nazwa:=Copy(Linijka,0,pos(' ',Linijka)-1);
       Delete(Linijka,1,pos(' ',Linijka));
       nazwa:=nazwa + ' '+ Linijka;
       Delete(Linijka,1,pos(' ',Linijka));
       Nowy_pasazer:=Pasazer(Nazwa, Miejsce);
       Dodaj_linie(Head, Nazwa_linii, Nowy_pasazer);

    end;
  Close(Plik);
  end else
     WriteLn('Plik "',nazwa_pliku,'" nie istnieje!');
end;

{******************************************************************************}
procedure Zakonczenie_dzialania(var Head: PLinia);
var
  tmpp: PPasazer;
  tmp: PLinia;
  P: Text;
begin
  tmp:=Head;
  while (tmp^.Next<>NIL) do begin
     Assign(P, tmp^.Linia+'.txt');                   {Zapis pasazerow do pliku tekstowego o nazwie tmp^.Linia}
     Rewrite(P);
     tmpp:=tmp^.Pasazer;
     while (tmpp^.Next<>NIL)do begin
        WriteLn(P,tmpp^.Miejsce,' ',tmpp^.Dane);
        tmpp:=tmpp^.Next;
        end;
     WriteLn(P,tmpp^.Miejsce,' ',tmpp^.Dane);
     tmp:=tmp^.Next;
     Close(P);
  end;
  Assign(P, tmp^.Linia+'.txt');                   {Zapis pasazerow do pliku tekstowego o nazwie tmp^.Linia}
     Rewrite(P);
     tmpp:=tmp^.Pasazer;
     while (tmpp^.Next<>NIL)do begin
        WriteLn(P,tmpp^.Miejsce,' ',tmpp^.Dane);
        tmpp:=tmpp^.Next;
        end;
     WriteLn(P,tmpp^.Miejsce,' ',tmpp^.Dane);
     tmp:=tmp^.Next;
     Close(P);
end;
{******************************************************************************}
procedure Wyczysc_pasazer(var wsk:PPasazer);
begin
  if(wsk^.Next<>NIL) then Wyczysc_pasazer(wsk^.Next);
  dispose(wsk);
end;

procedure Wyczysc(var Head:PLinia);
var tmp:PLinia;
begin
  tmp:=Head;
  if (tmp^.Next<>NIL) then
  begin
    Wyczysc(tmp^.Next);
    Wyczysc_pasazer(tmp^.Pasazer);
  end;
  dispose(tmp);
end;



{******************************************************************************}
var
  Head: PLinia;
  Opcja:byte;
begin
  Head:=NIL;
  WczytajPlik('text.txt', Head);

  Zakonczenie_dzialania(Head);
  Wyczysc(Head);


  readln();

end.
0

Otóż mam kłopoty przy zapisie do pliku, musiałem dodać sytuacje, gdy 2 numer miejsca w danym locie jest mniejszy od pierwszego na podwieszonej do tego lotu liscie pasażerów.

Jeśli faktycznie tak jest, to problemem raczej nie jest zapis do pliku, a procedura dodająca pasażera do listy pasażerów danego lotu; Z tego wynika, że numery pasażerów po ich dodaniu nie są posortowane właściwie - i tutaj bym szukał pod debugerem w jaki sposób pasażerowie są dodawani do listy;

Niestety procedura Wstaw_pasazera jest nieczytelna, więc polecam sformatować kod i usunąć komentarze, bo sam raczej wiesz co konkretne instrukcje wykonują.

0

Najgłupsze błędy najtrudniejsze do znalezienia..
Brakowało var-a przy wskaźniku do listy pasażerów w procedurze

procedure Wstaw_pasazera(var Pasazer: PPasazer; WskDoPasazer: PPasazer);

dziękuje za pomoc :)

dodanie znacznika <code class="delphi"> - fp

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