क्या "जबकि (सच)" इतना बुरा है? [बन्द है]


218

मैं अब कई वर्षों से जावा में प्रोग्रामिंग कर रहा हूं, लेकिन मैं अभी हाल ही में औपचारिक डिग्री प्राप्त करने के लिए स्कूल लौटा हूं। मुझे यह जानकर काफी हैरानी हुई कि, अपने आखिरी असाइनमेंट पर, मैंने नीचे दिए गए लूप का उपयोग करने के लिए अंक खो दिए।

do{
     //get some input.
     //if the input meets my conditions, break;
     //Otherwise ask again.
} while(true)

अब अपने परीक्षण के लिए मैं सिर्फ कुछ कंसोल इनपुट के लिए स्कैन कर रहा हूं, लेकिन मुझे बताया गया कि इस तरह के लूप को हतोत्साहित किया जाता है क्योंकि इसका उपयोग करने के breakलिए समान हैgoto , हम बस ऐसा नहीं करते हैं।

मैं gotoऔर इसके जावा चचेरे भाई के नुकसान को पूरी तरह से समझता हूंbreak:label , और मेरे पास इनका उपयोग न करने की अच्छी समझ है। मुझे यह भी एहसास है कि एक अधिक पूर्ण कार्यक्रम, पलायन के कुछ अन्य साधन प्रदान करेगा, उदाहरण के लिए कार्यक्रम को समाप्त करने के लिए कहें, लेकिन यह एक कारण नहीं था कि मेरे प्रोफेसर ने उद्धृत किया, इसलिए ...

इसमें गलत क्या है do-while(true)?


23
अपने शिक्षक से पूछें, उस तरह का सामान बहुत व्यक्तिपरक है।
क्रिस एबरले

18
मुझे यह लेख यह समझने में मददगार लगा है कि गोटो के लिए क्या हानिकारक है । के साथ तुलना breakशायद अच्छी तरह से अर्थ है, लेकिन वास्तव में गलत समझा। शायद आप इस पर अपने प्रोफेसर को शिक्षित कर सकते हैं;) मेरे अनुभव में प्रोफेसरों को प्रोग्रामिंग के शिल्प के बारे में ज्यादा जानकारी नहीं है।
मैग्नस हॉफ

100
इसके बारे में वास्तव में, केवल निर्विवाद बुरी बात मेरे दिमाग में है, तथ्य यह do {} while (true)है कि इसके बराबर है while(true) {}और बाद में कहीं अधिक पारंपरिक रूप और बहुत स्पष्ट है।
वू

11
यदि किसी की सरल अभिव्यंजक शक्ति की सराहना नहीं करते हैं break, तो उन्हें इसके बिना किसी भाषा में प्रोग्रामिंग की कोशिश करनी चाहिए। इससे पहले कि आप इसके लिए चाहते हैं यह बहुत सारे छोरों को नहीं लेता है!
स्टीवन

16
मैं होमवर्क टैग से असहमत हूं।
आआआआ बीबीबब

जवाबों:


220

मैं यह नहीं कहूंगा कि यह बुरा है - लेकिन समान रूप से मैं कम से कम एक विकल्प की तलाश करूंगा।

जिन स्थितियों में यह पहली बात है, जो मैं लिखता हूं, मैं लगभग हमेशा कम से कम इसे कुछ स्पष्ट करने की कोशिश करता हूं । कभी-कभी इसकी मदद नहीं की जा सकती (या विकल्प के पास एक boolचर है जो कुछ भी सार्थक नहीं है सिवाय पाश के अंत को इंगित करता है, एक breakबयान की तुलना में कम स्पष्ट रूप से ) लेकिन यह कम से कम कोशिश करने के लायक है।

एक उदाहरण के रूप में जहां यह breakध्वज की तुलना में उपयोग करने के लिए स्पष्ट है , विचार करें:

while (true)
{
    doStuffNeededAtStartOfLoop();
    int input = getSomeInput();
    if (testCondition(input))
    {
        break;
    }
    actOnInput(input);
}

अब इसे एक ध्वज का उपयोग करने के लिए मजबूर करते हैं:

boolean running = true;
while (running)
{
    doStuffNeededAtStartOfLoop();
    int input = getSomeInput();
    if (testCondition(input))
    {
        running = false;
    }
    else
    {
        actOnInput(input);
    }
}

मैं उत्तरार्द्ध को पढ़ने के लिए अधिक जटिल के रूप में देखता हूं: यह एक अतिरिक्त elseब्लॉक मिला है , actOnInputअधिक इंडेंट किया गया है, और यदि आप यह पता लगाने की कोशिश कर रहे हैं कि testConditionरिटर्न होने पर क्या होता है true, तो आपको बाकी ब्लॉक को ध्यान से देखने की जरूरत है कुछ नहीं है के बादelse ब्लॉक जो घटित होता है कि क्या runningकरने के लिए स्थापित किया गया हैfalse या नहीं।

