लूप के लिए C ++ से पहले कभी नहीं देखा गया


164

मैं C # एल्गोरिथ्म को C # में परिवर्तित कर रहा था। मैं इस लूप के लिए आया था:

for (u = b.size(), v = b.back(); u--; v = p[v]) 
b[u] = v;

यह C ++ में कोई त्रुटि नहीं देता है, लेकिन यह C # में करता है (int को बूल में नहीं बदल सकता)। मैं वास्तव में लूप के लिए यह पता नहीं लगा सकता, कि हालत कहाँ है?

क्या कोई समझा सकता है?

पुनश्च। बस जाँच करने के लिए, एक सूची को अनुकूलित करने के लिए लिस्ट करता है b.back () b [b.Count-1] के अनुरूप?


35
कहां है हालत? वह होगा u--। अर्ध-उपनिवेशों का उपयोग forकथन के विभिन्न भागों का परिसीमन करने के लिए किया जाता है ।
डेविड हेफर्नन

77
यह काफी सामान्य लूप है। C # संख्याओं को बूलस में नहीं बदलता है, इसलिए आपको शर्त को चालू करने की आवश्यकता है; u-- != 0;
आर। मार्टिनो फर्नांडिस

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

18
मुझे आशा है कि, कोड परिवर्तित करने के बाद, आप चर की तुलना में बेहतर नाम दे b, u, v, आदि एकमात्र कारण वे इस तरह से नामित किया गया है, क्योंकि जब कोई आपको अपनी कोड अपठनीय बन द्वारा स्मार्ट देखने के लिए करना चाहता था।
दान

33
@houbysoft: यह एक सामान्य स्टैकओवरफ़्लो समस्या है। यदि आप एक विशिष्ट शोध डोमेन में बहुत विस्तृत, अच्छी तरह से शोध और दिलचस्प प्रश्न पूछते हैं, जो एक कठिन और दिलचस्प समस्या का समाधान करता है, और आप अनुसंधान के कठिन दिनों के बाद इस तरह के सवाल का जवाब देते हैं, तो आपको केवल कुछ ही मिलेंगे दर्जन आगंतुकों और क्षेत्र में कुछ विशेषज्ञों से एक या दो upvotes। यदि आप जल्दी से बहुत सारे लाभ प्राप्त करना चाहते हैं, तो आपको इन जैसे सवालों का जवाब देना होगा। "मैं php में दो नंबर कैसे जोड़ूं", " doC ++ में क्या मतलब है" - ट्यूटोरियल की तलाश करने वाले शुरुआती लोगों से हजारों हिट मिलेंगे।
vsz

जवाबों:


320

forलूप की स्थिति मध्य में है - दो अर्धविरामों के बीच ;

सी ++ में लगभग किसी भी अभिव्यक्ति को एक शर्त के रूप में रखना ठीक है: कुछ भी जो शून्य साधनों का मूल्यांकन करता है false; गैर शून्य का मतलब है true

आपके मामले में, शर्त यह है u--: जब आप C # में कनवर्ट करते हैं, तो बस जोड़ें != 0:

for (u = b.size(), v = b.back(); u-- != 0; v = p[v]) 
    b[u] = v; //                     ^^^^ HERE

55
वैसे, थॉमस कॉमा के उपयोग से भी भ्रमित हो सकते हैं, यह अर्ध-बृहदान्त्र की तुलना में बहुत अलग है, यह आपको लूप के लिए एक सेक्शन में कई काम करने देता है (इस मामले में, यह दो वेरिएबल्स को इनिशियलाइज़ करता है)। पिछली बार जब मैंने जाँच की तो इन असामान्य निर्माणों को सबसे अधिक संभव समाधान नहीं माना गया था और इसलिए इसे कुछ लोगों द्वारा गलत माना जा सकता है।
बिल के

2
अगर मुझे सही तरीके से याद है, और एक अल्पविराम से युक्त अभिव्यक्ति के दाईं ओर अंतिम उपप्रकार का मान है। यह C से आता है और किसी भी अभिव्यक्ति में इस्तेमाल किया जा सकता है, न केवल एक लूप में।
जियोर्जियो

7
@Roger यह वही लूप नहीं होगा जब से आप लूप के अंत में यू को घटा रहे हैं, शुरुआत के बजाय (यानी b [u] = v के बजाय पहले)। वास्तव में आपको u = b.size() - 1इसके बजाय इसे इनिशियलाइज़ करना होगा ।
दिदिर एल

