Stworzenie procedury porównującej

0

Mam takie o to zadanie do zrobienia:

W pliku tekstowym A.txt znajduje się wykaz punktów geodezyjnych,
składający się z numeru punktu (typu Word) oraz jego opisu (max. 15
znaków). W jednym wierszu pliku A.txt zapisane są dane dotyczące
jednego punktu, np.
33 Punkt I klasy
52 Punkt poligonowy
itd. ...
W pliku tekstowym B.txt zamieszczono wykaz współrzędnych punktów.
W jednym wierszu tego pliku znajduje się numer punktu oraz
współrzędne X, Y np.
11 20.345 30.567
33 10.456 67.888
itd. ...
Napisz program, w którym trzy procedury realizują następujące
zadania:

  1. Procedura jeden wybiera z plików A.txt i B.txt punkty, których
    numery występują w obydwu plikach oraz zapisuje je do tablicy
    rekordów.
  2. Procedura dwa sortuje wybrane punkty w kolejności od
    najmniejszego do największego (wg numerów).
  3. Procedura trzy zapisuje wybrane i posortowane punkty w pliku
    zdefiniowanym C,
    Punkty maja następującą strukturę:
    Punkt = record
    Nr : Word;
    X,Y : Real;
    opis : String[15];
    end;

Udało mi się napisać taki kod na wczytanie obu tablic rekordowych:

 
program Zad_5PK;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type punkt = record
  nr:integer;
  X,Y: real;
  opis:string[20];
  end;

  var i,j,n:Integer;
  spis: array[1..20] of punkt;
  A,B,C:text;

begin

Assign(A,'A.txt');
reset(A);
i:=1;
Repeat
  read(A,spis[i].nr);
  read(A,spis[i].opis);
  i:=i+1;
until eof(A);
close (A);

Assign(B,'B.txt');
reset(B);
i:=1;
Repeat
  read(B,spis[i].nr);
  read(B,spis[i].X);
  read(B,spis[i].Y);
  i:=i+1;
until eof(B);
close (B);

readln;
end.

I teraz pytanie jak zapisać procedurę jeden, ponieważ nie wiem jak porównać rekordy z pliku A z rekordami z pliku B.
Co do reszty procedur myślę że sobie poradzę.

0

Zakładając, że dane z pliku wczytujesz poprawnie (nie zweryfikuję teraz tego), to widzę wyraźny błąd koncepcyjny. Zwróć uwagę, że numery punktów z pliku B nie muszą się pokrywać z tymi z pliku A. Czytając z pliku B nadpisujesz numery wczytane wcześniej z A. Wczytując numer punktu z pliku B musisz poszukać najpierw czy taki numer jest w tablicy rekordów, a następnie uzupełnić dane w tym rekordzie (lub dodać nowy rekord jeżeli numer nie zostanie znaleziony).

0

Ten kod realizuje też punkt 1.

program Zad_5PK;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils;
 
type Tpunkt = record
  nr:integer;
  X,Y: real;
  opis:string[20];
  end;
 
  var i,j,n:Integer;
  spis: array of Tpunkt;
  A,B,C:text;
  s:ansistring;
  r1,r2:double;
 
begin
 
Assign(A,'A.txt');
reset(A);
setlength(spis,0);
while not eof(a) do
  begin
  readln(a,i,s);
  setlength(spis,length(spis)+1);
  spis[high(spis)].nr:=i;
  spis[high(spis)].opis:=s;
  end;
close (A);
 
Assign(B,'B.txt');
reset(B);
while not eof(b) do
  begin
  readln(b,i,r1,r2);
  n:=-1;
  for j:=0 to length(spis)-1 do if spis[j].nr=i then 
    begin
    n:=j;
    break;
    end;
  if n=-1 then continue;//Nie ma takiego punktu w bazie
  spis[n].x:=r1;
  spis[n].y:=r2;
  end;
close (B);
 
readln;
end.

Przy okazji: Jak masz okazję się przekonać, kod z wcięciami czyta się dużo lepiej.

0

To ja dopiero teraz odpiszę, bo coś wolno mi szło kodzenie, jak zwykle to u mnie bywa chaotycznie i musiałem poprawiać. Szkoda, że nie dołączyłeś przykładowych plików z danymi albo nie wrzuciłeś ich na jakiś hosting. Ale luzik, z podanego przykładu plus jednej danej dla siebie zrobiłem taki kod, jak wklejam poniżej. Ja tam nie umiem dobrze sortować samodzielnie tablic i porównywać czy występuje już w tablicy tworząć dodatkowe pętle. Widziałem, że wkleiłeś nagłówek z aplikacji konsolowej pod Delphi, z SysUtils w uses. A skoro możesz korzystać z dobrodziejstw Delphi i modułów z komponentami, to dlaczego by sobie nie ułatwić zadania. Skorzystałem z TStringList. Najpierw w procedurze Jeden dopisuje do tablicy rekordów nieposortowane rekordy, a później je sortuje i dopisuje jeszcze raz do tej tablicy. Jak widać TStringList ma wygodne procedury do sortowania. Program nie sprawdza poprawności danych (czy są to liczby w dobrym formacie) ale to już sobie dorób, a i zapisuje on punkty z separatorem dziesiętnym, jednak jeżeli chcesz mieć zamiast tego kropki jak w wejściowych plikach to znowu sobie przy dodawaniu - zastosuj w procedurze Trzy ponownie StringReplace z DecimalSeparator na kropkę. I może da się poniższy kod jeszcze uprościć, ale ja zrobiłem tak jak potrafiłem, i z moich testów wynika, że działa dobrze. A i zaraz nasz forumowu mądrala TomRiddle się przyczepi do czegoś sam nie odpowiadając sensownie w pore - na przykład, że po co używać funkcji Explode jak można ExtractStrings. Jednak ja tam wolę korzystać z niej niż jakieś tam niepotrzebne parametry stosować we wbudowanej. Wiem, że tutaj korzystamy z modułów z komponentami, ale z czym sobie można ułatwić to można sobie ułatwić, a funkcja Explode dawno na google znaleziona i przydaje się na przyszłość. Gdzie korzystamy z ułatwień w postaci TStringList to korzystamy z ułatwień, ale z Explode nie chciałem sobie ułatwiać i tyle :P Najwyżej pytający dopasuje sobie ten kod po swojemu.

program zad_5pk;

{$APPTYPE CONSOLE}

uses
  Classes, SysUtils;

type
  TPunkt = record
    Nr : Word;
    X, Y : Real;
    Opis : string[15];
  end;
  TPunktObj = class(TObject)
    Nr : Word;
    X, Y : Real;
    Opis : string[15];
  end;

const
  PlikANazwa = 'a.txt';
  PlikBNazwa = 'b.txt';
  PlikWyjNazwa = 'c.txt';
var
  Obj : TPunktObj;
  Sciezka : string;
  TabPunkty : array of TPunkt;
  PlikASL, PlikBSL, WyjASL, WyjBSL, TymczSL : TStringList;

function Explode(Str : string; Separator : string) : TStringList;
var
  X : integer;
begin
  Result := TStringList.Create;
  X := Pos(Separator, Str);
  while X > 0 do
  begin
    Result.Add(Copy(Str, 1, X - 1));
    if X <= Length(Str) then
    begin
      Str := Copy(Str, X + Length(Separator), Length(Str));
    end;
    X := Pos(Separator, Str);
  end;
  if (Length(Str) > 0) then
  begin
    Result.Add(Str);
  end;
end;

function NumeryPunktowRosnaco(List : TStringList; Index1, Index2 : integer) : integer;
var
  I1, I2 : integer;
begin
  I1 := TPunktObj(List.OBjects[Index1]).Nr;
  I2 := TPunktObj(List.OBjects[Index2]).Nr;
  if I1 < I2 then
    Result := -1
  else
    if I1 > I2 then
      Result := 1
    else
      Result := 0;
end;

procedure Jeden;
var
  I, J : integer;
begin
  if FileExists(Sciezka + PlikANazwa) then
  begin
    PlikASL.LoadFromFile(PlikANazwa);
  end
  else
  begin
    Writeln('Plik: ', Sciezka + PlikANazwa, ' nie istnieje! Zamykam program. Nacisnij Enter.');
    Readln;
    Halt;
  end;
  if FileExists(Sciezka + PlikBNazwa) then
  begin
    PlikBSL.LoadFromFile(PlikBNazwa);
  end
  else
  begin
    Writeln('Plik: ', Sciezka + PlikBNazwa, ' nie istnieje! Zamykam program. Nacisnij Enter.');
    Readln;
    Halt;
  end;
  WyjASL.Sorted := True;
  WyjASL.Duplicates := dupIgnore;
  WyjBSL.Sorted := True;
  WyjBSL.Duplicates := dupIgnore;
  for I := 0 to PlikASL.Count - 1 do
  begin
    TymczSL := Explode(PlikASL[I], ' ');
    Obj := TPunktObj.Create;
    Obj.Opis := '';
    Obj.Nr := StrToInt(TymczSL[0]);
    for J := 1 to TymczSL.Count - 1 do
    begin
      if J < TymczSL.Count - 1 then
      begin
        Obj.Opis := Obj.Opis + TymczSL[J] + ' ';
      end
      else
      begin
        Obj.Opis := Obj.Opis + TymczSL[J];
      end;
    end;
    WyjASL.AddObject(TymczSL[0], Obj);
  end;
  for I := 0 to PlikBSL.Count - 1 do
  begin
    TymczSL := Explode(PlikBSL[I], ' ');
    J := WyjASL.IndexOf(TymczSL[0]);
    if J > -1 then
    begin
      Obj := TPunktObj(WyjASL.Objects[J]);
      TymczSL[1] := StringReplace(TymczSL[1], ',', DecimalSeparator, []);
      TymczSL[1] := StringReplace(TymczSL[1], '.', DecimalSeparator, []);
      TymczSL[2] := StringReplace(TymczSL[2], ',', DecimalSeparator, []);
      TymczSL[2] := StringReplace(TymczSL[2], '.', DecimalSeparator, []);
      Obj.X := StrToFloat(TymczSL[1]);
      Obj.Y := StrToFloat(TymczSL[2]);
      WyjBSL.AddObject(WyjASL[J], Obj);
    end;
  end;
  SetLength(TabPunkty, WyjBSL.Count);
  for I := 0 to WyjBSL.Count - 1 do
  begin
    Obj := TPunktObj(WyjBSL.Objects[I]);
    with TabPunkty[I] do
    begin
      Nr := Obj.Nr;
      Opis := Obj.Opis;
      X := Obj.X;
      Y := Obj.Y;
    end;
  end;
end;

procedure Dwa;
var
  I : integer;
begin
  WyjBSL.Sorted := False;
  WyjBSL.CustomSort(NumeryPunktowRosnaco);
  for I := 0 to WyjBSL.Count - 1 do
  begin
    Obj := TPunktObj(WyjBSL.Objects[I]);
    with TabPunkty[I] do
    begin
      Nr := Obj.Nr;
      Opis := Obj.Opis;
      X := Obj.X;
      Y := Obj.Y;
    end;
  end;
end;

procedure Trzy;
var
  I : integer;
begin
  TymczSL.Clear;
  begin
    for I := Low(TabPunkty) to High(TabPunkty) do
    begin
      with TabPunkty[I] do
      begin
        TymczSL.Add(IntToStr(Nr) + ' ' + Opis + ' ' + FloatToStr(X) + ' ' + FloatToStr(Y))
      end;
    end;
  end;
  try
    TymczSL.SaveToFile(Sciezka + PlikWyjNazwa);
  except
    Writeln('Nie można zapisać do pliku: ', Sciezka + PlikWyjNazwa, ' Nacisnij Enter.');
    Readln;
  end;
end;

begin
  Sciezka := ExtractFilePath(ParamStr(0));
  PlikASL := TStringList.Create;
  PlikBSL := TStringList.Create;
  TymczSL := TStringList.Create;
  WyjASL := TStringList.Create;
  WyjBSL := TStringList.Create;
  Jeden;
  Dwa;
  Trzy;
  PlikASL.Free;
  PlikBSL.Free;
  TymczSL.Free;
  WyjASL.Free;
  WyjBSL.Free;
end.
0

O wow nie spodziewałem się aż takiego zainteresowania :) Dziękuje bardzo i biorę się do roboty :D w razie jakiś niejasności napiszę :) co do plików to sam nie miałem ale utworzyłem coś takiego na próbę w załącznikach.

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