while-Schleife verlassen (C)

Gast #4826901
Lesenswert?

Aus dem C-Standard:
1
6.8.6.3 The break statement
2
Constraints
3
1 A break statement shall appear only in or as a switch body or loop body.
4
Semantics
5
2 A break statement terminates execution of the smallest enclosing switch or iteration statement.
6

7
6.8.6.4 The return statement
8
Constraints
9
1 A return statement with an expression shall not appear in a function whose return type is void. A return statement without an expression shall only appear in a function whose return type is void.
10
Semantics
11
2 A return statement terminates execution of the current function and returns control to its caller. A function may have any number of return statements.

Wie aber schon richtig gesagt wurde, eine while-Schleife hat eine 
Abbruchbedingung. Sonst überleg dir ein anderes Konstrukt.
Gast #4826912
Lesenswert?

Peter II schrieb:
> warum sollte er da machen? return ist durchaus sinnvoll zu
> Fehlerbehandlung!

Na klar. Aber wir sollen wir durch unsere Glaskugeln überhaupt wissen 
was er möchte. Grundsätzlich lautet die Antwort auf die Frage:

> kann man in C eine while-Schleife auch mit "return" verlassen?

ein einfaches "ja".
Gast #4826915
Lesenswert?

Fred R. schrieb:
> While
> Goto Outside
> Do
>
> Outside:

WÜRG. Bitte ganz schnell vergessen, oder Assembler programmieren.

@TMG: Dir fehlt ein gutes C Buch, das du auch lesen musst. Das sind die 
absoluten Basics.

Um Schleifen zu beenden oder in den nächsten Durchlauf zu springen gibt 
es zwei Schlüsselwörter:
"break" und "continue".

Die müssen sitzen.

Ja und in einer Funktion kann man auch mit return aus einer Schleife. 
Das beendet aber nicht nur die Schleife, sondern die ganze Funktion.
Gast #4827107
Lesenswert?

Chris K. schrieb:
> while Schleife
> eine Abbruchbedingung mitgeben.
Nein, kann man nicht! Schleifen in C/C++ haben (per se)
keine Abbruchbedingung! Es sind immer Laufbedingungen!

Bei Schleifen (in C/C++) heisst es immer : Laufe solange wie...
Und nicht: Breche ab wenn...

Das ist ein wesentlicher Unterschied. Auch wenn jeder hier vermutlich 
weiss was gemeint ist, so bleibt es trotzdem falsch.

Eine Abbruchbedinung hat man z.B. bei einer do-until-Schleife wie es sie 
in VBA gibt.

Eine Abbruchbedingung kann man nur kuenstlich erzeugen durch
ein if(...) break;
Gast #4827181
Lesenswert?

Kaj schrieb:
> Chris K. schrieb:
>> while Schleife
>> eine Abbruchbedingung mitgeben.
> Nein, kann man nicht! Schleifen in C/C++ haben (per se)
> keine Abbruchbedingung! Es sind immer Laufbedingungen!
>
> Bei Schleifen (in C/C++) heisst es immer : Laufe solange wie...
> Und nicht: Breche ab wenn...

Und diese Haarspalterei hilft niemandem, der einzige Unterschied ist 
nämlich die Negierung.
Gast #4827283
Lesenswert?

Ich bin jetzt kein C Entwickler, aber in anderen Sprachen gibt es das 
auch das man aus einem while frühzeitig raus will. Am einfachsten ist 
das wohl so zu lösen:
1
    int i = 0;
2
    int cancel = 0;
3

4
    while (i < 100 && cancel == 0)
5
    {
6
        printf("%i ", i);
7
        i++;
8
        
9
        if (i == 50)
10
            cancel = 1;
11
    }
Gast #4827290
Lesenswert?

Peter II schrieb:
> ganz bestimmt nicht. Einfach ist ein break.

Eben, ausserdem ist Martins "cancel" Beispiel auch noch beliebig falsch, 
da der Schleifenkörper nicht an dem Punkt abgebrochen wird, sondern bis 
zum Anfang des nächsten Durchlaufs weiterläuft.
Das kann je nachdem was hinter dem "cancel = 1" noch an Code steht 
beliebig falsch sein.
Gast #4827344
Lesenswert?

Fred R. schrieb:
> While
> Goto Outside
> Do
>
> Outside:

Persönlich finde ich das die schlimmste Methode.
Sehr unübersichtlich wenn der Code größer wird und vor allem glaube ich 
wird bei dieser Methode nicht aufgeräumt, richtig?

Also würden die innerhalb der Schleife angelegten temporären Variablen 
nicht nicht wieder gelöscht und für ehwig im Speicher verweilen. Oder 
täusche ich mich da jetzt?
Gast #4827407
Lesenswert?

