2009-05-14 10 views
6

आप पाश के लिए एक में एक ही प्रकार के 2 वैरिएबल निर्धारित कर सकते हैं:लूप प्रारंभकर्ता में दो अलग-अलग प्रकार के चर परिभाषित करने का कोई तरीका है?

int main() { 
    for (int i = 0, j = 0; i < 10; i += 1, j = 2*i) { 
    cout << j << endl; 
    } 
} 

लेकिन यह विभिन्न प्रकार के चर निर्धारित करने गैरकानूनी है:

int main() { 
    for (int i = 0, float j = 0.0; i < 10; i += 1, j = 2*i) { 
    cout << j << endl; 
    } 
} 

वहाँ यह करने के लिए कोई तरीका है? (मुझे i लूप के अंदर j का उपयोग करने की आवश्यकता नहीं है।)

यदि आपने पूरी तरह से हैक किया है और अस्पष्ट समाधान है, तो यह मेरे लिए ठीक है।

इस संक्रमित उदाहरण में मुझे पता है कि आप दोनों चर के लिए double का उपयोग कर सकते हैं। मैं एक सामान्य जवाब की तलाश में हूं।

कृपया शरीर के बाहर किसी भी चर को स्थानांतरित करने का सुझाव न दें, शायद मेरे लिए उपयोग करने योग्य नहीं है क्योंकि एक लूप के बाद गायब होना है और मेरे कथन को foreach मैक्रो में संलग्न करना है:

#define foreach(var, iter, instr) {     \ 
    typeof(iter) var##IT = iter;      \ 
    typeof(iter)::Element var = *var##IT;   \ 
    for (; var##_iterIT.is_still_ok(); ++var##IT, var = *var#IT) { \ 
     instr;           \ 
    }            \ 
    } 

यह इस प्रकार किया जा सकता है:

foreach(ii, collection, { 
    cout << ii; 
}). 

लेकिन मैं कुछ है कि इस तरह इस्तेमाल किया जाएगा की जरूरत है:

foreach(ii, collection) 
    cout << ii; 

कृपया किसी भी रनटाइम ओवरहेड को पेश न करें (लेकिन यह संकलित करने में धीमा हो सकता है)।

+1

में और कुछ दिए गए नाम के साथ कई चर प्रकार घोषणा के लिए भी कुछ सामान्य तरीका प्रदान करता है आपको पता है कि वहाँ हो सकता है कोई समाधान नहीं है जो आपके द्वारा दी गई सभी शर्तों को पूरा करता है? –

+6

"कृपया शरीर के बाहर के किसी भी चर को स्थानांतरित करने का सुझाव न दें, शायद मेरे लिए उपयोग न करें क्योंकि लूप के बाद हीटरेटर गायब हो जाना चाहिए।" ऐसा लगता है जैसे आपने कृत्रिम आवश्यकता बनाई है। आप जिस चीज की परवाह करते हैं वह इटरेटर का दायरा है, न कि यह इसके शरीर में है या नहीं। स्कोपिंग के बारे में अपने पूर्वकल्पित विचारों को जोड़ने के बिना * केवल * अपनी आवश्यकताओं को समझाने का प्रयास करें। लोगों के लिए आपकी समस्या को समझना और आपकी मदद करना आसान होगा। – dss539

+3

हर बार जब कोई समाधान के साथ आता है, तो आप "कृपया मत कहो ....." और टिप्पणी करें "उपयोगी नहीं है ... शरीर बदलता है ...." आप ऐसा क्यों करते हैं ?? –

उत्तर

9

यहाँ बढ़ावा पूर्वप्रक्रमक का उपयोग कर एक संस्करण है (यह सिर्फ मनोरंजन के लिए है वास्तविक दुनिया जवाब के लिए, @ रसोई के एक ऊपर देखें।):

FOR((int i = 0)(int j = 0.0), i < 10, (i += 1, j = 2 * i)) { 

} 

