Funkcja zwracająca pierwszy "wolny" indeks tablicy

0

Witam, w programie potrzebuję mieć dostęp do informacji, który wiersz będzie pierwszym wolnym, robię to za pomocą tablicy boolean'ów, napisałem następującą funkcję

function wolny_wiersz(var wiersze : array of boolean):byte; 
    var 
        i : byte; 
        jest : boolean; 
    begin     
        i:= 1; 
        jest:= false; 
        while (not jest) and (i <= 50) do 
            if wiersze[i]=true then inc(i)
            else begin
                wolny_wiersz:= i;
                jest:= true;
                wiersze[i]:= true;
            end; 
        if not jest then wolny_wiersz:= 51;   
    end;

jednak zwraca ona złe wartości - np. gdy wiersze[1]:= true to funkcja dalej zwraca wartość "1", gdy wiersze[2]:=true to zwraca "2" itd. Nie wiem jak poprawić ten kod, by funkcja działała tak, że będzie zwracała indeks w którym jest pierwsza z wartości false a nie ostatnia z wartości true..
Pozdrawiam

1

Przede wszystkim nie kombinować:

function wolny_wiersz(var wiersze:array of boolean):Integer; 
var  i:Integer;
begin     
  for i:=0 to Length(wiersze)-1 do
  begin
    if not wiersze[i] then
    begin
      wolny_wiersz:=i;
      Exit;
    end;
  end;
  wolny_wiersz:=Length(wiersze);
end;
4

Do funkcji przekazujesz open array, która zawsze jest indeksowana od 0, a inicjujesz licznik i na 1, więc zawsze pomijasz pierwszy element macierzy;

Poza tym możesz uniknąć każdorazowego wyszukiwania pierwszego wolnego miejsca, jeśli zadeklarujesz sobie zmienną (lub prywatne pole w klasie) i w nim zapamiętasz indeks tego elementu; Przy ustawianiu danego elementu pola sprawdzasz czy jego indeks jest mniejszy niż indeks pierwszego wolnego i jeśli tak - wpisujesz indeks do zmiennej; W ten sposób zamiast przeszukiwać całą macierz, za każdym razem masz go od razu w zmiennej (czy tam polu);

A jeśli koniecznie chcesz wyszukiwać, to zrób tak jak podał poprzednik, tyle że ustal sobie wartość np. -1 w przypadku, gdy macierz będzie cała zapełniona:

// jeśli wolny wiersz nie zostanie znaleziony, funkcja zwróci -1
function WolnyWiersz(var Wiersze: array of Boolean): Integer;
begin
  Result := High(Wiersze);

  while Result >= 0 do
    if not Wiersze[Result] then
      Exit
    else
      Dec(Result);
end;

Krótsza wersja :]

A jeśli potrzeba znaleźć pierwszy wolny wiersz szukając od początku pętli (co i tak jest kwestią umowną) to licznik pętli trzeba wykorzystać na odwrót:

// jeśli wolny wiersz nie zostanie znaleziony, funkcja zwróci -1
function WolnyWiersz(var Wiersze: array of Boolean): Integer;
begin
  Result := Low(Wiersze);

  while Result <= High(Wiersze) do // lub while Result < Length(Wiersze) do
    if not Wiersze[Result] then
      Exit
    else
      Inc(Result);

  Result := -1;
end;
0

Dziękuje obu panom, wykorzystałem sposób @_13th_Dragon z drobnymi modyfikacjami

function wolny_wiersz(var wiersze:array of boolean):Integer;
    var
        i:Integer;
    begin     
        for i:=0 to 49 do
        begin
            if not wiersze[i] then
            begin
                wolny_wiersz:=i+1;
                wiersze[i]:=true;
                exit;
            end;
        end;
    end;

bo potrzebowałem zapamiętać, że ten wiersz już wolny wcale nie jest, ale obie odpowiedzi poszerzają moją wiedzę programistyczną, jeszcze raz wielkie dzięki :)

0

A zastanawiałeś się co twoja "modyfikacja" zwróci jak nie znajdzie wolnego?

0

@revenantq - masz trochę zbędnego i nie do końca bezpiecznego kodu; Poza tym Twoja metoda wyszukiwania jest wadliwa z założenia, dlatego że po znalezieniu pustego elementu zwracasz indeks następnego nie sprawdzając, czy faktycznie jest wolny;

Dlatego też polecam stosować się do wskazówek, a finalna wersja funkcji na pewno będzie działać prawidłowo i w każdych warunkach;

A co do Twojego kodu, to w FPC (być może w Delphi też, ale trzeba by sprawdzić) procedura Exit może przyjmować argument, który zostanie zwrócony przez funkcję, w której się znajduje; Twóją pętlę można skrócić:

function WolnyWiersz(var Wiersze: array of Boolean): Integer;
var
  I: Integer;
begin
  Result := -1;

  for I := Low(Wiersze) to High(Wiersze) do
    if not Wiersze[I] then
    begin
      Wiersze[I] := True;
      Exit(I + 1);
    end;
end;

I na koniec polecam stosować funkcje Low oraz High, dzięki którym w pętle staną się bardziej elastyczne.

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