Kaj schrieb:
> Chris K. schrieb:
>> while Schleife
>> eine Abbruchbedingung mitgeben.
> Nein, kann man nicht! Schleifen in C/C++ haben (per se)
> keine Abbruchbedingung! Es sind immer Laufbedingungen!

Korinthen kacken kann ich auch: Deine Aussage ist Unsinn, da es gar 
keine Sprache namens "C/C++" gibt. Es gibt aber die Sprache C und die 
Sprache C++, für die das gesagte gleichermaßen gilt. Ich sag ja auch 
nicht "Eine Kuh/Katze hat vier Beine".

> Eine Abbruchbedingung kann man nur kuenstlich erzeugen durch
> ein if(...) break;

Was verstehst du unter "künstlich erzeugt"? Es ist doch praktisch die 
wörtliche Entsprechung von:

> Breche ab wenn...
Gast #4827414
Lesenswert?

Der Andere schrieb:
> Eben, ausserdem ist Martins "cancel" Beispiel auch noch beliebig falsch,
> da der Schleifenkörper nicht an dem Punkt abgebrochen wird, sondern bis
> zum Anfang des nächsten Durchlaufs weiterläuft.
> Das kann je nachdem was hinter dem "cancel = 1" noch an Code steht
> beliebig falsch sein.

Ein bisschen Kreativität muss da jeder schon noch selber mitbringen. War 
ja original kein Code vorgeben.

Peter II schrieb:
> ganz bestimmt nicht. Einfach ist ein break.
ja in Sprachen in es dieses Feature gibt schon

Frank M. schrieb:
> Einfacher wäre
> jedoch dann ein "i = 100;" gewesen ;-)

Einfacher ja, aber zumindest etwas was ich bei einem Review so nicht 
durchlassen würde (weder maintainable noch intuitiv)
Gast #4827707
Lesenswert?

Rüdiger schrieb:
> Auch wenn sie in Einzelfällen ihre Berechtigung haben, sind
> Programmsprünge mit break, continue oder goto in der Regel schlechter
> Programmierstil.

das ist doch Unsinn. bei goto kann man sich ja noch streiten aber break 
und continue sind üblich und werden auch ständig gebraucht.
Gast #4827779
Lesenswert?

Ich würde es mal so formulieren: Wenn man ohnehin schon den 
Bad-Style-Fail gemacht hat einen Schleifenrumpf auf mehrere 
Bildschirmseiten Code auszudehnen, dann haut man mit continues und 
breaks dem Fass den Boden endgültig weg. Da blickt dann niemand mehr 
durch, wann und wo die Schleife durchlaufen oder abgebrochen wird.

Bei einem übersichtlich kompakten Rumpf hingegen gewinnt man nichts an 
Lesbarkeit, wenn man syntaktische Verrenkungen macht nur um 
Teufel-komm-raus contiues oder breaks zu vermeiden. Da ist ein break 
jederzeit besser als zusätzliche Abbruchvariablen oder -bedingungen.
Gast #4827893
Lesenswert?

Joachim B. schrieb:
> TMG schrieb:
>> kann man in C eine while-Schleife auch mit "return" verlassen?
>
> ja aber sollte man nicht, wie gesagt wurde break;

und wie schon oft gesagt, warum sollte man das nicht? Ich habe oben 
schon ein Beispiel gebracht das es zur Fehlerbehandlung sehr sinnvoll 
ist.
Gast #4827902
Lesenswert?

Hm, ich merke gerade, dass ich zu wenig gotos verwende. Ich hätte auch 
mit break und return geantwortet.
Aber das goto ist ja richtig klasse: Retro-Style, wie damals in den 
80ern.
Zu NDW und Space Invaders gehört auch ein richtigen goto.
Gast #4827939
Lesenswert?

Rüdiger schrieb:
> Auch wenn sie in Einzelfällen ihre Berechtigung haben, sind
> Programmsprünge mit break, continue oder goto in der Regel schlechter
> Programmierstil.

Dann wünsche ich viel Spass bei der Suche nach dem Bug, weil jemand bei 
einer switch/case Anweisung das break vergessen hat. Sowas hat mich 
schon Tage gekostet.

break ist genau dafür gedacht, um eine Schleife vorzeitig zu verlasse 
(wenn die Abbruchbedingung noch nicht erfüllt ist). Das hat weder mit 
schlechtem Stil noch mit Unwissenheit zu tun.

Grüsse,
René
Gast #4827943
Lesenswert?

Kurt schrieb:
> ... einen Schleifenrumpf auf mehrere
> Bildschirmseiten Code auszudehnen, dann haut man mit continues und
> breaks dem Fass den Boden endgültig weg. Da blickt dann niemand mehr
> durch, wann und wo die Schleife durchlaufen oder abgebrochen wird.