Fyi: मैं सिर्फ आप 500K सीमा से अधिक धक्का दिया। क्या वह कहीं दस लाख ग्राहक होने के नाते और कहीं जीतने वाला है? किसी भी मामले में: बहुत-बहुत बधाई; हमेशा अपने सटीक, तीखे जवाबों की तलाश में! बढ़ा चल; मिलते हैं 1 मिलियन की बात बनाते हुए ... बाद में इस सदी में।
घोस्टकट

165

सटीक उत्तर के बहुत सारे, लेकिन मुझे लगता है कि यह लूप के बराबर है।

for (u = b.size(), v = b.back(); u--; v = p[v]) 
   b[u] = v;

के बराबर है:

u = b.size();
v = b.back();
while(u--) {
   b[u] = v;
   v = p[v];
}

जब आप C # में अनुवाद करते हैं तो आप उस समय () प्रारूप पर विचार कर सकते हैं। मेरी राय में यह स्पष्ट है, नए प्रोग्रामरों के लिए एक जाल से कम, और उतना ही कुशल।

के रूप में अन्य लोगों ने बताया है - लेकिन मेरा उत्तर पूरा करने के लिए - यह सी # में काम करते हैं आप परिवर्तन करने की आवश्यकता होगी बनाने के लिए while(u--)करने के लिए while(u-- != 0)

... या while(u-- >0)सिर्फ मामले में यू नेगेटिव शुरू होता है। (ठीक है, b.size()कभी भी नकारात्मक नहीं होगा - लेकिन एक सामान्य मामले पर विचार करें जहां शायद कुछ और शुरू में यू)।

या, इसे और भी स्पष्ट करने के लिए:

u = b.size();
v = b.back();
while(u>0) {
   u--;
   b[u] = v;
   v = p[v];
}

यह स्पष्ट होने की तुलना में स्पष्ट है बेहतर है।


29
यह उत्तर न केवल खराब कोड को स्पष्ट करता है, बल्कि एक अच्छा विकल्प भी देता है। एक ऊपर!!
पोलोवाज़ुल

2
एक तरफ के रूप में, मैं while (u-- >0)फार्म के साथ सावधान रहना होगा । यदि रिक्ति गड़बड़ हो जाती है, तो आप एक "शून्य से नीचे" लूप के साथ समाप्त हो सकते हैं: while (u --> 0)जो पहली नज़र में सभी को भ्रमित करने के लिए जाता है। ( मुझे यकीन नहीं है कि यह वैध सी # है, लेकिन यह सी में है, और मुझे लगता है कि यह सी + + में भी हो सकता है! )
इजाकाटा

9
मुझे नहीं लगता कि आपका कोड आवश्यक रूप से स्पष्ट है। इसके forबजाय की बात whileयह है कि आप एक बयान में इनिशियलाइज़ेशन और इंक्रीमेंट / डिक्रीमेंट डालते हैं, और यह जरूरी नहीं कि कोड को समझना कठिन हो। अन्यथा, हमें बिल्कुल भी उपयोग नहीं करना चाहिए for
मुशीफिल

1
जितना संभव हो उतना कम कोड को फिर से लिखना भी महत्वपूर्ण है। (लूप के लिए, सब के बाद बदल सकता है।) आपने "u--" को दो अलग-अलग स्थानों पर रखा है, और लूप वास्तव में स्पष्ट नहीं है (मैं देख सकता हूं कि लूप एक नज़र में क्या करता है; मुझे स्कैन करना होगा कई लाइनों के साथ)। श्लोक होने के भी फायदे हैं। उन्हें निराश मत करो। हालांकि, यह कैसे लिखा जा सकता है, इसका एक अच्छा उदाहरण। यह उन लोगों के लिए समझना आसान बनाता है जो C ++ (या शायद बिल्कुल भी) में बयान के लिए उपयोग नहीं किए गए हैं।
NotKyon

2
@ इज़काटा: यह कभी भी एक ऑपरेटर नहीं है, यह एक --टोकन के बाद एक टोकन के रूप में पार्स किया जाता है >। दो अलग-अलग ऑपरेटर। एक "डाउन टू ज़ीरो" लूप, पोस्ट-डीरेसमेंट और अधिक से अधिक का एक सीधा संयोजन है। C ++ ऑपरेटर ओवरलोडिंग नए ऑपरेटर नहीं बनाता है, यह सिर्फ मौजूदा लोगों को पुन: पेश करता है।
बेन Voigt

66

शर्त यह है u--;, क्योंकि यह निर्देश के लिए दूसरी स्थिति में है ।

यदि का मान u--;0 से भिन्न है, तो इसकी व्याख्या इस प्रकार की जाएगी true(अर्थात, अनुमानित रूप से बूलियन मान के लिए true।) यदि, इसके बजाय, इसका मान 0 है, तो इसे कास्ट किया जाएगा false

यह बहुत बुरा कोड है

अपडेट: मैंने इस ब्लॉग पोस्ट में "फॉर" छोरों के लेखन पर चर्चा की । इसकी सिफारिशों को निम्नलिखित पैराग्राफ में संक्षेप में प्रस्तुत किया जा सकता है:

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

लूप के लिए सभी हिस्से छोटे और पठनीय होने चाहिए। परिवर्तनीय नामों को समझना आसान बनाने के लिए चुना जाना चाहिए।

यह उदाहरण इन पुनर्मूल्यांकन का स्पष्ट रूप से उल्लंघन करता है।


3
या यह u == 0 पर रुकेगा ... शायद?
थॉमस

2
नहीं; C ++ में int से bool में एक अंतर्निहित रूपांतरण है, जिसमें 0 को गलत में परिवर्तित किया गया है। लूप तब समाप्त हो जाएगा जब u-- == 0. C # में, ऐसा कोई अंतर्निहित रूपांतरण नहीं है, इसलिए आपको स्पष्ट रूप से u-- == 0. EDIT कहना होगा: यह आपकी पहली टिप्पणी के जवाब में है।
क्रिस

48
यह भयानक कोड है, एक बहुत ही सरल कारण के लिए; जब आप इसे पढ़ते हैं तो आप इसे आसानी से समझ नहीं सकते। यह "चतुर", एक "हैक" है; यह कोडिंग संरचनाओं के संयोजन का उपयोग करता है, और यह ज्ञान देता है कि वे पर्दे के पीछे कैसे काम करते हैं, एक ऐसा ढांचा बनाने के लिए जो काम करता है, लेकिन यह समझ को ख़राब करता है, क्योंकि यह उस रूप में नहीं है जिस पर भाषा के लेखकों की कल्पना की गई थी और इसे सबसे अधिक संप्रेषित किया गया था भाषा उपयोगकर्ता।
कीथ्स

4
बहुत बढ़िया जवाब। मैं इसे +1 करता ... यदि नहीं "यह बहुत बुरा कोड है।" कथन;)
सैंडमैन 4