breakबयान और अधिक स्पष्ट रूप मंशा का, और ब्लॉक के बाकी यह पहले की स्थिति के बारे में चिंता किए बिना क्या करने की जरूरत के साथ पर मिलता है।

ध्यान दें कि यह ठीक उसी प्रकार का तर्क है जो लोगों के पास एक विधि में कई रिटर्न स्टेटमेंट्स के बारे में है। उदाहरण के लिए, यदि मैं पहले कुछ पंक्तियों के भीतर एक विधि के परिणाम को काम कर सकता हूं (उदाहरण के लिए क्योंकि कुछ इनपुट शून्य है, या खाली है, या शून्य है) तो मुझे यह स्पष्ट है कि परिणाम को संग्रहीत करने के लिए एक चर होने की तुलना में सीधे उत्तर देने के लिए वापस लौटना होगा , फिर अन्य कोड का एक पूरा ब्लॉक, और अंत में एक returnबयान।


3
मैं मानता हूं कि यह मेरे लिए पहुंचने वाला पहला उपकरण नहीं है, लेकिन यह सिर्फ इतनी सफाई से समस्या की देखभाल करने के लिए लग रहा था, और मुझे साफ कोड पसंद है।
19

3
@ एक्स-जीरो: हाँ, कभी-कभी। यदि आप "ब्रेक" को "वापसी" में बदल सकते हैं जो अक्सर अच्छाई है ... हालांकि आप अभी भी एक साथ खत्म कर सकते हैंwhile (true)
जॉन स्कीट

21
@ प्रवृत्ति: मैं अपने कोड के अधिकांश के रूप में संभव के रूप में unindented किया जाना पसंद करते हैं। और एक यौगिक कार्य के साथ एक शर्त मुझे और अधिक जटिल लगती है।
जॉन स्कीट

3
@ विंस: हाँ, और यह बहुत अच्छा है अगर आप लूप की शुरुआत में आसानी से स्थिति व्यक्त कर सकते हैं । लेकिन कभी-कभी आप ऐसा नहीं कर सकते - और हम जिस स्थिति के बारे में बात कर रहे हैं। कृपया मेरे उत्तर के पहले दो वाक्यों पर ध्यान दें।
जॉन स्कीट

6
@ इस्माइल: मुझे उम्मीद नहीं है। पोस्ट को केवल उनकी सामग्री पर ही आंका जाना चाहिए, न कि लेखक पर। हेक, मैं एक एरिक लिपर्ट पोस्ट को भी डाउनवोट करूंगा अगर मुझे लगा कि यह गलत / अनहेल्दी है। हालांकि यह अभी तक नहीं हुआ है :)
जॉन स्कीट

100

AFAIK कुछ भी नहीं, वास्तव में। शिक्षकों को सिर्फ एलर्जी है goto, क्योंकि उन्होंने सुना है कि यह वास्तव में बुरा है। नहीं तो आप बस लिखेंगे:

bool guard = true;
do
{
   getInput();
   if (something)
     guard = false;
} while (guard)

जो लगभग एक ही बात है।

शायद यह क्लीनर है (क्योंकि सभी लूपिंग जानकारी ब्लॉक के शीर्ष पर निहित है):

for (bool endLoop = false; !endLoop;)
{

}

4
मुझे आपके सुझाव पसंद हैं क्योंकि समाप्ति की स्थिति बहुत अधिक दिखाई दे रही है। इसका मतलब है कि कोड पढ़ते समय आप जल्द ही समझ पाएंगे कि यह क्या करने की कोशिश कर रहा है। मैं कभी अनंत लूप का उपयोग नहीं करता, लेकिन अपने दो संस्करणों का अक्सर उपयोग करता हूं।
स्लेज

4
आम सहमति यह है कि एक झंडा बड़े पैमाने पर तोड़ने से बेहतर है क्योंकि यह इरादे को व्यक्त करता है? मैं देख सकता हूं कि यह फायदेमंद होगा। सभी ठोस उत्तर, लेकिन मैं इसे स्वीकार करूँगा।
20

20
ये दोनों अभी भी बाकी लूप से प्रदूषित हो रहे हैं (कम से कम कुछ स्थितियों में) कम से कम लूप के शरीर के अंत तक चलते रहना चाहिए भले ही आपको पता हो कि आप तोड़ रहे हैं । मैं अपने जवाब में एक उदाहरण रखूँगा ...
जॉन स्कीट

8
मुझे जॉन स्कीट का जवाब बेहतर लगा। इसके अलावा, जबकि (सच्चा) {} MUCH से बेहतर है {} जबकि (सच्चा)
आआआआ बीबीबीब