पहले भाग को निर्दिष्ट घोषणाओं के एक दृश्य: (a)(b)...। बाद में घोषित चर वे उनके सामने घोषित चर का उल्लेख कर सकते हैं। दूसरा और तीसरा हिस्सा सामान्य रूप से होता है। जहां कॉमा दूसरे और तीसरे हिस्सों में होते हैं, ब्रांड्स का उपयोग मैक्रो तर्कों को अलग करने के लिए रोकने के लिए किया जा सकता है।

मेरे लिए ज्ञात दो चालें हैं जो चर को घोषित करने के लिए उपयोग की जाती हैं जो बाद में एक मैक्रो के बाहर जोड़े गए यौगिक बयान में दिखाई देती हैं। पहले उपयोग की शर्तें, जैसे कि:

if(int k = 0) ; else COMPOUND_STATEMENT 

फिर k दिखाई दे रहा है। स्वाभाविक रूप से, इसे हमेशा false का मूल्यांकन करना होगा। तो इसका इस्तेमाल हमारे द्वारा नहीं किया जा सकता है। दूसरा संदर्भ यह है:

for(int k = 0; ...; ...) COMPOUND_STATEMENT 

यही वह है जो मैं यहां उपयोग करने जा रहा हूं। हमें केवल COMPOUND_STATEMENT का एक पुनरावृत्ति देखने के लिए देखना होगा। वास्तविक for लूप जो वृद्धि और स्थिति जांच को अंत में आना है, इसलिए संलग्न मिश्रित कथन इसके लिए उपयुक्त है।

#include <boost/preprocessor.hpp> 
#include <iostream> 

#define EMIT_DEC_(R,D,DEC) \ 
    for(DEC; !_k;) 

#define FOR(DECS, COND, INC) \ 
    if(bool _k = false) ; else \ 
     BOOST_PP_SEQ_FOR_EACH(EMIT_DEC_, DECS, DECS) \ 
     for(_k = true; COND; INC) 

int main() { 
    FOR((int i = 0)(float j = 0.0f), i < 10, (i += 1, j = 2 * i)) { 
     std::cout << j << std::endl; 
    } 
} 

यह for बयान का एक समूह बनाने की है, प्रत्येक एक दूसरे में नेस्ट।यह फैलता में:

if(bool _k = false) ; else 
    for(int i = 0; !_k;) 
    for(float j = 0.0f; !_k;) 
     for(_k = true; i < 10; (i += 1, j = 2 * i)) { 
     std::cout << j << std::endl; 
     } 
+0

बिल्कुल मुझे क्या चाहिए। धन्यवाद –

+0

यह पता चला है कि पहले अगर दो और दो अनुकूलित किए गए हैं। –

24

कृपया चर के किसी भी बाहर शरीर के लिए शायद मेरे लिए नहीं प्रयोग करने योग्य स्थानांतरित करने के लिए, सुझाव नहीं के रूप में इटरेटर सिर्फ पाश के बाद गायब हो गया है है।

आप ऐसा कर सकता है:

#include <iostream> 

int main(int, char *[]) { 
    { 
     float j = 0.0; 

     for (int i = 0; i < 10; i += 1, j = 2*i) { 
      std::cout << j << std::endl; 
     } 
    } 

    float j = 2.0; // works 

    std::cout << j << std::endl; 

    return 0; 
} 
+0

सेकंड में इसे मारो! –

+0

मुझे भी, और यहां तक ​​कि अधिक बॉयलरप्लेट कोड के साथ भी! :) – Reunanen

+0

दुर्भाग्य से उपयोगी नहीं –

0

तुम सिर्फ क्यों घोषित करने और पाश के लिए के बाहर अपने चर प्रारंभ नहीं करते हैं? आप अभी भी परीक्षण और वृद्धि कर सकते हैं क्योंकि आपके पास अभी है।

+0

क्योंकि कथन के लिए मैक्रो में उपयोग किया जाएगा। –

+0

