nieelegancki break?

cepa
  • Rejestracja: dni
  • Ostatnio: dni
0
ŁF napisał(a)

co goto jako wyjścia z zagnieżdżonej pętli - od kilku lat większość nowoczesnych jezyków programowania ma cos takiego jak wyjątki. pozwalają one nie tylko wyjść z pętli, ale dowolnie zagnieżdżonych wywołań funkcji (np. przy rekurencji).

no w C tez to jest - dalekie skoki setjmp.h - tyle ze tak czy siak mechanizm przypomina goto :P

Marooned
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
0
Marcin_ napisał(a)

w petli for (i=0; i<100; i++) powiniem zrobic "if (costam) i=100;
Akurat w C (i jemu podobnych) jest to możliwe, ale w Pascalu/Delphi nie można zmieniać licznika, gdyż nie jest on analizowany za każdym przejściem pętli.

Nawet pomoc Borlanda o tym pisze:

It is illegal to assign a value to the for loop control variable inside the for loop.

If the purpose is to leave the loop prematurely, <font color="red">use a break or goto statement</span>.

Kopiuj
program Produce;

var
  I: Integer;
  A: array [0..99] of Integer;
begin
  for I := 0 to 99 do begin
    if A[I] = 42 then
      I := 99;
  end;
end.

In this case, the programmer thought that assigning 99 to I would cause the program to exit the loop.

Kopiuj
program Solve;

var
  I: Integer;
  A: array [0..99] of Integer;
begin
  for I := 0 to 99 do begin
    if A[I] = 42 then
      Break;
  end;
end.

<font color="red">Using a break statement is a cleaner way to exit out of a for loop.</span>

Ja nie widzę żadnych przeciwskazań w używaniu break - co więcej - uważam to za jedno z najbardziej przydatnych słów kluczowych języka [piszę w C++ / C# / PHP / JS więc wsie C-podobne, gdzie mogę ingerować w licznik].

Przez myśl mi nie przeszło tak koszmarne rozwiązanie, jak if (cos) i=100;
Jeśli pominąć optymalizator, to taki kod będzie dłuższy i wolniejszy o kilka instrukcji w Assemblerze oraz mniej czytelny dla człowieka, bo nie zawsze mamy jawną wartość końca pętli, przykład [tak oczywiście się nie robi, ale to tylko przykład]

Kopiuj
for (int i=0; i<JakasFunkcja(); i++)
{smth = doSmth();
 ...
 if (smth) break;
}

i co, miałbym tam dać
if (smth) i=JakasFunkcja(); ? nonsens...

A co jeśli mamy taki kod:

Kopiuj
for (float i=0; i<=20.2; i++)
{
...
if (smth) i=20.3; //co to w ogóle ma być? porażka, nawet jak dam ładniej i=30
}
Kooba
  • Rejestracja: dni
  • Ostatnio: dni
0

Słucham i nie wierze, parę osób twierdzi ze programuje od x lat i nigdy nie użyło break... przecież to jest tak oczywista i wygodna instrukcja ze nie wyobrażam sobie programowania bez niej (oczywiście pomijam używanie jej wewnątrz instrukcji switch co jest absolutnie nieuniknione)..

Może ja jestem dziwny ale wydaje mi sie ze to "nigdy nie użyłem break" jest z Waszej strony wyolbrzymieniem..

  • Rejestracja: dni
  • Ostatnio: dni
0

Hm, osobiscie nie widze nic zlego w stosowaniu goto/break Skoro jest to element chyba wszystkich liczacych sie jezykow, to dlaczego nie korzystac z tego? Inna sprawa, ze czasem mozna obejsc problem w znacznie lepszy sposob. Jestem po prostu przeciwnikiem zasad typu: lepiej tego nie uzywac.
Jezyk jest przeznaczony dla programisty, a to jest ktos kto ma wiedziec co dokladnie robi jego kod i jak mozna go jeszcze dopiescic. I jezeli uwaza, ze warto uzyc break/goto to dlaczego nie?

Przeciez tak bardzo lubiane przez wszystkich switch/case of (czy jakby to nazwac) to tez nic innego jak seria etykiet goto. A nie spotkalem sie jeszcze z zalecaniem kodu typu:

Kopiuj
if(a == 1) { do1(); }
else if(a == 2) { do2(); }
....
else { doelse(); }

Zamiast zwyklego switch(a) { }
Poza tym piszac jakies male aplikacje sieciowe zawsze uzywam while(1) po listen();
W jaki sposob moglbym wyjsc z tego while bez uzywania break?

Krytykowanie tych instrukcji jest smieszne...</cpp>

Adam.Pilorz
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2998
0
Kooba napisał(a)

Słucham i nie wierze, parę osób twierdzi ze programuje od x lat i nigdy nie użyło break... przecież to jest tak oczywista i wygodna instrukcja ze nie wyobrażam sobie programowania bez niej (oczywiście pomijam używanie jej wewnątrz instrukcji switch co jest absolutnie nieuniknione)..

Może ja jestem dziwny ale wydaje mi sie ze to "nigdy nie użyłem break" jest z Waszej strony wyolbrzymieniem..

W instrukcji switch jest to trochę inna historia - tam instrukcja break; działa inaczej, nie licząc faktu, że w Delphi czegośtakiego nie ma :). Jest coś takiego:
case zmienna of
wartosc: instrukcja lub begin instrukcje end;
wartosc2: instrukcja lub begin instrukcje end;
else instrukcja lub begin instrukcje end;
end;
Więc tu nie ma co się break'a doszukiwać. Osobiście w pętlach nigdy nie widziałem potrzeby używania break. A programuję jak już wspomniałem wcześniej ca. 14 lat (nie liczę wcześniejszych elementów w BASIC'u). I na prawdę nic nie wyolbrzymiam.