1
मुझे इस बात से नफरत है कि दीजकस्ट्रा ने कभी भी उस गो लेख को लिखा था। हालांकि GoTo निश्चित रूप से अक्सर अतीत में दुरुपयोग किया गया था, इसका मतलब यह नहीं है कि आपको कभी भी इसका उपयोग नहीं करना चाहिए। इसके अलावा, एक्जिट फॉर, ब्रेक, एक्जिट जबकि, कोशिश / कैच सभी गोटो के विशेष रूप हैं। गोटोस अक्सर कोड को अधिक पठनीय बना सकते हैं। और हाँ मुझे पता है कि गोटो के बिना कुछ भी किया जा सकता है। इसका मतलब यह नहीं होना चाहिए।
किबी जूल 28'11

39

डगलस क्रॉफोर्ड की एक टिप्पणी थी कि वे कैसे चाहते थे कि जावास्क्रिप्ट में एक loopसंरचना शामिल हो:

loop
{
  ...code...
}

और मुझे नहीं लगता कि जावा किसी loopसंरचना के होने के लिए भी बदतर होगा ।

वहाँ के साथ स्वाभाविक कुछ भी गलत नहीं while(true)छोरों, लेकिन वहाँ है शिक्षकों को हतोत्साहित करने के लिए के लिए एक प्रवृत्ति। शिक्षण के दृष्टिकोण से, छात्रों को अंतहीन लूप बनाना बहुत आसान है और समझ में नहीं आता है कि लूप कभी बच क्यों नहीं रहा है।

लेकिन वे शायद ही कभी उल्लेख करते हैं कि सभी लूपिंग तंत्र को while(true)छोरों के साथ दोहराया जा सकता है ।

while( a() )
{
  fn();
}

के समान है

loop
{
  if ( !a() ) break;
  fn();
}

तथा

do
{
  fn();
} while( a() );

के समान है:

loop
{
  fn();
  if ( !a() ) break;
}

तथा

for ( a(); b(); c() )
{
  fn();
}

के समान है:

a();
loop
{
  if ( !b() ) break;
  fn();
  c();
}

जब तक आप अपने छोरों को इस तरह से सेट कर सकते हैं , जो आपके द्वारा उपयोग किए जाने वाले निर्माण का काम करता है, महत्वहीन है। यदि यह लूप में फिट होने के लिए होता है for, तो लूप का उपयोग करें for

एक अंतिम भाग: अपने छोरों को सरल रखें। यदि हर कार्यक्षमता पर बहुत अधिक कार्यक्षमता होनी चाहिए, तो इसे किसी फ़ंक्शन में रखें। काम करने के बाद आप इसे हमेशा अनुकूलित कर सकते हैं।


2
+1: forजब continueबयान शामिल होते हैं तो लूप के साथ अतिरिक्त जटिलताएं होती हैं , लेकिन वे एक प्रमुख विस्तार नहीं हैं।
डोनाल्ड फेलो

मैं आमतौर पर लूप के लिए उपयोग करता हूं जब कोई अनुक्रम होता है जिसे मैं पार करना चाहता हूं, और थोड़ी देर के लूप जब कोई शर्त होती है जिसे मैं मिलना चाहता हूं। इससे कोड अधिक सुपाठ्य रहता है।
डैस्कैंडी

