Ich habe einen C ++ - Algorithmus in C # konvertiert. Ich bin auf diese for-Schleife gestoßen:
for (u = b.size(), v = b.back(); u--; v = p[v])
b[u] = v;
Es gibt keinen Fehler in C ++, aber in C # (int kann nicht in bool konvertiert werden). Ich kann das für die Schleife wirklich nicht herausfinden, wo ist die Bedingung?
Kann mir bitte jemand erklären?
PS. Nur um zu überprüfen, um einen VEKTOR an eine LISTE anzupassen, entspricht b.back () b [b.Count-1]?
u--
. Die Semikolons werden verwendet, um die verschiedenen Teile derfor
Anweisung abzugrenzen .; u-- != 0;
b
,u
,v
etc. Der einzige Grund , warum sie so genannt wurden, weil jemand , indem sie ihr Code nicht lesbar suchen Smart wollte.do
das in C ++?" - erhalten Tausende von Treffern von Anfängern, die nach einem Tutorial suchen.Antworten:
Der Zustand der
for
Schleife liegt in der Mitte - zwischen den beiden Semikolons;
.In C ++ ist es in Ordnung, fast jeden Ausdruck als Bedingung zu setzen: Alles, was als Null ausgewertet wird, bedeutet
false
; Nicht-Null-Mitteltrue
.In Ihrem Fall lautet die Bedingung
u--
: Wenn Sie in C # konvertieren, fügen Sie einfach Folgendes hinzu!= 0
:quelle
u = b.size() - 1
stattdessen mit initialisieren .Viele genaue Antworten, aber ich denke, es lohnt sich, die entsprechende while-Schleife aufzuschreiben.
Ist äquivalent zu:
Bei der Übersetzung in C # können Sie eine Umgestaltung in das while () -Format in Betracht ziehen. Meiner Meinung nach ist es klarer, für neue Programmierer weniger eine Falle und ebenso effizient.
Wie andere bereits betont haben - aber um meine Antwort zu vervollständigen -, müssten Sie zu C # wechseln
while(u--)
, damit sie in C # funktioniertwhile(u-- != 0)
.... oder
while(u-- >0)
nur für den Fall, dass du negativ anfängst. (OK,b.size()
wird niemals negativ sein - aber betrachten Sie einen allgemeinen Fall, in dem vielleicht etwas anderes u initialisiert wurde).Oder um es noch deutlicher zu machen:
Es ist besser klar zu sein als knapp zu sein.
quelle
while (u-- >0)
Formular vorsichtig sein . Wenn der Abstand durcheinander gerät, kann es zu einer Schleife "bis Null" kommenwhile (u --> 0)
, die alle auf den ersten Blick verwirrt. ( Ich bin nicht sicher, ob es gültig ist C #, aber es ist in C, und ich denke, es kann auch in C ++ sein? )for
stattwhile
ist genau, dass Sie die Initialisierung und das Inkrement / Dekrement in einer Anweisung zusammenfassen, und das macht den Code nicht unbedingt schwieriger zu verstehen. Andernfalls sollten wir überhaupt nicht verwendenfor
.--
Token gefolgt von einem>
Token analysiert . Zwei separate Operatoren. Eine "bis auf Null" -Schleife ist nur eine einfache Kombination aus Nachdekrementierung und Größer als. Durch das Überladen von C ++ - Operatoren werden keine neuen Operatoren erstellt, sondern nur vorhandene neu verwendet.Die Bedingung ist
u--;
, weil es sich an der zweiten Position der for- Anweisung befindet.Wenn sich der Wert von
u--;
von 0 unterscheidet, wird er interpretiert alstrue
(dh implizit in den booleschen Wert umgewandelttrue
). Wenn stattdessen der Wert 0 ist, wird er in umgewandeltfalse
.Das ist sehr schlechter Code .
Update: Ich habe das Schreiben von "for" -Schleifen in diesem Blog-Beitrag besprochen . Ihre Empfehlungen können in den folgenden Absätzen zusammengefasst werden:
Dieses Beispiel verstößt eindeutig gegen diese Empfehlungen.
quelle
Dies ist die C # -Form Ihrer Schleife.
Ersetzen Sie einfach das Äquivalent für Größe () und Rückseite ().
Es kehrt die Liste um und speichert sie in einem Array. Aber in C # haben wir direkt eine systemdefinierte Funktion dafür. Sie müssen diese Schleife also auch nicht schreiben.
quelle
v = b.back();
aus dem for-Intializer haben Sie nicht nur die Funktionsweise geändert, da derv = p[v]
vonv = b.back();
wurde einmal vor dem Start der Iterationenv = p[v]
ausgeführt und wurde zu Beginn jeder Iteration ausgeführt. In dieser C # -Versionv = p[v]
wird zu Beginn jeder Iteration noch ausgeführt, jedochv = b.back();
direkt danach ausgeführt, wobei der Wert vonv
für die nächste Anweisung geändert wirdb[u] = v;
. (Vielleicht wurde die Frage bearbeitet, nachdem Sie sie gelesen haben)v = b.back()
. Sie haben es bei jeder Schleifeniteration ausgeführt, anstatt nur bei der ersten - wir wissen nicht, was esback()
tut (gibt es irgendwelche Nebenwirkungen? Ändert es die interne Darstellung vonb
?), Daher entspricht diese Schleife nicht der in die Frage.v = b.back()
er außerhalb der darüber liegenden Schleife verschoben würde . (Auch wenn Sie versuchen, auf jemanden zu antworten, verwenden Sie@
vor seinem Namen, damit wir eine Benachrichtigung erhalten)ist Initialisierung.
ist die Bedingung.
ist die Iteration
quelle
Die Bedingung ist das Ergebnis von
u--
, was der Wert ist,u
bevor er dekrementiert wurde.In C und C ++, eine
int
ist umwandelbar in Bool durch implizit einen tun!= 0
Vergleich (0 istfalse
, alles andere isttrue
).b.back()
ist das letzte Element in einem Container, dhb[b.size() - 1]
wannsize() != 0
.quelle
In C befindet sich alles, was nicht Null ist,
true
in "booleschen" Kontexten, wie z. B. der Schleifenendbedingung oder einer bedingten Anweisung. In C # müssen Sie diese Prüfung explizit machen :u-- != 0
.quelle
Wie von anderen angegeben, bedeutet die Tatsache, dass C ++ implizites Casting in Boolesche
u--
Werte hat, die Bedingung , die wahr ist, wenn der Wert nicht Null ist.Es lohnt sich hinzuzufügen, dass Sie eine falsche Annahme haben, wenn Sie fragen, wo die Bedingung ist. Sowohl in C ++ als auch in C # (und anderen ähnlich syntaxierten Sprachen) können Sie eine leere Bedingung haben. In diesem Fall wertet es immer wahr, so dass die Schleife für immer weitergeht, oder bis zu einigen anderen Zustand verlässt sie (über
return
,break
oderthrow
).In der Tat kann jeder Teil der for-Anweisung weggelassen werden. In diesem Fall wird er einfach nicht ausgeführt.
Im Allgemeinen
for(A; B; C){D}
oderfor(A; B; C)D;
wird:Ein oder mehrere von A, B, C oder D können weggelassen werden.
Infolgedessen einige Vorliebe
for(;;)
für Endlosschleifen. Ich mache das, weil ich zwarwhile(true)
populärer bin, aber das als "bis die Wahrheit nicht mehr wahr ist" lese, was im Vergleich zu meiner Lektürefor(;;)
als "für immer" etwas apokalyptisch klingt .Es ist Geschmackssache, aber da ich nicht die einzige Person auf der Welt bin, die es mag
for(;;)
, lohnt es sich zu wissen, was es bedeutet.quelle
Alle Antworten sind richtig: -
Die for-Schleife kann auf verschiedene Arten wie folgt verwendet werden:
quelle
Im obigen Code
u
undv
werden mitb.size()
und initialisiertb.back()
.Jedes Mal, wenn die Bedingung überprüft wird, führt sie auch eine Dekrementanweisung aus, dh
u--
.Die
for
Schleife wird verlassen , wennu
sein wird0
.quelle
Der in C # selbst aufgetretene Fehler löscht den Zweifel. Die for-Schleife sucht nach a
Bedingung zu beenden. Und wie wir wissen,
Im Gegensatz zu C ++ kann C # dies jedoch nicht alleine verarbeiten. Die Bedingung, nach der Sie suchen, ist also
Sie müssen die Bedingung jedoch explizit in C # als angeben
oder
Versuchen Sie dennoch, diese Art der Codierungspraxis zu vermeiden. Das
Die oben als Antwort angegebene ist eine der einfachsten Versionen von Ihnen
quelle
Wenn Sie an C / C ++ gewöhnt sind, ist dieser Code nicht so schwer zu lesen, obwohl er ziemlich knapp und nicht so großartig ist. Lassen Sie mich also die Teile erklären, die mehr Cism als alles andere sind. Zunächst sieht die allgemeine Syntax einer C for-Schleife folgendermaßen aus:
Der Initialisierungscode wird einmal ausgeführt. Dann wird die Bedingung vor jeder Schleife getestet und zuletzt wird das Inkrement nach jeder Schleife aufgerufen. In Ihrem Beispiel finden Sie also die Bedingung
u--
Warum
u--
arbeitet als Bedingung in C und nicht in C #? Weil C implizit viele Dinge zu bools konvertiert und es Probleme verursachen kann. Für eine Zahl ist alles, was nicht Null ist, wahr und Null ist falsch. Es wird also von b.size () - 1 bis 0 heruntergezählt. Der Nebeneffekt in der Bedingung ist etwas ärgerlich und es wäre vorzuziehen, ihn in den inkrementellen Teil der for-Schleife zu setzen, obwohl viel C. Code macht das. Wenn ich es schreiben würde, würde ich es eher so machen:Der Grund dafür ist zumindest für mich klarer. Jeder Teil der for-Schleife erledigt seinen Job und sonst nichts. Im ursprünglichen Code wurde die Variable durch die Bedingung geändert. Der Inkrement-Teil hat etwas getan, das sich im Codeblock usw. befinden sollte.
Der Kommaoperator wirft Sie möglicherweise auch für eine Schleife. In C
x=1,y=2
sieht so etwas wie eine Anweisung für den Compiler aus und passt in den Initialisierungscode. Es wertet nur jedes der Teile aus und gibt den Wert des letzten zurück. Also zum Beispiel:würde ausdrucken 2.
quelle