Edycja wartości w liście

0

Temat pewnie niewiele tłumaczy, więc rozwinę tutaj co mam na myśli :)

Stworzyłem listę, gdzie rekord składa się m.in. ze zmiennej łańcuchowej (string). Program początkowo odczytuje kolejne linie tekstu do listy, kiedy napotka koniec pliku przestaje. Z tym nie mam żadnego problemu. Problem pojawia się za to w momencie, kiedy chcę zmodyfikować zmienną łańcuchową w pewnym określonym miejscu. Zamierzałem zrobić to w taki sposób: korzystam z dwóch wskaźników, pierwszy wskazuje na początek listy. Drugiemu przypisuję wartość pierwszego, a następnie wyszukuję odpowiedni rekord w liście. Zmieniam wartość stringa... i tu pojawia się problem.

Program to edytor tekstu, gdzie kursorem można sterować strzałkami. Rzecz w tym, że przy dopisywaniu nowego znaku litery są wypisywane, natomiast kiedy już dochodzi do ruchu za pomocą strzałek wyświetlana jest dawna zawartość. Mówiąc po polsku: program zachowuje się, jak gdyby istniały dwie różne listy i zależnie od tego czy piszę nowe znaki, czy poruszam się za pomocą strzałek program wypisuje jedną z nich.

Kod wrzucam tutaj: http://pastie.org/3197927 i tak - wiem że jest ohydny, nieskładny etc. ale w tym momencie zależy mi tylko na tym żeby to działało jak trzeba. Jeśli jest możliwość, wolałbym zmodyfikować program tak, żeby lista została w takim stanie w jakim jest (teoretycznie mógłbym zrobić listę w liście z pojedynczymi znakami zamiast stringa, ale to wiązałoby się z kompletną przebudową programu i zwyczajnie mogę się nie wyrobić w terminie). Tak więc, jeśli ktoś wytłumaczy jak zmodyfikować rekord w liście - będę bardzo wdzięczny. [Wszystkie tutoriale jakie widziałem pokazywały tylko jak wstawić element do tablicy.]

BTW. Program domyślnie próbuje odczytać plik "D:\text.txt", gdzie żadna z linii nie posiada więcej niż 255 znaków (ograniczenie stringa).

1

Rozumiem, że program będzie aplikacją konsolową? Tak rozumiem z treści wątku; Jeżeli tak, to niepotrzebnie przechowujesz łańcuch 255 znakowy; Konsola ma bodajże 80x50 znaków, więc wystarczył by Ci typ String[79] w deklaracji rekordu:

Line = record
  NrPorz: Integer;
  Linia: String[79];
  Nxt: PLine;
end;

Popracuj nad nazewnictwem identyfikatorów, bo mieszasz trochę - pół po angielsku, a pół po naszemu;

Mam jeszcze jedno pytanie: czy musisz korzystać z listy? Łatwiej było by skorzystać z macierzy, ale tylko pod warunkiem, że nie pracujesz na Turbo Pascal 7, bo z tego co wiem, nie ma zaimplementowanej obsługi macierzy dynamicznych, a tylko takie wchodzą w rachubę;

0

Jezu... już wiem gdzie miałem błąd. Wartości tablicy zmieniały się tak jak chciałem, problem jest gdzieś w poprzedniej procedurze printtext:

for j:=1 to 78-length(onscr[i]) do onscr[i]:=onscr[i]+' ';

Aż wstyd że tego nie zauważyłem i od razu napisałem. Muszę zmodyfikować tą procedurę i wszystko będzie cacy.

EDIT: wygląda na to że to wszystko przez korzystanie z funkcji length(). Dobrze kojarzę, że Pascal podczas korzystania z programu liczy ją tylko raz, a potem korzysta z tej konkretnej wartości?...

Dzięki za uwagi co do nazewnictwa, fakt faktem że muszę nad tym popracować. Tak, program musi być na listach, taki jest wymóg projektu. A co do stringa to jest większej długości dlatego, że program pozwala na poruszanie się w prawo/lewo jeśli łańcuch jest dłuższy niż to co musi być wyświetlone :)

Skoro już piszę, to spytam o jeszcze jedną rzecz. Mianowicie chodzi o samo wypisywanie. Gdy patrzę choćby na Free Pascala, Turbo Pascala czy jakikolwiek inny edytor zastanawia mnie jedna rzecz... jak można tak szybko wypisać wszystko na ekran? Chodzi mi o to, że gdy zmieniam linię w FPC w górę to wszystko od razu jest wyświetlone, bez żadnych przerw ani nic. Mój program wypisuje kolejne linie za pomocą writeln(linia) [że tak to w skrócie zapiszę] i niestety widać gołym okiem wypisywanie wszystkich linii przy zmianie wiersza o jeden w górę lub z dół. Trwa to poniżej pół sekundy, ale jednak przejście o kilka(-naście? -dziesiąt?) linii w górę/dół robi ogromną różnicę. Jest jakiś szybszy sposób na wypisanie wszystkiego na ekran?

0
n4zArh napisał(a)

wygląda na to że to wszystko przez korzystanie z funkcji length(). Dobrze kojarzę, że Pascal podczas korzystania z programu liczy ją tylko raz, a potem korzysta z tej konkretnej wartości?...

Oszalałeś...?! Czy mi się dobrze wydaje, czy Ty twierdzisz, że ten program:

program LengthProblem;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  sLine: String;
begin
  sLine := 'Delphi';
  WriteLn('Length: ', Length(sLine));

  sLine := 'Object Pascal';
  WriteLn('Length: ', Length(sLine));

  ReadLn;
end.

Dwa razy wypisze wartość 6..? Bo ja mam w konsoli taki wynik:

Length: 6
Length: 13

To jaki miała by sens, jakby działała tylko raz...? A poza tym gdzie tą "konkretną wartość" miała by przechowywać...?

0

Chodzi o to, że w Pascalu/Delphi granice pętli for są liczone tylko raz, przed pętlą. Jeśli zależą od jakichś warunków, które zmieniają się w trakcie działania pętli, to nie wpłynie to na ilość przebiegów pętli.

w takiej pętli:

for j:=1 to 78-length(onscr[i]) do onscr[i]:=onscr[i]+' ';

rzeczywiście tylko RAZ obliczone będą granice: dolna 1 i górna 78-length(onscr[i]). Ilość przebiegów pętli jest więc góry zdeterminowana.

Później mimo że długość stringa się zmienia, length() nie będzie wywoływane.

Mała demonstracja:

function siedem:integer;
begin
  writeln('siedem');
  siedem:=7;
end;

var i:integer;
begin
  for i:=1 to siedem do;
end.

Widać że siedem() jest wykonane tylko raz.
Nie ma to związku z samą funkcją length, która jest wykonywana normalnie jak każda inna — nie jest ona jakoś szczególnie tu winna.

0

W sumie to ta linijka jest winna:

for J := 1 to 78 - Length(onscr[I]) do
  onscr[I] := onscr[I] + ' ';

bo autor wykorzystując taką konstrukcję chce sztucznie przedłużyć ilość iteracji pętli; Stąd funkcja nie spełnia założenia;

Można natomiast pętlę for zastąpić inną: repeat .. until lub while .. do + dodatkowy licznik i będzie działać;

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