4
क्या for (;;) {कोई और नहीं लिखता ? (उच्चारण "हमेशा के लिए")। यह बहुत लोकप्रिय हुआ करता था।
दाऊद इब्न करीम

16

1967 में वापस, एडगर डिज्स्ट्रा ने एक व्यापार पत्रिका में एक लेख लिखा था कि कोड गुणवत्ता में सुधार के लिए उच्च स्तर की भाषाओं से गोटो को क्यों हटाया जाना चाहिए। एक संपूर्ण प्रोग्रामिंग प्रतिमान जिसे "संरचित प्रोग्रामिंग" कहा जाता है, इस से बाहर आया, हालांकि निश्चित रूप से हर कोई इससे सहमत नहीं है कि गोटो स्वचालित रूप से खराब कोड का मतलब है।

संरचित प्रोग्रामिंग का क्रूस अनिवार्य रूप से यह है कि कोड की संरचना को गोटो या ब्रेक होने के बजाय इसके प्रवाह का निर्धारण करना चाहिए या जहां भी संभव हो प्रवाह का निर्धारण करना जारी रखना चाहिए। एक लूप या फ़ंक्शन में कई प्रविष्टि और निकास बिंदु होने पर, उस प्रतिमान में भी हतोत्साहित किया जाता है।

जाहिर है कि यह केवल प्रोग्रामिंग प्रतिमान नहीं है, लेकिन अक्सर इसे ऑब्जेक्ट उन्मुख प्रोग्रामिंग (अला जावा) जैसे अन्य प्रतिमानों पर आसानी से लागू किया जा सकता है।

आपके शिक्षकों को शायद पढ़ाया गया है, और आपकी कक्षा को यह सिखाने की कोशिश की जा रही है कि हम सबसे बेहतर "स्पेगेटी कोड" से बचेंगे, यह सुनिश्चित करके कि हमारा कोड संरचित है, और संरचित प्रोग्रामिंग के निहित नियमों का पालन करना है।

हालांकि, एक कार्यान्वयन के साथ स्वाभाविक रूप से "गलत" कुछ भी नहीं है जो ब्रेक का उपयोग करता है, कुछ इसे कोड को पढ़ने में काफी आसान मानते हैं जहां लूप के लिए स्थिति स्पष्ट रूप से (जबकि) स्थिति के भीतर निर्दिष्ट होती है, और अत्यधिक मुश्किल होने की कुछ संभावनाओं को समाप्त करती है। थोड़ी देर (सच्ची) स्थिति का उपयोग करने के लिए निश्चित रूप से नुकसान होते हैं जो नौसिखिए प्रोग्रामर द्वारा कोड में अक्सर पॉप अप करने के लिए लगते हैं, जैसे कि गलती से एक अनंत लूप बनाने का जोखिम, या कोड बनाना जो पढ़ना मुश्किल है या अनावश्यक रूप से भ्रमित करना है।

विडंबना यह है कि अपवाद हैंडलिंग एक ऐसा क्षेत्र है, जहां संरचित प्रोग्रामिंग से विचलन निश्चित रूप से सामने आएगा और उम्मीद की जाएगी कि आप जावा में प्रोग्रामिंग में आगे बढ़ेंगे।

यह भी संभव है कि आपका प्रशिक्षक आपसे यह अपेक्षा कर सकता है कि आप किसी विशेष लूप संरचना या सिंटैक्स का उपयोग करने की अपनी क्षमता का प्रदर्शन उस अध्याय या पाठ के पाठ में कर रहे हैं, और जबकि आपके द्वारा लिखा गया कोड कार्यात्मक रूप से समतुल्य है, तो आप प्रदर्शन नहीं कर रहे होंगे। विशेष कौशल आप उस पाठ में सीखने वाले थे।



14

इनपुट इनपुट पढ़ने के लिए us बेकार जावा सम्मेलन है:

import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String strLine;

while ((strLine = br.readLine()) != null) {
  // do something with the line
}

और इनपुट पढ़ने के लिए सामान्य C ++ सम्मेलन है:

#include <iostream>
#include <string>
std::string data;
while(std::readline(std::cin, data)) {
  // do something with the line
}

और सी में, यह है

#include <stdio.h>
char* buffer = NULL;
size_t buffer_size;
size_t size_read;
while( (size_read = getline(&buffer, &buffer_size, stdin)) != -1 ){
  // do something with the line
}
free(buffer);

या यदि आप आश्वस्त हैं कि आपको पता है कि आपकी फ़ाइल में सबसे लंबी पंक्ति कितनी लंबी है, तो आप कर सकते हैं

#include <stdio.h>
char buffer[BUF_SIZE];
while (fgets(buffer, BUF_SIZE, stdin)) {
  //do something with the line
}

यदि आप यह देखने के लिए परीक्षण कर रहे हैं कि क्या आपके उपयोगकर्ता ने कोई quitकमांड दर्ज की है , तो इन 3 लूप संरचनाओं में से किसी एक को विस्तारित करना आसान है। मैं इसे आपके लिए जावा में करूँगा:

import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;

while ((line = br.readLine()) != null  && !line.equals("quit") ) {
  // do something with the line
}

इसलिए, जबकि निश्चित रूप से ऐसे मामले हैं जहां breakया gotoउचित है, यदि आप जो भी कर रहे हैं वह फ़ाइल या लाइन से कंसोल लाइन द्वारा पढ़ रहा है, तो आपको while (true)इसे पूरा करने के लिए लूप की आवश्यकता नहीं होनी चाहिए - आपकी प्रोग्रामिंग भाषा ने आपको पहले ही आपूर्ति की है लूप स्थिति के रूप में इनपुट कमांड का उपयोग करने के लिए एक उपयुक्त मुहावरे के साथ।


वास्तव में, यदि आप while (true)इन पारंपरिक इनपुट छोरों में से एक के बजाय एक लूप का उपयोग कर रहे हैं, तो आप फ़ाइल के अंत की जांच करना भूल सकते हैं।
केन ब्लूम

3
आप whileसशर्त में लूप के पहले भाग को भरकर इसे प्रभावी ढंग से पूरा कर रहे हैं। अंतिम जावा स्थिति में यह पहले से ही काफी विषम हो रहा है, और अगर आपको यह जारी रखने या न करने के लिए व्यापक हेरफेर करना पड़ा, तो यह काफी लंबा हो सकता है। आप इसे एक अलग फ़ंक्शन में विभाजित कर सकते हैं, और यह सबसे अच्छा हो सकता है। लेकिन अगर आप इसे एक फ़ंक्शन में चाहते हैं, और यह जारी रखने से पहले कि क्या जारी रखना है, यह तय करने के लिए कोई भी काम नहीं है while(true)
पूल जू

@ पल्ली: फिर लूप कंडीशन (जो ईओएफ के लिए जांचता है) के रूप में रीड कमांड का उपयोग करना सबसे अच्छा है, और ब्रेक स्टेटमेंट के रूप में लूप के अंदर अपनी अन्य स्थितियों की जांच करें।
केन ब्लूम

1
जो इसके लायक है, gets()वह आम सम्मेलन नहीं है। यह अत्यधिक ओवरफ्लो बफर करने के लिए अनुकूल है। fgets(buffer, BUFFER_SIZE, file)मानक अभ्यास की तरह बहुत अधिक है।
डेव

@ क्या: मैंने अब उपयोग करने के लिए उत्तर संपादित किया है fgets
केन ब्लूम

12

यह इतनी भयानक बात नहीं है, लेकिन आपको कोडिंग करते समय अन्य डेवलपर्स को ध्यान में रखना होगा। स्कूल में भी।

आपके साथी डेवलपर्स को लूप डिक्लेरेशन में आपके लूप के लिए बाहर निकलने का क्लॉज देखने में सक्षम होना चाहिए। आपने ऐसा नहीं किया। आप लूप के बीच में बाहर निकलने के क्लॉज को छिपाते हैं, किसी और के लिए अधिक काम करते हैं जो साथ आता है और आपके कोड को समझने की कोशिश करता है। यही कारण है कि "ब्रेक" जैसी चीजों से बचा जाता है।

कहा जा रहा है, आप अभी भी इस तरह की चीजों को वास्तविक दुनिया में कोड के बहुत से देखेंगे।


4
यदि लूप बंद हो जाता है तो while (true)यह बहुत स्पष्ट है कि इसमें breakया इसके returnअंदर होने वाला है, या यह हमेशा के लिए चलेगा। सीधा होना महत्वपूर्ण है, लेकिन while(true)विशेष रूप से बुरा नहीं है, अपने आप से। वेरीएबल्स जिनमें लूप पुनरावृत्तियों में जटिल आक्रमण होते हैं, यह उस चीज़ का एक उदाहरण होगा जो बहुत अधिक गुस्से का कारण बनता है।
पूल जू

4
एक खोज में तीन स्तरों को गहरा करने की कोशिश करें और फिर किसी तरह बाहर तोड़कर। यदि आप उस बिंदु से वापस नहीं आते हैं तो कोड बहुत खराब होने वाला है।
डैस्कैंडी

11

यह आपकी बंदूक, आपकी गोली और आपका पैर है ...

यह बुरा है क्योंकि आप परेशानी पूछ रहे हैं। यह इस पृष्ठ पर आप या किसी भी अन्य पोस्टर नहीं होंगे जिनके पास छोरों के समय कम / सरल के उदाहरण हैं।

मुसीबत भविष्य में कुछ बहुत ही यादृच्छिक समय पर शुरू होगी। यह किसी अन्य प्रोग्रामर के कारण हो सकता है। यह सॉफ्टवेयर इंस्टॉल करने वाला व्यक्ति हो सकता है। यह अंतिम उपयोगकर्ता हो सकता है।

क्यों? मुझे यह पता लगाना था कि क्यों एक 700K LOC ऐप धीरे-धीरे सीपीयू समय के 100% को जलाना शुरू कर देगा, जब तक कि प्रत्येक सीपीयू संतृप्त न हो जाए। यह एक आश्चर्यजनक समय था जब (सच) लूप था। यह बड़ा और बुरा था, लेकिन यह नीचे उबला हुआ था:

x = read_value_from_database()
while (true) 
 if (x == 1)
  ...
  break;
 else if (x ==2)
  ...
  break;
and lots more else if conditions
}

