jak poprawnie odczytywać z pliku TXT?

0

Witam!

Mam zapisane w pliku wykres.txt wartości w taki sposób:

1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
10 100

i teraz chcialbym je sczytać tak zeby pierwszą kolumnne wpisalo do tablicy x, drugą do tablicy y i potem wykreśliło na na TChart. Napisałem do tego taki kod:

var
  Form1: TForm1;
  i, p : Integer;
  Lines : array of String;
  x_rys, y_rys : array of Integer;
  II, III : String;


    AssignFile(plik,'wykres.txt');
    if FileExists('wykres.txt') then
    begin
      reset(plik);
      i:=1;
      while not (EOF(plik)) do
      begin
        readln(plik, Lines[i]);

        p := Pos(#9, Lines[i]);
        II := Copy(Lines[i], 1, p-1);
        x_rys[i] := StrToInt(II);

        p := Pos(#9, Lines[i]);
        Delete(Lines[i], 1, p);
        p := Pos(#10#13, Lines[i]);
        III := Copy(Lines[i], 1, p-1);
        y_rys[i] := StrToInt(III);

        Form1.Series2.AddXY(x_rys[i],y_rys[i]);

        inc(i);
      end;
      CloseFile(plik);
    end;

Program się kompiluje lecz przy pobieraniu danych i rysowaniu sie wiesza. Gdzie mogę mieć błąd?

Proszę o pomoc :)

0

1 - Sprawdź czy plik istnieje przed jego użyciem (via AssignFile).
2 - Jaki rozmiar ma tablica Lines, x_rys i y_rys, bo z kodu wynika, że nie mają rozmiaru (SetLength).
3 - Indeksy tablic dynamicznych zaczynają się od 0 nie 1.
4 - Pozycja tabulatora nie zmieni się po wykonaniu Copy, więc nie ma potrzeby wyznaczać jej jeszcze raz.
5 - ReadLn nie umieszcza w buforze (Lines[i]) znaku końca wiersza #10#13, więc nie ma potrzeby wykonywania kolejnego Pos'a i Copy.

0

Dziękuję Loloki !! :)

Zastosowałem się do Twoich uwag i już procedura działa. Teraz kod wygląda tak:

procedure TForm1.Button3Click(Sender: TObject);
var
plik : TextFile;
begin
SetLength(x_rys, 1000);
SetLength(y_rys, 1000);
SetLength(Lines, 1000);

if CheckBox1.Checked=true then
begin
AssignFile(plik,'wykres.txt');
if FileExists('wykres.txt') then
begin
reset(plik);
i:=0;
while not (EOF(plik)) do
begin
readln(plik, Lines[i]);

    p := Pos(#9, Lines[i]);
    II := Copy(Lines[i], 1, p-1);
    x_rys[i] := StrToInt(II);

    Delete(Lines[i], 1, p);
    y_rys[i] := StrToInt(Lines[i]);

    Form1.Series2.AddXY(x_rys[i],y_rys[i]);

    inc(i);
  end;
  CloseFile(plik);
end;

end;
end;

Mam jeszcze pytanie jak można odczytać ten sam plik od 2 wiersza?
Jak bym miał dodane oznaczenie kolumn a one wiadomo nie były by przypisywane do tablic:

x y
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
10 100

Jeszcze raz wielkie dzięki loloki! :)

0

Możesz przed pętlą dać odczyt jednej linii wraz ze sprawdzeniem czy czytać, lub w pętli dodać zmienną pomocniczą (powiedzmy ominac:boolean ustawioną na true) i po niej sprawdzać, czy pierwsza linia była już czytana.
Lepsze jest pierwsze rozwiązanie, bo nie sprawdzasz warunku co iterację.

if not eof(plik) then  // 1
  readln(plik,Lines[0]); // 1 - i tak będzie potem nadpisana
while not (EOF(plik)) do
  begin
    readln(plik, Lines[i]);
    if ominac then  // 2
      ominac:=false  // 2
    else  // 2
      begin  // 2
        p := Pos(#9, Lines[i]);
        II := Copy(Lines[i], 1, p-1);
        x_rys[i] := StrToInt(II);
        Delete(Lines[i], 1, p);
        y_rys[i] := StrToInt(Lines[i]);
        Form1.Series2.AddXY(x_rys[i],y_rys[i]);
        inc(i);
      end; // 2
  end;

Wywal 1 lub 2 i będzie działać.

I jeszcze 2 rzeczy:
1 - Staraj się nie korzystać ze zmiennych globalnych, a jak już to deklaruj je jako pola formy.
2 - Używaj tagów kolorowania składni. Pierwszy post już Qyon poprawił. Tagi są takie same jak w html < język > < / język > (bez spacji) dla popularnych języków: delphi, cpp, php czy asm lub < code = język > < / code > dla bardziej "egzotycznych"* via sql, java i inne.

    • czytaj "nie dorobiły się jeszcze swoich tagów".
0

No i jeszcze raz wielkie dzięki Loloki! Zastosowałem się do pierwszego rozwiązania i pięknie działa :)

Dlaczego lepiej nie używać zmiennych globalnych? Nawet jak mam tylko jedną formatkę?

0

Taka jest ogólnie przyjęta koncepcja. Poza tym, jeśli masz zmienną lokalną, to nie musisz daleko odjeżdżać w kodzie, żeby zmienić/sprawdzić coś. Kod jest bardziej zwarty, a to ogólnie ułatwia pracę.

Powiedzmy że pracujesz nad czymś większym (pojedynczy moduł ma 2k+ linii kodu), i zauważyłeś, że jakaś wartość szybko wyjdzie poza zakres typu. Dla zmiennej lokalnej lekko podjedziesz do góry i zmieniasz, dla globalnej droga może być już nieco dłuższa ;) poza tym trzeba będzie jeszcze wrócić. Pal licho jak akurat klepiesz coś na końcu pliku, gorzej z szukaniem gdzieś w środku :>

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