Dziwne zachowanie funkcji w Delphi

Dziwne zachowanie funkcji w Delphi
KM
  • Rejestracja:około 9 lat
  • Ostatnio:10 miesięcy
  • Lokalizacja:Łomża
  • Postów:34
0

Cześć, mam funkcję:

Kopiuj
function UsunZnaki(b: String): String;
begin
Delete(b,Pos('-',b),1);
Delete(b,Pos(':',b),1);
if Pos('-',b) > 0 then UsunZnaki(b);
if Pos(':',b) > 0 then UsunZnaki(b);
Result := b;
end;

funkcja dostaje zmienną w której występuje '-' i ':' i w trakcje działania krok po kroku funkcja działa prawidłowo, usuwa mi zbędne znaki. W chwili kiedy usunie już wszystkie zbędne znaki przechodzi do linii Result := b; i tak mi się wydaje że powinna zakończyć się funkcja i wartość zmiennej b powinna wrócić do miejsca wywołania funkcji. Tak nie jest, funkcja zaczyna odtwarzać wcześniejszą wartość zmiennej b tzn, wstawia do zmiennej '-' i ':' i po odtworzeniu zmiennej zwraca ją do miejsca wywołania.
Czemu tak się dzieje ?

Wywołanie funkcji wygląda tak:

Kopiuj
a := UsunZnaki(nazwa);
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:Tuchów
  • Postów:12175
2
Kopiuj
if Pos('-',b) > 0 then UsunZnaki(b);
if Pos(':',b) > 0 then UsunZnaki(b);

Rezultat wywołań rekurencyjnych nie trafia do żadnej zmiennej, więc czego się spodziewałeś? Do tego przekazujesz wejściowy łańcuch przez wartość, co po pierwsze jest najwolniejszym sposobem podawania łańcuchów do procedur/funkcji, a po drugie, każde rekursyjne wywołanie dostaje kopię łańcucha i zmiany na nim dokonane są widoczne jedynie lokalnie (w jednej instancji funkcji, poza nią już nie);

Lepszym rozwiązaniem było by po prostu przepisywanie znaków z łańcucha wejściowego do rezultatu:

Kopiuj
function RemoveChars(const AString: String): String;
var
  LChar: Char;
begin
  Result := '';

  for LChar in AString do
    if not (LChar in [':', '-']) then
      Result += LChar;
end;

lub tak:

Kopiuj
function RemoveChars(const AString: String; const ACharsToRemove: TSysCharSet): String;
var
  LChar: Char;
begin
  Result := '';

  for LChar in AString do
    if not (LChar in ACharsToRemove) then
      Result += LChar;
end;

lub skorzystanie z wbudowanych funkcji do zamiany znaków, np. StringReplace.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 4x, ostatnio: flowCRANE
KM
Nie działa mi ta konstrukcja pętli for (for LChar in AString do), kompilator wyświetla: Operator not applicable to this operand type
flowCRANE
Na temat odpowiadaj w postach;
U3
  • Rejestracja:prawie 13 lat
  • Ostatnio:prawie 2 lata
  • Postów:196
0
Kopiuj
Result += LChar;

Zrób z plusa dwukropek

kaczus
raczej Result := Result + LChar; A może w nowszych delphi jest zaimplementowany operator += - który oznacza dokładnie to co na pisał przedpiszca. Nie miałem okazji się bawić nowszymi wersjami, więc nie potwierdzę ani nie zaprzeczę :)
U3
Korzystam od D7 do XE10.1 więc dementuję plotkę, jakoby był taki operator.
kaczus
tak czy inaczej, obawiam się, że sama zamiana + na dwukropek, może nie być wystarczająca :)
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:Tuchów
  • Postów:12175
0
user322 napisał(a)

Zrób z plusa dwukropek

Nie, to nie będzie to samo - przydałoby się najpierw ten kod zrozumieć, zanim się cokolwiek podpowie; Jak zamieni + na : to rezultatem funkcji zawsze będzie jeden znak; Tak więc aby "naprawić" ten kod, należy skorzystać ze wskazówki @kaczusa (na temat piszemy w postach), czyli wykorzystać schemat X := X + Y;

Korzystam od D7 do XE10.1 więc dementuję plotkę, jakoby był taki operator.

To nie jest żadna plotka - nie zauważyłem, że wątek dotyczy Delphi i podałem kod dla mnie natywny, czyli dla FPC; Poza tym szkoda, że Delphi nadal nie wspiera tego operatora, a tym samym nie umożliwia skracania zapisu tego typu dopisań.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 3x, ostatnio: flowCRANE
U3
Nie napisałem, że się nie zgadzam z komentarzem od kaczusa, wręcz przeciwnie ma rację - za szybko wklepałem odpowiedź.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.