ठीक है, आपकी समस्या है। मैक्रोज़ स्वाभाविक रूप से त्रुटिपूर्ण और खतरनाक हैं और आप उन स्थितियों में भाग लेते हैं जिन्हें वे संभाल नहीं सकते हैं। उस मामले के लिए, आप अक्सर खराब हो जाते हैं क्योंकि मैक्रोज़ उनमें अल्पविराम के साथ टेम्पलेट को नहीं समझते हैं। मैक्रो पर छोड़ दो, आपकी सभी समस्याएं दूर हो गई हैं। –

+0

जैसा कि पहले से ही उल्लेख किया गया है, बस अपनी अभिव्यक्ति को एक नए दायरे में रखें {..}। पॉज़ड्रायम। –

7
{ 
    int i = 0; 
    float j = 0.0; 
    for (; i < 10; i += 1, j = 2*i) { 
    cout << j << endl; 
    } 
} 

ब्लॉक के बाद वेरिएबल "गायब हो जाते हैं"।

+1

मैक्रोज़ के भीतर चर बनाने के लिए यह कैननिकल दृष्टिकोण है। –

6

यह इटरेटर (या इस मामले में, नाव) जब यह कोई और अधिक आवश्यक है गायब कर देगा:

int main() { 
    // some code... 

    { 
    float j = 0.0; 
    for (int i = 0; i < 10; i += 1, j = 2*i) { 
     cout << j << endl; 
    } 
    } 

    // more code... 
} 
10

खैर, यह बदसूरत है। लेकिन आप जोड़ी का उपयोग कर सकते हैं।

int main() { 
    for (std::pair<int,float> p(0,0.0f); 
     p.first < 10; 
     p.first += 1, p.second = 2*p.first) { 
    cout << p.second << endl; 
    } 
} 
+1

अच्छा विचार! और फिर boost :: tuple का उपयोग करके दो से अधिक प्रकार के लिए सामान्यीकृत करें। – Reunanen

+0

अच्छा विचार है लेकिन यह लूप के शरीर को बदलने के लिए मजबूर करता है, इसलिए मैं इसे स्वीकार नहीं कर सकता –

+3

boost :: tuple के साथ जवाब देना चाहता था, लेकिन आपने मुझे हराया :) लेकिन क्यों नहीं (std :: pair p (0 , 0.0 एफ); पी। फर्स्ट <10; पी। फर्स्ट ++, पी। सेकेंड = 2 * पी। फर्स्ट) {...}? इस खूबसूरत कोड दस्त के लिए –

2

कृपया के रूप में इटरेटर बस पाश के बाद गायब हो गया है मेरे लिए के बाहर शरीर के लिए चर के किसी भी ले जाने के लिए सुझाव है कि नहीं है, शायद उपयोगी नहीं।

आप अभी भी ऐसा कर सकते हैं, और अतिरिक्त चीज को घुमावदार ब्रेसिज़ में डालकर अतिरिक्त चर को दायरे से बाहर कर सकते हैं।

int main() 
{ 
    { 
    float j = 0.0; 
    for (int i = 0; i < 10; i += 1, j = 2*i) 
    { 
     cout << j << endl; 
    } 
    } 
    // more code... 
} 

इस तरह j सही पाश के बाद क्षेत्र से बाहर जाना होगा।

2

आवश्यकताओं के साथ आप सबसे सरल कोड मैं के बारे में सोच सकते हैं है:

for (int i = 0; i < 10; ++i) 
{ 
    float f = i * 2; 
    std::cout << f << std::endl; 
} 

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

तो असली नाव (मैं यह सोचते हैं कि जब से मैं सच में किसी पूर्णांक नहीं है, च एक नाव भी नहीं हो सकता है) के निर्माण के लिए ज्यादा मूल्य है, तो एक के अंदर encapsulating के अन्य समाधान फिर नियत से ज्यादा महंगा है दायरे को सीमित करने के लिए घुंघराले ब्रेसिज़ की अतिरिक्त जोड़ी सबसे अच्छा विकल्प होगा।