कोई दूसरी शाखा नहीं थी। यदि मान किसी शर्त से मेल नहीं खाता है तो लूप समय के अंत तक चालू रहता है।

बेशक, प्रोग्रामर ने प्रोग्रामर द्वारा अपेक्षित मान नहीं चुनने के लिए अंतिम उपयोगकर्ताओं को दोषी ठहराया। (तब मैंने कोड में (सत्य) सभी उदाहरणों को समाप्त कर दिया था।)

IMHO यह अच्छा (रक्षा) जैसे निर्माण का उपयोग करने के लिए रक्षात्मक प्रोग्रामिंग नहीं है। यह आपको परेशान करने के लिए वापस आ जाएगा।

(लेकिन मुझे लगता है कि अगर हम हर पंक्ति, i ++ के लिए भी टिप्पणी नहीं करते हैं, तो हम नीचे दिए गए प्रोफेसरों को याद करते हैं;)


3
रक्षात्मक प्रोग्रामिंग के बारे में टिप्पणी के लिए +1।
जर्नच

3
आपके उदाहरण में, कोड बेवकूफ होने के कारण (सही) नहीं है, बल्कि कोड के चारों ओर लूप लगाने के विचार के कारण है।
फ्लोरियन एफ

वास्तव में, उस पाश का क्या मतलब था? :)
जजलिन