14
मुझे समझ में नहीं आता है कि इतने सारे लोगों को लगता है कि यू - वास्तव में केवल कोड गायब होने (सी ++ में निहित) के कारण बुरा कोड है ! = 0 । निश्चित रूप से कोड के साथ काम करने वाला कोई भी व्यक्ति पूरी तरह से अवगत होगा कि 0 = गलत, हर दूसरे मूल्य = सचयू के पूर्व-पोस्ट-इन्क्रीमेंटिंग के बारे में भ्रम के लिए कहीं अधिक गुंजाइश है , या लोग शायद यह मानकर चल रहे हैं कि u = b.size () हमेशा v = b.back () से पहले निष्पादित होगा (मेरी समझ से निष्पादन अनुक्रम अपरिभाषित है,) लेकिन मैं सही होने के लिए खड़ा हूं)।
FumbleFingers

23

यह आपके लूप का C # फॉर्म होगा।

// back fetches the last element of vector in c++.
for (u = b.size(), v = b.back(); (u--) != 0; v = p[v]) 
{      
  b[u] = v;      
}

बस आकार () और पीछे () के लिए बराबर बदलें।

यह जो करता है वह सूची को उलट देता है और एक सरणी में संग्रहीत करता है। लेकिन C # में हमारे पास इसके लिए सिस्टम डिफाइन्ड फंक्शन है। इसलिए आपको इस लूप को भी लिखने की जरूरत नहीं है।

b = b.Reverse().ToArray();

1
v = b.back();Intializer के लिए बाहर ले जाने से आप जिस तरह से यह काम करता है, सिर्फ उसी तरीके से बदल नहीं जाता है, जब v = p[v]तक
João Portela

v = p [v] अंतिम परिणाम पर कोई प्रभाव नहीं पड़ेगा क्योंकि यह रेखा अंतिम पर निष्पादित होगी। और उसके बाद v को लूप में संदर्भित नहीं किया जाता है। यह लाइन सिर्फ यह दिखाने के लिए है कि लूप को C ++ से C # में कैसे बदला जाता है।
नरेंद्र

1
c ++ कोड v = b.back();को पुनरावृत्तियों के प्रारंभ होने से पहले एक बार v = p[v]निष्पादित किया गया था और प्रत्येक पुनरावृत्ति की शुरुआत में निष्पादित किया गया था। उस सी # संस्करण v = p[v]में अभी भी प्रत्येक पुनरावृत्ति की शुरुआत में निष्पादित किया जाता है, लेकिन v = b.back();इसके ठीक बाद निष्पादित किया जाता है, vअगले निर्देश के लिए मूल्य बदल रहा है b[u] = v;। (शायद इसे पढ़ने के बाद प्रश्न संपादित किया गया था)
जोओ पोर्टेला