+0

अरग! मुझे * एक * सेकंड से मारो! (एसओ के अनुसार) – Reunanen

1
int main() { 
    for (int i = 0, float j = 0.0; i < 10; i += 1, j = 2*i) { 
    cout << j << endl; 
    } 
} 

शायद मैं घना हो रहा हूं, लेकिन आपको फ्लोट घोषित करने की भी आवश्यकता क्यों है? जब भी आप लूप को छोड़ते हैं तो आप बस इसे "फेंक दें"। सही?

for(int i=0; i<10; ++i) 
    cout << (float)2*i << endl; 

आपको जम्मू की आवश्यकता क्यों है?

1

आप कहते हैं कि i अपने स्वयं के प्रकार है, और तुम सिर्फ, सही ji से बाहर उत्पन्न करने के लिए की जरूरत है? आसान। j मान उत्पन्न करने के लिए i की कक्षा में एक सदस्य फ़ंक्शन जोड़ें, और हमेशा इसका उपयोग करें। यदि आप चाहें तो संभवतः उस सदस्य फ़ंक्शन को कॉल को "छुपाएं" करने के लिए मैक्रो भी बना सकते हैं। :-)

6

आप मैक्रो के साथ समस्या हो रही है, वहाँ एक मानक do..while चाल है कि पूरी तरह से काम करता है:

#define MYFOR(init, test, post, body) \ 
    do \ 
    { \ 
     init \ 
     for(; test; post) \ 
      body \ 
    } while(0) 

इसका इस्तेमाल इस प्रकार है:

MYFOR(int i = 0; float j = 0.0f; , i < 10 , (i += 1, j = 2.0f * i), 
    { 
     cout << j << endl; 
    }); 

यह बदसूरत है, लेकिन यह करता है आप क्या चाहते हैं: i और j का दायरा मैक्रो से do..while लूप द्वारा सीमित है, और इसके अंत में अर्धविराम की आवश्यकता होती है, इसलिए आप इसे किसी अन्य/कथन के पूर्वानुमान में डालकर काट नहीं पाएंगे।

+0

यह सबसे अच्छा है जो मैं आया था। लेकिन मुझे शरीर को मैक्रो से अलग करने की जरूरत है। –

4

EDIT: प्रश्न एक बार और बदल गया है। सवाल अब स्पष्ट रूप से एक foreach पाश को लागू करना चाहता है। सरल जवाब:

#include <boost/foreach.hpp> 
void(std::vector<int>& v) { 
    BOOST_FOREACH(int & x, v) { 
     x = x*2; 
    } 
} 

एक कोड ब्लॉक

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

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

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

void f(std::vector<int>& container) 
{ 
    INTVECTOR_FOREACH(int & x, container) 
    { 
     x = x*2; 
    } 
} 
अन्य भाषाओं में foreach के समान अर्थ विज्ञान के साथ

: एक्स कंटेनर में प्रत्येक तत्व को संदर्भित किया जाता है, इसलिए समारोह वास्तव में पूर्णांक वेक्टर के अंदर प्रत्येक मूल्य दोगुना हो जाता है कि

अब सरलीकृत मैक्रो का कोड:।

#define INTVECTOR_FOREACH(variable, container) \ 
    for (std::vector<int>::iterator it = container.begin(); it!=container.end(); ++it) \ 
     if (bool condition=false) {} else \ 
     for (variable = *it; !condition; condition=true) 

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

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

5

यह एक भी बदसूरत है, लेकिन एक के लिए लूप

int main() { 
    for (struct { int i; float j; } x = { }; 
     x.i < 10; x.i += 1, x.j = 2 * x.i) { 
    cout << x.j << endl; 
    } 
} 
+0

+1 रचनात्मक समाधान :-) –

+0

यह समाधान केवल जीसीसी के साथ काम करता है, वीएस 2010 नहीं ... – Gob00st

संबंधित मुद्दे

 संबंधित मुद्दे