Das kann nur jemand schreiben, der niemals mit größeren Code-Basen zutun 
hatte. Allen Lehrbuch-, Misra- oder SIL-Regeln zum Trotz kann man 
komplexe Aufgaben (in C), die z.B. 1Mio Codezeilen erfordern, nicht 
sinnvoll so auf LIBs, Files und Funktionen verteilen, dass McCabe-Zahlen 
ein-oder zweistellig bleiben.

> Bei einem übersichtlich kompakten Rumpf hingegen gewinnt man nichts an
> Lesbarkeit, wenn man syntaktische Verrenkungen macht nur um
> Teufel-komm-raus contiues oder breaks zu vermeiden. Da ist ein break
> jederzeit besser als zusätzliche Abbruchvariablen oder -bedingungen.

Wenn das schon bei kleinem Code stimmt... umso wichtiger ist es bei 
großem Code, d.h. ein einheitlicher Einsatz dieser (und anderer) 
Sprachmittel. Man darf (und sollte) also break oder return in 
10.000-Zeilen-Funktionen ruhig verwenden, nur nicht in "unüblicher" 
Weise. Wenn 1000 aufeinanderfolgende case: mit break enden, sollte kein 
unerwartetes return darunter sein und vice versa.

Nochwas zu großem Code: Die Anzahl der Zeilen ist natürlich kein 
hinreichendes Kriterium. 1000 unabhängige Teilprozesse von je 1000 
Codezeilen sind natürlich so sauber zu programmieren wie ein Miniprojekt 
von 1000 Zeilen (also grob 10 C-Files a 10 Funktionen a 10 Zeilen wie im 
Lehrbuch)
#4828044
Lesenswert?

Kurt schrieb:
> Ich würde es mal so formulieren: Wenn man ohnehin schon den
> Bad-Style-Fail gemacht hat einen Schleifenrumpf auf mehrere
> Bildschirmseiten Code auszudehnen, dann haut man mit continues und
> breaks dem Fass den Boden endgültig weg. Da blickt dann niemand mehr
> durch, wann und wo die Schleife durchlaufen oder abgebrochen wird.

Genau da, wo break bzw continue steht. Wo sonst?

Und die Funktion wird da beendet, wo return steht. Ein Problem?
#4828176
Lesenswert?

Thomas S. schrieb:
> @ Wilhelm M.
> Also ich hatte keine Probleme mit diesem Tutorial-Ausschnitt.
>
> Weiter hab ich nichts überprüft. Nicht meine Aufgabe.

Folgendes fiel mir sofort auf:
1
int i, x = 55; // i ist uninitialsiert
2
double x;  // x ist schon als int deklariert , wird nicht initialisiert.
3

4
for(i = 100; i > -x; i--) // i besser innerhalb definieren, x ist nicht initialiert (s.o.)
5
{
6
// ...
7
}

Dann habe ich aufgehört zu lesen ...
#4828200
Lesenswert?

Wilhelm M. schrieb:
> Folgendes fiel mir sofort auf:
> int i, x = 55; // i ist uninitialsiert
> double x;  // x ist schon als int deklariert , wird nicht initialisiert.
>
> for(i = 100; i > -x; i--) // i besser innerhalb definieren, x ist nicht
> initialiert (s.o.)
> {
> // ...
> }

Die doppelte Verwendung von x ist Murks. Doch ist es Ansichtssache, wo 
man definiert und wo man initialisiert.

Ich bevorzuge alle Definitionen am Anfang einer Funktion und 
Initialisierung kurz vor Gebrauch.
#4828201
Lesenswert?

Thomas S. schrieb:
> Da hast Du recht.
> Bei sowas nutzt kein break und auch kein return.
>
> Aber ... wir sind alle nur menschen ...
>
> Gruß aus Spandau

Noch ne andere Stelle daraus:

"Wie man sieht, wurde die Variable ' x' in der aurufenden Funktion 
verändert, die Adresse der Variablen x wird mit dem Kaufmannns-und in 
die Funktion
FunktionMitPointer(&x); hineingegeben und dort mit dem * Operator 
dereferenziert und verändert. Weil man hier nicht die Variable sondern 
die Referenz, die Adresse der Variablen, übergibt nennt sich das ganze 
Call By Reference."

Call-by-reference ist Quatsch!

Wenn solche Sachen durch solche schlechten Tutorials verbreitet werden, 
ist das wirklich schlecht.
#4828313
Lesenswert?

Fred R. schrieb:
> While
> Goto Outside
> Do
>
> Outside:

Ein goto kann durchaus sehr übersichtlichen Code erlauben, wenn es 
gefühlte 100 Kriterien gibt und man alles an einer Stelle behandeln 
möchte. z.B. eine Fehlerausgabe oder so.
Aber ich würde es auch sparsam einsetzen, nur da, wo es wirklich sehr 
der Übersichtlichkeit dient oder den Code sehr vereinfacht.
Ansonsten würde ich in diesem Fall auch break verwenden um die Schleife 
zu verlassen oder return, wenn man auch gleich die Funktion verlassen 
will.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren