Konwertowałem algorytm C ++ na C #. Natknąłem się na to for loop:
for (u = b.size(), v = b.back(); u--; v = p[v])
b[u] = v;
Nie daje błędu w C ++, ale robi to w C # (nie można przekonwertować int na bool). Naprawdę nie mogę tego rozgryźć pętli for, gdzie jest warunek?
Czy ktoś może wyjaśnić?
PS. Żeby sprawdzić, czy aby dostosować WEKTOR do LISTY, czy b.back () odpowiada b [b.Count-1]?
u--
. Do oddzielenia poszczególnych częścifor
instrukcji używa się średników .; u-- != 0;
b
,u
,v
, itd. Jedynym powodem, dla którego zostały nazwane w ten sposób dlatego, że ktoś chce wyglądać elegancko, dokonując ich kod nieczytelny.do
znaczy w C ++” - dostanie tysiące trafień od początkujących szukających samouczka.Odpowiedzi:
Stan
for
pętli znajduje się pośrodku - między dwoma średnikami;
.W C ++ można umieścić prawie każde wyrażenie jako warunek: wszystko, co daje wynik zerowy, oznacza
false
; niezerowe oznaczatrue
.W twoim przypadku warunek jest taki
u--
: kiedy konwertujesz na C #, po prostu dodaj!= 0
:źródło
u = b.size() - 1
zamiast tego zainicjować go za pomocą .Wiele trafnych odpowiedzi, ale myślę, że warto wypisać ich odpowiednik w pętli while.
Jest równa:
Możesz rozważyć refaktoryzację do formatu while () podczas tłumaczenia na język C #. Moim zdaniem jest to wyraźniejsze, mniej pułapka dla nowych programistów i równie wydajne.
Jak zauważyli inni - ale aby moja odpowiedź była kompletna - aby działała w C #, musisz zmienić
while(u--)
nawhile(u-- != 0)
.... lub
while(u-- >0)
na wypadek, gdybyś zaczął negatywnie. (OK,b.size()
nigdy nie będzie ujemne - ale rozważ ogólny przypadek, w którym być może coś innego zainicjowało u).Lub, żeby było jeszcze jaśniej:
Lepiej być klarownym niż zwięzłym.
źródło
while (u-- >0)
formularzem. Jeśli odstępy zostaną pomieszane, możesz skończyć z pętlą „w dół do zera”:,while (u --> 0)
która na pierwszy rzut oka wprowadza wszystkich w błąd. ( Nie jestem pewien, czy jest to poprawne C #, ale jest w C, i myślę, że może być również w C ++? )for
zamiastwhile
właśnie, że można umieścić inicjalizacji i góra / dół w jednym sprawozdaniu, a nie koniecznie uczynić kod trudniejsze do zrozumienia. W przeciwnym raziefor
w ogóle nie powinniśmy używać .--
token, po którym następuje>
token. Dwóch oddzielnych operatorów. Pętla „w dół do zera” jest po prostu prostą kombinacją post-dekrementacji i większego niż. Przeciążanie operatorów C ++ nie tworzy nowych operatorów, po prostu zmienia ich przeznaczenie.Warunkiem jest
u--;
, bo to jest w drugiej pozycji do instrukcji.Jeśli wartość
u--;
jest różna od 0, zostanie zinterpretowana jakotrue
(tj. Niejawnie rzutowana na wartość logicznątrue
). Jeśli zamiast tego jego wartość wynosi 0, zostanie rzutowana nafalse
.To bardzo zły kod .
Aktualizacja: omówiłem pisanie pętli „for” w tym poście na blogu . Jego zalecenia można podsumować w następujących akapitach:
Ten przykład wyraźnie narusza te zalecenia.
źródło
Będzie to forma Twojej pętli w języku C #.
Po prostu zastąp odpowiednik size () i back ().
To, co robi, odwraca listę i przechowuje w tablicy. Ale w C # mamy bezpośrednio zdefiniowaną przez system funkcję do tego. Więc nie musisz również pisać tej pętli.
źródło
v = b.back();
z for intializatora, nie zmieniłeś tylko sposobu, w jaki to działa, ponieważv = p[v]
jest on nadpisany przezv = b.back();
było wykonywane raz przed rozpoczęciem iteracji iv = p[v]
było wykonywane na początku każdej iteracji. W tej wersji C #v = p[v]
jest nadal wykonywana na początku każdej iteracji, alev = b.back();
jest wykonywana zaraz po niej, zmieniając wartośćv
dla następnej instrukcjib[u] = v;
. (być może pytanie zostało zredagowane po przeczytaniu)v = b.back()
. Masz go wykonującego się przy każdej iteracji pętli zamiast tylko pierwszej - nie wiemy, co toback()
robi (czy są jakieś skutki uboczne? Czy zmienia wewnętrzną reprezentacjęb
?), Więc ta pętla nie jest równoważna z tą w pytanie.v = b.back()
został przeniesiony poza pętlę, nad nią. (Ponadto, jeśli próbujesz komuś odpowiedzieć, użyj@
przed jego nazwiskiem, abyśmy otrzymali powiadomienie)to inicjalizacja.
jest warunkiem.
jest iteracją
źródło
Warunek jest wynikiem
u--
, którego jest wartościąu
sprzed obniżenia wartości.W C i C ++ an
int
można zamienić na bool przez niejawne wykonanie!= 0
porównania (0 tofalse
, wszystko inne jesttrue
).b.back()
to ostatni element w kontenerze, czylib[b.size() - 1]
kiedysize() != 0
.źródło
W języku C wszystko niezerowe znajduje się
true
w kontekstach „boolowskich”, takich jak warunek zakończenia pętli lub instrukcja warunkowa. W języku C # trzeba zrobić to sprawdzić jednoznaczne:u-- != 0
.źródło
Jak stwierdzili inni, fakt, że C ++ ma niejawne rzutowanie na wartość logiczną, oznacza, że warunkowe jest
u--
, które będzie prawdziwe, jeśli wartość jest różna od zera.Warto dodać, że pytając „gdzie jest warunek”, masz fałszywe założenie. W obu językach C ++ i C # (i innych językach o podobnej składni) możesz mieć pusty warunek. W tym przypadku jest zawsze wartość true, więc pętla trwa wiecznie, albo aż niektórych innych wyjść warunku (przez
return
,break
lubthrow
).Rzeczywiście, dowolną część instrukcji for można pominąć, w takim przypadku po prostu nie jest wykonywana.
Ogólnie
for(A; B; C){D}
lubfor(A; B; C)D;
staje się:Można pominąć jeden lub więcej z A, B, C lub D.
W rezultacie pewna przysługa
for(;;)
dla nieskończonych pętli. Robię to, ponieważ chociażwhile(true)
jest bardziej popularne, czytam to jako „dopóki prawda przestanie być prawdą”, co brzmi nieco apokaliptycznie w porównaniu z moim czytaniemfor(;;)
jako „na zawsze”.To kwestia gustu, ale ponieważ nie jestem jedyną osobą na świecie, która lubi
for(;;)
, warto wiedzieć, co to znaczy.źródło
wszystkie odpowiedzi są prawidłowe: -
pętla for może być używana na różne sposoby w następujący sposób:
źródło
W powyższym kodzie
u
iv
są inicjowane za pomocąb.size()
ib.back()
.Za każdym razem, gdy warunek jest sprawdzany, wykonuje również instrukcję dekrementacji, tj
u--
.for
Pętla wyjdzie kiedyu
będzie0
.źródło
Błąd napotkany w samym C # rozwiązuje wątpliwości. Pętla for wyszukuje plik
warunek do rozwiązania. Jak wiemy,
ale C # nie może tego przetworzyć samodzielnie, w przeciwieństwie do C ++. Zatem warunek, którego szukasz, jest
ale musisz jawnie podać warunek w C # jako
lub
Ale nadal staraj się unikać tego rodzaju praktyk kodowania. Plik
podana powyżej w odpowiedzi jest jedną z najbardziej uproszczonych wersji twojego
źródło
Jeśli jesteś przyzwyczajony do C / C ++, ten kod nie jest trudny do odczytania, chociaż jest dość zwięzły i niezbyt świetny. Pozwólcie więc, że wyjaśnię części, które są bardziej Cismem niż czymkolwiek innym. Po pierwsze, ogólna składnia pętli C for wygląda następująco:
Kod inicjujący jest uruchamiany raz. Następnie warunek jest testowany przed każdą pętlą i na koniec po każdej pętli wywoływany jest przyrost. Więc w twoim przykładzie znajdziesz warunek
u--
Dlaczego
u--
działa jako warunek w C, a nie C #? Ponieważ C niejawnie konwertuje wiele rzeczy, zbytnio jeździ i może powodować problemy. Dla liczby wszystko, co jest niezerowe, jest prawdą, a zero jest fałszem. Więc będzie odliczać od b.size () - 1 do 0. Efekt uboczny w stanie jest trochę denerwujący i lepiej byłoby umieścić go w przyrostowej części pętli for, chociaż dużo C kod to robi. Gdybym to pisał, zrobiłbym to bardziej tak:Przyczyna tego jest przynajmniej dla mnie jaśniejsza. Każda część pętli for wykonuje swoją pracę i nic więcej. W oryginalnym kodzie warunkiem była modyfikacja zmiennej. Część inkrementacyjna robiła coś, co powinno znajdować się w bloku kodu itp.
Operator przecinka może również rzucać ci w pętlę. W C coś
x=1,y=2
wygląda jak jedna instrukcja, jeśli chodzi o kompilator i pasuje do kodu inicjalizacji. Po prostu ocenia każdą z części i zwraca wartość ostatniej. Na przykład:wydrukowałby 2.
źródło