6

यह इस अर्थ में बुरा है कि संरचित प्रोग्रामिंग निर्माणों को (कुछ हद तक असंरचित) पसंद किया जाता है और बयान जारी रखते हैं। वे इस सिद्धांत के अनुसार "गोटो" को पसंद करते हैं।

मैं हमेशा आपके कोड को यथासंभव संरचित बनाने की सलाह दूंगा ... हालांकि, जैसा कि जॉन स्कीट बताते हैं, इसे इससे अधिक संरचित न करें!


5

ज्यादातर मामलों में मेरे अनुभव के अनुसार लूप्स को जारी रखने के लिए "मुख्य" स्थिति है। यह वह शर्त है जिसे स्वयं (ऑपरेटर) के समय में लिखा जाना चाहिए। अन्य सभी स्थितियां जो लूप को तोड़ सकती हैं वे गौण हैं, इतना महत्वपूर्ण नहीं आदि। उन्हें अतिरिक्त if() {break}विवरण के रूप में लिखा जा सकता है ।

while(true) अक्सर भ्रमित होता है और कम पठनीय होता है।

मुझे लगता है कि ये नियम 100% मामलों को कवर नहीं करते हैं लेकिन शायद उनमें से केवल 98% हैं।


ख़ूब कहा है। यह लूप के लिए एक कर का उपयोग करने जैसा है: जबकि (सच) {i ++; ...}। आप 'हस्ताक्षर' के बजाय लूप की स्थिति को लूप के अंदर दफन कर रहे हैं।
लीजेंडलॉग्रान

3

हालांकि जरूरी नहीं कि इसका उपयोग करने के लिए एक उत्तर के रूप में while (true), मुझे हमेशा यह कॉमिक मिला है और लेखक के बयान के साथ-साथ ऐसा करने के बजाय ऐसा करने के लिए एक संक्षिप्त व्याख्या क्यों दी गई है।

अपने प्रश्न के संबंध में: कोई अंतर्निहित समस्या नहीं है

while(true) {
   do_stuff();
   if(exit_time) {
      break;
   }
}

... यदि आप जानते हैं कि आप क्या कर रहे हैं और सुनिश्चित करें कि exit_timeकुछ बिंदु पर मूल्यांकन करना होगा true

शिक्षक आपको while(true)तब तक उपयोग करने से हतोत्साहित करते हैं जब तक और जब तक आप इस बिंदु पर नहीं होते हैं कि आप जानते हैं कि आप क्या कर रहे हैं, यह एक महत्वपूर्ण गलती करने का आसान तरीका है।


मुझे लगता है कि सेटिंग exit_time = false; while(!exit_time) { execute_stuff(); }और do { execute_stuff(); } while(! exit_time );दोनों if( condition ) { break; }एक साथ एक लूप के अंत में होने की तुलना में बहुत स्पष्ट हैं while(true)। लूप के लिए शॉर्ट-सर्किट होते हैं - लूप के बीच में शॉर्ट-सर्किट के रूप में उपयोग किए जाने पर पूरी तरह से ठीक होता है, लेकिन आपको लूप के अंत में एक स्टेटमेंट बनाम ब्रेक होने पर बस एक शर्त का मूल्यांकन करना चाहिए।
डॉ। जंबोब

उस कॉमिक के संबंध में: जबकि करते समय वह सब नहीं कर सकता है, जबकि वह कर सकता है, जबकि कभी-कभी बेहतर करना वही करता है, जबकि वह भी कर सकता है।
थरोट

3

आप केवल लूप को समाप्त करने का संकेत देने के लिए बूलियन ध्वज का उपयोग कर सकते हैं। Breakऔर go toसॉफ़्टवेयर को बनाए रखने में मुश्किल होने के कारण थे - सॉफ़्टवेयर-संकट (टीएम) - और इसे टाला जाना चाहिए, और आसानी से भी हो सकता है।

यह एक सवाल है कि क्या आप व्यावहारिक हैं या नहीं। व्यावहारिक कोडर्स सिर्फ उस साधारण स्थिति में ब्रेक का उपयोग कर सकते हैं।

लेकिन इनका उपयोग न करने की आदत प्राप्त करना अच्छा है, अन्यथा आप इनका उपयोग अनुपयुक्त स्थितियों में निवास से बाहर कर सकते हैं, जैसे कि जटिल नेस्टेड छोरों में जहां उपयोग करने से आपके कोड की पठनीयता और स्थिरता कठिन हो जाती है break


