Delphi działanie na plikach.

0

Potrzebuje zrobić następujący program. Tylko za bardzo, nie wiem jak to wszystko mam napisać w kompilatorze, żeby działało poprawnie. Możecie mnie jakoś naprowadzić?

Muszę pobrać losowe wersy z dwóch plików txt. Myślałem, o randomie tylko najpierw w pętli musiałbym policzyć ilość tych wszystkich wersów. Następie chciałem te dwie rzeczy wylosowane zapisać w jednym wersie, nowo utworzonym trzecim pliku txt i używając pętli for wykonać to X razy.

Wiem, że muszę mieć 3 zmienne TextFile oraz zmienną pomocniczą string w której będę zapisywał wylosowane wersy. Potrzebna jest również inicjalizacja przy użyciu komendy AssignFile oraz stworzenie nowego pliku poleceniem Rewrite,a poleceniem Reset odczytać dwa pliki z których będę losować.

4

No dobrze myślisz. Tylko zamiast tych textfilów assignów i innych użyj TStringList.LoadFromFile Gdzie wczytasz sobie wiersze z pliku i pod TStringList.Count będziesz miał ilość tych wierszy.

2
var a,b,c:TStringList;
var i:Integer;

a:=TStringList.Create();
b:=TStringList.Create();
c:=TStringList.Create();
try
  a.LoadFromFile('a.txt');
  b.LoadFromFile('b.txt');
  for i:=1 to X do c.Add(a[Random(a.Count)]+' '+b[Random(b.Count)]);
  c.SaveToFile('c.txt');
finally
  a.Free;
  b.Free;
  c.Free;
end;
0

Nie wiem czy wykładowca nie będzie chciał wykorzystania tamtych komend, które napisałem w pierwszym poście. Wieczorem przeanalizuje to z tym TStringList, bo wydaje się prostsze.

0
morodis napisał(a)

Tylko za bardzo, nie wiem jak to wszystko mam napisać w kompilatorze, żeby działało poprawnie. Możecie mnie jakoś naprowadzić?

Naprowadzając - kod pisze się w edytorze, a kompilatora nawet nie widać; Heh, widzę że Ty też padłeś ofiarą systemu nauczania - "otwórzcie kompilatory"... :]

babubabu napisał(a)

Tylko zamiast tych textfilów assignów i innych użyj TStringList.LoadFromFile [...]

Tu pasowało by uściślić;

Klasa TStringList jest przede wszystkim wygodna - zawiera kupkę bardzo przydatnych metod i właściwości; Niestety ma jeden minus - nie umożliwia buforowania odczytu, przez co cały plik musi zostać załadowany do pamięci (np. za pomocą metody LoadFromFile); Przy małych plikach nie ma to znaczenia, natomiast przy dużych i bardzo dużych owszem;

Druga sprawa to konstrukcja z AssignFile, Reset/Rewrite/Append i CloseFile; To nie jest konstrukcja przestarzała czy z jakiegokolwiek innego powodu niezalecana; Po pierwsze umożliwia buforowanie odczytu/zapisu, po drugie umożliwia obsługę błędów I/O, bez korzystania z mechanizmu wyjątków; Konstrukcja ta nie jest tak wygodna jak gotowe klasy kontenerów, jednak ma swoje plusy i warto mieć taką obsługę plików obcykaną;


Wracając do samego programu - nie podałeś @morodis informacji o tym, czy liczba linii w plikach jest ograniczona; W stricte szkolnych programach to jest norma; Zakładam, że nie może ich być więcej niż 50, a także że wspomniane X jest stałe - tego również nie podałeś; W razie czego zawsze możesz dopytać; Program pisany dla FPC:

const
  MAGIC_X = 20;

type
  TFileLines = array [0 .. 49] of String;

type
  TFileContent = record
    Count: Integer;
    Lines: TFileLines;
  end;

  procedure LoadFile(const AFileName: String; out AContent: TFileContent);
  var
    fInput: TextFile;
  begin
    AssignFile(fInput, AFileName);
    Reset(fInput);
    try
      AContent.Count := 0;

      while not EoF(fInput) do
      begin
        ReadLn(fInput, AContent.Lines[AContent.Count]);
        Inc(AContent.Count);
      end;
    finally
      CloseFile(fInput);
    end;
  end;

  procedure CreateCombinedFile(const AFileName: String; const AContentA, AContentB: TFileContent);
  var
    fOutput: TextFile;
    intX: Integer;
  begin
    AssignFile(fOutput, AFileName);
    ReWrite(fOutput);
    try
      for intX := 0 to MAGIC_X - 1 do
        WriteLn(fOutput, AContentA.Lines[Random(AContentA.Count)], ' ', AContentB.Lines[Random(AContentB.Count)]);
    finally
      CloseFile(fOutput);
    end;
  end;

var
  fcContentA, fcContentB: TFileContent;
begin
  Randomize();

  LoadFile('A.txt', fcContentA);
  LoadFile('B.txt', fcContentB);

  CreateCombinedFile('C.txt', fcContentA, fcContentB);
end.

To taki prosty przykład; Nie wiem czy zapoznali Was ze starymi obiektami (alokowanymi na stosie), w każdym razie można by zrobić z typu TFileContent właśnie stary obiekt, dodać do niego metodę RandomLine:

type
  TFileContent = object
    Count: Integer;
    Lines: TFileLines;
    function RandomLine(): String;
  end;

  function TFileContent.RandomLine(): String;
  begin
    Result := Lines[Random(Count)];
  end;

i użyć tej metody w pętli łączącej - wyjdzie nieco krócej i czytelniej:

for intX := 0 to MAGIC_X - 1 do
  WriteLn(fOutput, AContentA.RandomLine(), ' ', AContentB.RandomLine());

Ewentualnie zostawię to jako ciekawostkę.

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