06
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2440
0
Adam.Pilorz napisał(a)

W instrukcji switch jest to trochę inna historia - tam instrukcja break; działa inaczej

Błąd. Idea break'a w switch'u jak i we wszelakich pętlach jest taka sama - powoduje 'wyskoczenie' poza instrukcje ;)

Adam.Pilorz
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2998
0

Idea może tak, ale faktyczne zastosowanie jest inne :). Tzn. break w pętli jest jednym ze sposobów wyjścia z pętli, w pewnym sensie nienaturalnym, zaś break w switch jest jedynym sposobem na normalne oddzielenie przypadków.

//jedynym? zapomniałeś o goto :D - M

06
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2440
0

Idea może tak, ale faktyczne zastosowanie jest inne[...]

Pisałeś, że działa inaczej, a to akurat nie jest prawdą ;) Dla rozjaśnienia ów idei potraktuj tego break'a jak instrukcję goto, która "skacze" za blok switch/for/while. Efekt (i instrukcja) będzie ten sam, a jak twierdzisz zastosowania różne.

break w pętli jest jednym ze sposobów wyjścia z pętli, w pewnym sensie nienaturalnym

Tak "nienaturalnym" jak "nienaturalnym" jest możliwość tworzenia pętli bezwarunkowych... :]

AP
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3079
0
Kooba napisał(a)

Słucham i nie wierze, parę osób twierdzi ze programuje od x lat i nigdy nie użyło break... przecież to jest tak oczywista i wygodna instrukcja ze nie wyobrażam sobie programowania bez niej (oczywiście pomijam używanie jej wewnątrz instrukcji switch co jest absolutnie nieuniknione)..

Może ja jestem dziwny ale wydaje mi sie ze to "nigdy nie użyłem break" jest z Waszej strony wyolbrzymieniem..
Ja się wytłumaczę :P Oczywiście znam i stosuje break; ale nie w pętli for. po prostu jeśli wiem, że nie będę musiał do końca wykonywać danych instrukcji to stosuje raczej while (a nie for) i to jest pierwsza myśl jaka przychodzi mi do głowy przy zmaganiach z tego typu problemami. Do samej instrukcji break; nic nie mam i powiem nawet, że nie raz jej używałem i rzeczywiście jest bardzo przydatna.</image>

Adam.Pilorz
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2998
0
0x666 napisał(a)

Idea może tak, ale faktyczne zastosowanie jest inne[...]

Pisałeś, że działa inaczej, a to akurat nie jest prawdą ;) Dla rozjaśnienia ów idei potraktuj tego break'a jak instrukcję goto, która "skacze" za blok switch/for/while. Efekt (i instrukcja) będzie ten sam, a jak twierdzisz zastosowania różne.