8
क्योंकि बूलियन ध्वज रखना शायद कोई स्पष्ट नहीं है, और मेरे अनुभव में कम स्पष्ट हो सकता है?
जॉन स्कीट

3
@Jon Skeet वैसे तो यह एक अच्छा निवास स्थान के साथ जाने या ब्रेक का उपयोग करके अपने आप को एक बुरा प्रशिक्षण देने का प्रश्न है। "रनिंग" नामक एक बूल आपके लिए स्पष्ट नहीं है? इसका स्पष्ट, डिबग करना आसान है, और जैसा कि मैंने बताया कि एक अच्छे निवास स्थान से पहले एक अच्छी बात है। समस्या कहाँ हे?
डैनियल लेसकोवस्की

4
एक बूल जिसे रनिंग कहा जाता है, उसके लिए मुझे if (running)लूप के भीतर होना चाहिए , बाकी सभी कोड को इंडेंट करना जब मैं चाहता हूं कि लूप से बाहर निकलना है तो निश्चित रूप से एक साधारण ब्रेक स्टेटमेंट की तुलना में मेरे लिए कम स्पष्ट है जो बताता है कि मुझे क्या चाहिए। आप ब्रेक को बुरी आदत के रूप में स्वयंसिद्ध रूप से उपयोग करने पर विचार कर रहे हैं - मुझे ऐसा नहीं लगता।
जॉन स्कीट

2
आप लूप के भीतर एक (चल) क्यों होगा? जैसे कि आप लूप के अंत में ब्रेक लगाते हैं, अगर आप चेक करना चाहते हैं कि क्या आप ब्रेक का उपयोग करने के बजाय फ्लैग को बाहर निकालना चाहते हैं और फ्लैग का उपयोग कर रहे हैं (जबकि (चल रहा है) जबकि (सही)। मैं आपकी बात को गंभीरता से नहीं लेता। मैं सहमत हूँ कि एक व्यावहारिक कोडर कुछ स्थितियों में ब्रेक का उपयोग कर सकता है, लेकिन मैं वास्तव में आपके सुझाव के तहत आपके द्वारा की गई टिप्पणियों को प्राप्त नहीं करता हूं
डैनियल लेसकोव्स्की

3
आप मान रहे हैं कि आपको यह निर्धारित करने के बाद कि क्या छोड़ना है या नहीं, लूप के भीतर कुछ करने की ज़रूरत नहीं है। उदाहरण के लिए, ओपी की स्थिति में उसे छोड़ने के लिए अधिक इनपुट मांगने की आवश्यकता होती है।
जॉन स्कीट

3

शायद मैं बदकिस्मत हूं। या शायद मुझे सिर्फ एक अनुभव की कमी है। लेकिन हर बार जब मैं के साथ काम कर याद करते हैं while(true)होने breakके अंदर, यह संभव था कोड लागू करने में सुधार करने के निकालें विधि करने के लिए , जबकि ब्लॉक जो रखा, while(true)लेकिन (संयोग से?) तब्दील सभी breakमें रों returnरों।

मेरे अनुभव में while(true)बिना ब्रेक (यानी रिटर्न या थ्रो के साथ) काफी आरामदायक और समझने में आसान हैं।


  void handleInput() {
      while (true) {
          final Input input = getSomeInput();
          if (input == null) {
              throw new BadInputException("can't handle null input");
          }
          if (input.isPoisonPill()) {
              return;
          }
          doSomething(input);
      }
  }

3

मुझे लगता है कि हाँ यह बहुत बुरा है ... या कम से कम, कई डेवलपर्स के लिए। यह उन डेवलपर्स के लक्षण है जो अपने पाश स्थितियों के बारे में नहीं सोचते हैं। नतीजतन त्रुटि प्रवण है।


2

के साथ कोई बड़ी समस्या नहीं है while(true)के साथ breakबयान, लेकिन कुछ अपने से थोड़ा कोड पठनीयता को कम करती है सोच सकते हैं। चर को सार्थक नाम देने की कोशिश करें, उचित स्थान पर अभिव्यक्तियों का मूल्यांकन करें।

आपके उदाहरण के लिए, ऐसा कुछ करने के लिए बहुत स्पष्ट लगता है:

do {
   input = get_input();
   valid = check_input_validity(input);    
} while(! valid)

यह विशेष रूप से सच है यदि लूप लंबे समय तक हो जाता है - आप ठीक से जानते हैं कि चेक देखने के लिए कि क्या कोई अतिरिक्त पुनरावृत्ति हो रही है। सभी चर / कार्यों में अमूर्तता के स्तर पर उपयुक्त नाम हैं। while(true)बयान करता है आपको बता दूँ कि प्रसंस्करण जगह आप सोचा में नहीं है।

शायद आप लूप के माध्यम से दूसरी बार अलग-अलग आउटपुट चाहते हैं। कुछ इस तरह

input = get_input();
while(input_is_not_valid(input)) {
    disp_msg_invalid_input();
    input = get_input();
}

तब मेरे लिए अधिक पठनीय लगता है

do {
    input = get_input();
    if (input_is_valid(input)) {
        break;
    }
    disp_msg_invalid_input();
} while(true);

फिर, एक तुच्छ उदाहरण के साथ दोनों काफी पठनीय हैं; लेकिन अगर लूप बहुत बड़ा या गहरा घोंसला बन गया (जिसका अर्थ है कि आपको शायद पहले से ही रिफ्लेक्ट किया जाना चाहिए), पहला स्टाइल थोड़ा स्पष्ट हो सकता है।


1

मैं कुछ समान का उपयोग करता हूं, लेकिन विपरीत तर्क के साथ, अपने बहुत सारे कार्यों में।

DWORD dwError = ERROR_SUCCESS;

do
{
    if ( (dwError = SomeFunction()) != ERROR_SUCCESS )
    {
         /* handle error */
         continue;
    }

    if ( (dwError = SomeOtherFunction()) != ERROR_SUCCESS )
    {
         /* handle error */
         continue;
    }
}
while ( 0 );

if ( dwError != ERROR_SUCCESS )
{
    /* resource cleanup */
}

1

यह एक सौंदर्यशास्त्र की चीज से अधिक है, कोड को पढ़ने के लिए बहुत आसान है जहां आप स्पष्ट रूप से जानते हैं कि लूप की घोषणा में लूप सही क्यों बंद हो जाएगा।


1

मैं कहूंगा कि आम तौर पर इसका कारण यह नहीं माना जाता है कि यह एक अच्छा विचार है कि आप निर्माण का उपयोग पूरी क्षमता से नहीं कर रहे हैं। इसके अलावा, मुझे लगता है कि जब उनके छात्र "सामान" के साथ आते हैं, तो बहुत सारे प्रोग्रामिंग प्रशिक्षक इसे पसंद नहीं करते हैं। इसका मतलब है कि मुझे लगता है कि वे अपने छात्रों की प्रोग्रामिंग शैली पर प्राथमिक प्रभाव डालना पसंद करते हैं। तो शायद वह सिर्फ प्रशिक्षक का एक पालतू जानवर है।


1

मेरे लिए, समस्या पठनीयता है।

एक सही स्थिति के साथ एक बयान आपको लूप के बारे में कुछ नहीं बताता है। यह समझने के काम को और अधिक कठिन बना देता है।

इन दो स्निपेट को समझना आसान क्या होगा?

do {
  // Imagine a nice chunk of code here
} while(true);

do {
  // Imagine a nice chunk of code here
} while(price < priceAllowedForDiscount);

0

मुझे लगता है कि आपके शिक्षक के लिए ब्रेक का उपयोग करना फल प्राप्त करने के लिए पेड़ की एक शाखा को तोड़ने जैसा है, कुछ अन्य ट्रिक्स (शाखा को झुकाएं) का उपयोग करें ताकि आपको फल मिल जाए और शाखा अभी भी जीवित है। :)


0

1) कुछ भी गलत नहीं है a do -while(true)

2) आपका शिक्षक गलत है।

एनएसएफ !!:

3) अधिकांश शिक्षक शिक्षक होते हैं न कि प्रोग्रामर।


@ अपने शिक्षक के सुनने तक प्रतीक्षा करें!
पचेरियर

1
मैं स्वयं प्रोग्रामिंग के मोर्चे पर पढ़ाया जाता हूँ। मेरे द्वारा माध्यमिक विद्यालय में मेरे आईटी शिक्षक को पहचानना है, जिन्होंने हमें ड्रीमविवर का उपयोग करके वेबसाइटें बनाना सिखाया है, ताकि हर कोई एक पूर्णतया विभक्त हो ...
कोनेल

@ अपना अनुबंध दिखाने के लिए मेरे पोस्ट को
लाइक

2
"जो नहीं कर सकते, सिखाते हैं।" - यह एक बहुत बड़ा सामान्यीकरण है जो आपको नहीं लगता? क्या डॉक्टर, इंजीनियर, पायलट आदि सभी को स्वयं सिखाया जाना चाहिए क्योंकि उनके प्रशिक्षक आपके अनुसार अक्षम हैं?
filip-fku

@ filip-fku वाह वाह ~ इसे ठंडा करो!
पचेरियर

0

यदि आपका लूप बैकग्राउंड थ्रेड पर चलता है, तो यह बुरा हो सकता है, इसलिए जब आप UI थ्रेड समाप्त करके अपना एप्लिकेशन बंद करते हैं, तो कोड का वह टुकड़ा निष्पादित होता रहेगा। जैसा कि दूसरों ने पहले ही कहा था, आपको हमेशा रद्द करने का तरीका प्रदान करने के लिए किसी तरह के चेक का उपयोग करना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.