5
@Rain मुद्दा है v = b.back()। आपने इसे केवल पहले के बजाय हर लूप पुनरावृत्ति पर क्रियान्वित किया है - हमें नहीं पता कि क्या back()होता है ( क्या इसके कोई दुष्प्रभाव हैं? क्या यह आंतरिक प्रतिनिधित्व को बदल देता है b?), इसलिए यह लूप एक के बराबर नहीं है प्रश्न।
इजाकाता जूल

1
@ वास्तव में, अपने आप को करीब से देखो। प्रारंभ कदम है, केवल एक बार पहले पाश शुरू होता है होता नहीं की शुरुआत में हर यात्रा । यदि v = b.back()लूप के बाहर, इसके ऊपर ले जाया गया तो आपका कोड सही होगा । (इसके अलावा, यदि आप किसी को जवाब देने की कोशिश कर रहे हैं @, तो उनके नाम के सामने उपयोग करें, इसलिए हमें एक सूचना मिलती है)
इज़काता


14

स्थिति का परिणाम है u--, जो कि मूल्य uघटाने से पहले था।

सी और सी ++ में, एक int है परोक्ष एक करके bool के लिए परिवर्तनीय != 0तुलना (0 है false, बाकी सब है true)।

b.back()एक कंटेनर में अंतिम तत्व है, जो है b[b.size() - 1], जब size() != 0


11

सी में सब कुछ गैर-शून्य true"बूलियन" संदर्भों में है, जैसे कि लूप अंत स्थिति या एक सशर्त बयान। में सी # आपको लगता है कि जांच स्पष्ट करना है: u-- != 0


यह ओपी का सवाल नहीं है। वह टर्मिनल स्थिति (इस मामले में 'u-') के मूल्यांकन के बारे में पूछ रहा है।
ApplePie

6

जैसा कि दूसरों द्वारा कहा गया है, तथ्य यह है कि सी ++ में बूलियन के लिए अंतर्निहित कास्टिंग का मतलब सशर्त है u--, जो कि मूल्य शून्य न होने पर सच होगा।

यह जोड़ने के लायक है, कि आप "जहां सशर्त है" पूछने में एक गलत धारणा है। C ++ और C # (और अन्य समान रूप से वाक्य रचना भाषाओं) में आप एक खाली सशर्त हो सकते हैं। इस मामले में यह हमेशा की तरह, सही का आकलन तो पाश हमेशा के लिए जारी है, या किसी अन्य शर्त बाहर निकलता है जब तक यह (के माध्यम से return, breakया throw)।

for(int i = 0; ; ++i)
  doThisForever(i);

दरअसल, स्टेटमेंट के किसी भी हिस्से को छोड़ दिया जा सकता है, जिस स्थिति में यह सिर्फ प्रदर्शन नहीं किया जाता है।

सामान्य तौर पर, for(A; B; C){D}या for(A; B; C)D;हो जाता है:

{A}
loopBack:
if(!(B))
  goto escapeLoop;
{D}
{C}
goto loopBack;
escapeLoop:

A, B, C या D में से किसी एक या अधिक को छोड़ा जा सकता है।

इसके परिणामस्वरूप, for(;;) अनंत छोरों के लिए कुछ एहसान । मैं ऐसा इसलिए करता हूं क्योंकि जब मैं while(true)अधिक लोकप्रिय होता हूं, तो मैं यह पढ़ता हूं कि "जब तक सत्य सत्य नहीं होता" तब तक, जो मेरे पढ़ने की तुलना for(;;) में "हमेशा के लिए" की तरह कुछ सर्वनाश लगता है ।

यह स्वाद की बात है, लेकिन चूंकि मैं दुनिया का एकमात्र व्यक्ति नहीं हूं, जैसे for(;;)कि यह जानने का मतलब है कि इसका क्या मतलब है।


4

सभी उत्तर सही हैं: -

लूप का उपयोग विभिन्न तरीकों से किया जा सकता है:

Single Statement inside For Loop
Multiple Statements inside For Loop
No Statement inside For Loop
Semicolon at the end of For Loop
Multiple Initialization Statement inside For
Missing Initialization in For Loop
Missing Increment/Decrement Statement
Infinite For Loop
Condition with no Conditional Operator.

4
for (u = b.size(), v = b.back(); u--; v = p[v]) 
   b[u] = v;