Fakt, źle się wyraziłem.

0x666 napisał(a)

break w pętli jest jednym ze sposobów wyjścia z pętli, w pewnym sensie nienaturalnym

Tak "nienaturalnym" jak "nienaturalnym" jest możliwość tworzenia pętli bezwarunkowych... :]

W pewnym sensie jest to nienaturalne. Wszak w ten sposób piszesz, że pętla ma się wykonywać w nieskończoność, a potem nagle każesz zakończyć jej działanie. Dla mnie dużo naturalniejszym jest odpowiednie skonstruowanie warunku i pominięcie break. Wtedy patrząc na pętlę "z zewnątrz" od razu widać, co powoduje jej przerwanie, do czego ma doprowadzić w pewnym sensie.

06
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2440
0
Adam.Pilorz napisał(a)

W pewnym sensie jest to nienaturalne. Wszak w ten sposób piszesz, że pętla ma się wykonywać w nieskończoność, a potem nagle każesz zakończyć jej działanie

No i co z tego??? Jeśli dany język programowania daje mi taką możliwość to ją w miare potrzeb wykorzystuje.

Dla mnie dużo naturalniejszym jest odpowiednie skonstruowanie warunku i pominięcie break.

Dziwna sprawa. Siedząc, jak mówisz, 14 lat w programowaniu powinieneś wiedzieć, że nie zawsze da się obliczyć parametry wejściowe pętli... Ha!! nie zawsze się to opłaca ze względów wydajnościowych. Owszem można to zrobić bez break, ale wierz mi, kod wcale nie będzie czytelniejszy (szczególnie gdy tych warunków przewania pętli jest wiele) ;) Doświadczony programista widząc break wewnątrz bloku for/while wie, że jest to bezwarunkowe i natychmiastowe przerwanie pętli (pomimo głównego warunku, który na ogół definiuje tylko zakres działania pętli), a widząc takie freak'i w stylu:

Kopiuj
for (i=0; i<100; i++)
{
   ...

   if (costam) i=100;
   else
   {
     ...
        if (inne_costam) i=100;
        else
       {
         ...
       }
   }
}

musi się zastanawiać czy to po prostu zmiana parametrów algorytmu wewnątrz bloku czy też procedura "ewakuacji" z pętli ;p. Dodaj do tego jeszcze braces hell i już masz kod nieczytelny :] Takie instrukcje jak break i continue są właśnie po to, żeby kod stał się bardziej spójny, a przez to czytejniejszy.

vixen03
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 475
0

problem z goto oprocz kwesti czytelnosci/nieczytelnosci jest taki, ze po jego wywolaniu nie nastepuje wywolanie destruktorow i mozna doprowadzic do wyciekow pamieci.

nie wiem natomiast jak to w wypadku break.

06
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2440
0

W obu przypadkach wywoływane są destruktory (w BCB) :] goto to nie instrukcja assemblera [!!!]

Kopiuj
    switch(...)
    {
    case 0:
        {
            std::string text;
            goto END_SWITCH;
        }
    }
END_SWITCH:


    for(int i=0;i<2;i++)
    {
        std::string text;
        goto END_LOOP;
    }
END_LOOP:
  • Rejestracja: dni
  • Ostatnio: dni
0

moim zdaniem nie ma większej różnicy między między break a goto, z punktu widzenia kodu maszynowego są sobie bliskie, jednak goto <ort>kojażone </ort>jest językami liniowymi(listowymi) czy jak one się tak dokładnie wabią np. Basic (nie mówię o VisualBasicu czy podobnych).

Goto było wtedy <ort>wykożystywane </ort>jako przeskok do pseduprocedur i wyskok z nich.

Ciekawą rzecz czytałem kiedyś (dorwałem jakiś starszy podręcznik od C, ANSI C) : break z licznikiem łamanych pętli, np :
break 3 na wyskoczenie z 3 pętli naraz

nigdy tego nie próbowałem; nie w wszystkich kompilatorach działa poprawanie.

vixen03
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 475
0
0x666 napisał(a)

W obu przypadkach wywoływane są destruktory (w BCB) :]

[wstyd] racja, ryplo mi sie z dalekim goto.

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.