उपरोक्त कोड में, uऔर के vसाथ आरंभिक हैं b.size()और b.back()

हर बार जब स्थिति की जाँच की जाती है, तो वह विकृति कथन को भी निष्पादित करता है u--

forपाश से बाहर निकलें जब होगा uहो जाएगा 0


3

C # में मिली त्रुटि स्वयं संदेह को दूर करती है। के लिए लूप एक के लिए खोज करता है

असत्य

समाप्त करने की शर्त। और जैसा कि हम जानते हैं,

(BOOL) FALSE = (इंट) ०

लेकिन C # इसे C ++ के विपरीत अपने आप प्रोसेस नहीं कर सकता। तो जिस हालत को तुम खोज रहे हो, वह है

u--

लेकिन आपको सी # में स्थिति स्पष्ट रूप से देनी होगी

u--! = ०

या

u--> ०

लेकिन फिर भी इस तरह के कोडिंग अभ्यास से बचने की कोशिश करें।

घुमाव के दौरान

जवाब में ऊपर कहा गया है कि आपके सबसे सरल संस्करण में से एक है

पाश के लिए।


@Downvoter: डाउनवोटिंग ठीक है जहां तक ​​आप समाधान से संतुष्ट नहीं हैं, लेकिन साथ ही, कृपया कारण बताने के लिए समय निकालें, ताकि उत्तर बेहतर हो सकें।
अभनीत

3

यदि आप C / C ++ के लिए उपयोग किए जाते हैं, तो यह कोड पढ़ना इतना कठिन नहीं है, हालांकि यह बहुत अच्छा है और कोड का वह महान नहीं है। तो मुझे उन भागों की व्याख्या करें जो किसी भी चीज़ की तुलना में अधिक सिस्म हैं। लूप के लिए C का सामान्य सिंटैक्स पहले इस तरह दिखता है:

for (<initialization> ; <condition>; <increment>)
{
    <code...>
}

आरंभीकरण कोड एक बार चलाया जाता है। फिर हर लूप से पहले स्थिति का परीक्षण किया जाता है और अंत में वेतन वृद्धि को प्रत्येक लूप के बाद कहा जाता है। तो आपके उदाहरण में आप पाएंगे कि हालत क्या हैu--

u--C और C # में शर्त के रूप में क्यों काम करता है ? क्योंकि C का तात्पर्य बहुत सारी चीज़ों को बहुत अधिक धर्मान्तरित करना है और यह परेशानी का कारण बन सकता है। एक संख्या के लिए जो कुछ भी शून्य नहीं है वह सत्य है और शून्य गलत है। तो यह b.size () - 1 से 0. तक गिना जाएगा। स्थिति में साइड-इफ़ेक्ट होना थोड़ा कष्टप्रद है और इसे लूप के वेतन वृद्धि वाले हिस्से में रखना बेहतर होगा, हालाँकि बहुत सी कोड यह करता है। अगर मैं इसे लिख रहा था तो मैं इसे इस तरह से और अधिक करूंगा:

for (u = b.size() - 1, v = b.back(); u>=0; --u) 
{
    b[u] = v;
    v = p[v]
}

इसका कारण है, मेरे लिए कम से कम, यह स्पष्ट है। लूप के लिए प्रत्येक भाग काम करता है और कुछ नहीं। मूल कोड में स्थिति चर को संशोधित कर रही थी। इंक्रीमेंट पार्ट कुछ ऐसा कर रहा था जो कोड ब्लॉक आदि में होना चाहिए।

अल्पविराम ऑपरेटर आपको एक लूप के लिए भी फेंक सकता है। C में कुछ ऐसा x=1,y=2दिखता है जैसे कि एक कथन जहाँ तक संकलक का संबंध है और आरंभीकरण कोड में फिट बैठता है। यह सिर्फ प्रत्येक भाग का मूल्यांकन करता है और पिछले एक का मान लौटाता है। उदाहरण के लिए:

std::cout << "(1,2)=" << (1,2) << std::endl;

2 का प्रिंट आउट निकालेंगे।


आपके पुन: लिखने में समस्या यह है कि यदि b.size () अहस्ताक्षरित है, तो यह बहुत लंबे समय तक चलना होगा। (इसके अलावा, आप एक अर्धविराम याद कर रहे हैं।) लेकिन कम से कम आपने "डिक एंड जेन 'अच्छी अंग्रेजी नहीं ली है" दृष्टिकोण है कि इतने सारे अन्य उत्तरों और टिप्पणियों ने किया है, जो कि केवल आसान है neophytes और अन्य अकुशल प्रोग्रामर द्वारा पढ़ने के लिए।
जिम बेल्टर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.