क्या लूप के लिए विभिन्न प्रकार के दो चर घोषित करना संभव है?


240

क्या C ++ में लूप के आरंभीकरण निकाय में विभिन्न प्रकार के दो चर घोषित करना संभव है?

उदाहरण के लिए:

for(int i=0,j=0 ...

दो पूर्णांकों को परिभाषित करता है। क्या मैं इनिशियलाइज़ेशन बॉडी में intए और ए को परिभाषित कर सकता हूँ char? यह कैसे किया जाएगा?


3
यह g ++ - 4.4 ( -std=c++0x) के रूप में संभव है for(auto i=0, j=0.0; ..., लेकिन c ++ 0x ग्रंथों के साथ मेल खाने के लिए g ++ - 4.5 में इस संभावना को हटा दिया गया था।
रफक

जवाबों:


133

C ++ 17 : हाँ! आपको एक संरचित बाध्यकारी घोषणा का उपयोग करना चाहिए । सिंटैक्स को gcc और clang में वर्षों से समर्थित किया गया है (चूंकि gcc-7 और clang-4.0) ( clang live example )। यह हमें एक ट्यूपल को अनपैक करने की अनुमति देता है:

for (auto [i, f, s] = std::tuple{1, 1.0, std::string{"ab"}}; i < N; ++i, f += 1.5) {
    // ...
}

ऊपर आप देंगे:

  • int i करने के लिए सेट 1
  • double f करने के लिए सेट 1.0
  • std::string s करने के लिए सेट "ab"

#include <tuple>इस तरह की घोषणा के लिए सुनिश्चित करें ।

यदि आप एक प्रकार का नाम देना चाहते हैं, तो आप tupleउन सभी प्रकारों को अंदर टाइप करके निर्दिष्ट कर सकते हैं जो मेरे पास std::stringहैं। उदाहरण के लिए:

auto [vec, i32] = std::tuple{std::vector<int>{3, 4, 5}, std::int32_t{12}}

इसका एक विशिष्ट अनुप्रयोग एक नक्शे पर चलना, कुंजी और मूल्य प्राप्त करना है,

std::unordered_map<K, V> m = { /*...*/ };
for (auto& [key, value] : m) {
   // ...
}

एक जीवंत उदाहरण यहां देखें


C ++ 14 : आप टाइप-आधारित के अलावा C ++ 11 (नीचे) के समान कर सकते हैं std::get। इसलिए std::get<0>(t)नीचे के उदाहरण में, आप कर सकते हैं std::get<int>(t)


सी ++ 11 : std::make_pairआपको ऐसा करने की अनुमति देता है, साथ ही साथ std::make_tupleदो से अधिक वस्तुओं के लिए भी।

for (auto p = std::make_pair(5, std::string("Hello World")); p.first < 10; ++p.first) {
    std::cout << p.second << std::endl;
}

std::make_pairमें दो तर्कों को वापस करेगा std::pair। तत्वों के साथ .firstऔर पहुँचा जा सकता है .second

दो से अधिक वस्तुओं के लिए, आपको एक का उपयोग करने की आवश्यकता होगी std::tuple

for (auto t = std::make_tuple(0, std::string("Hello world"), std::vector<int>{});
        std::get<0>(t) < 10;
        ++std::get<0>(t)) {
    std::cout << std::get<1>(t) << std::endl; // cout Hello world
    std::get<2>(t).push_back(std::get<0>(t)); // add counter value to the vector
}

std::make_tupleएक वैरिएड टेम्प्लेट है जो किसी भी संख्या में तर्कों (पाठ्यक्रम की कुछ तकनीकी सीमाओं के साथ) का निर्माण करेगा। तत्वों को अनुक्रमणिका द्वारा पहुँचा जा सकता हैstd::get<INDEX>(tuple_object)

पाश के लिए शरीर के भीतर आप आसानी से वस्तुओं उर्फ, आप अभी भी उपयोग करने की जरूरत है, हालांकि .firstया std::getपाश हालत और अद्यतन अभिव्यक्ति के लिए के लिए

for (auto t = std::make_tuple(0, std::string("Hello world"), std::vector<int>{});
        std::get<0>(t) < 10;
        ++std::get<0>(t)) {
    auto& i = std::get<0>(t);
    auto& s = std::get<1>(t);
    auto& v = std::get<2>(t);
    std::cout << s << std::endl; // cout Hello world
    v.push_back(i); // add counter value to the vector
}

C ++ 98 और C ++ 03 आप स्पष्ट रूप से ए के प्रकारों का नाम दे सकते हैं std::pair। यद्यपि इसे दो से अधिक प्रकारों के लिए सामान्यीकृत करने का कोई मानक तरीका नहीं है:

for (std::pair<int, std::string> p(5, "Hello World"); p.first < 10; ++p.first) {
    std::cout << p.second << std::endl;
}

5
यदि आप C ++ 17 कर रहे हैं, तो आप इसे छोड़ भी सकते हैं make_और लिख सकते हैं std::pair(1, 1.0)
मार्क ग्लिससे

बालों वाली सी ++ 14 स्टाइल टपल / पेयर बिज़नेस - ऑल गुड (शायद, अपवोटेड), लेकिन विचित्र लगती है :)
mlvljr

3
संक्षेप में: हाँ यह संभव है, लेकिन सुंदर नहीं होने जा रहा है।
कुछ प्रोग्रामर ने

हाँ, सुंदर नहीं है, लेकिन यह डोप है! पूरी तरह से टपल-ईश का आनंद लिया। :) लेकिन यह वास्तव में C ++ में छोरों के लिए एक बहुत ही
अनपेक्षित सिंथेटिक गुण है

@aderchox अगर आप अपनी गलतफहमी को स्पष्ट कर सकते हैं तो मैं जवाब को अपडेट कर सकता हूं
रयान हेनिंग

276

नहीं - लेकिन तकनीकी रूप से एक काम है-आसपास (ऐसा नहीं है कि मैं वास्तव में इसका उपयोग तब तक करूंगा जब तक कि मजबूर न हो):

for(struct { int a; char b; } s = { 0, 'a' } ; s.a < 5 ; ++s.a) 
{
    std::cout << s.a << " " << s.b << std::endl;
}

3
यह वीएस 2008 पर संकलित नहीं करता है, लेकिन कोमू पर ऑनलाइन ;-)
JRL

7
@JRL: ओह, न तो VS2005। फिर भी वीसी ++ में एक और गैर-अनुपालन सुविधा मुझे लगता है।
जॉर्ज फ्रिट्ज़च

3
मैंने पर्ल में बराबर किया है। मैंने C ++ में कोड समीक्षा के माध्यम से इस तरह से कुछ छींकने की कोशिश नहीं की है।
जॉन

21
C ++ 11 के साथ मैं डिफ़ॉल्ट उदाहरणों का उपयोग करके इस उदाहरण को छोटा बना सकता हूंstruct { int a=0; char b='a'; } s;
रयान हेनिंग

1
यह उत्तर उत्तर की आवश्यकताओं को पूरा करता है, लेकिन एक पठनीयता POV से मैं @MK पसंद करता हूं। का जवाब है। एमके का समाधान भी घुंघराले ब्रेस को जोड़कर स्कूपिंग को संबोधित करता है।
ट्रेवर बॉयड स्मिथ

221

संभव नहीं है, लेकिन आप कर सकते हैं:

float f;
int i;
for (i = 0,f = 0.0; i < 5; i++)
{
  //...
}

या, स्पष्ट रूप से के दायरे को सीमित fऔर iअतिरिक्त कोष्ठक का उपयोग:

{
    float f; 
    int i;
    for (i = 0,f = 0.0; i < 5; i++)
    {
       //...
    }
}

मुझे पता है कि यह एक बहुत पुराना सवाल है, लेकिन क्या आप बता सकते हैं कि कुछ लोग इसके चारों ओर के अतिरिक्त कोष्ठकों के साथ ऐसा क्यों करेंगे, जैसा कि आपके दूसरे उदाहरण में है?
फोर्ड

13
@fizzisist स्पष्ट रूप से f और i के कोड के उन हिस्सों के केवल हिस्सों को सीमित करता है जहां उनका उपयोग किया जाता है।
एम.के.

1
@MK। धन्यवाद, यही मुझे संदेह था। मैंने आपके उत्तर को समझाने के लिए संपादित किया।
फोर्ड

केवल एक सवाल: ऐसा क्यों? : ओ
रोहन-पटेल

क्योंकि यह 'int a = 0, b = 4' की तरह काम करता है, मुझे लगता है। कहा जा रहा है कि, स्कूपिंग एफ और मैं केवल उन नामों (जो एक उचित कारण है) के पुन: उपयोग को रोकने के लिए उपयोगी होंगे, लेकिन उत्पन्न कोड आमतौर पर एक आधुनिक संकलक (इस मामले में) के समान होगा।
आसू

14

आप आरंभीकरण में कई प्रकार की घोषणा नहीं कर सकते, लेकिन आप कई प्रकार के ईजी को असाइन कर सकते हैं

{
   int i;
   char x;
   for(i = 0, x = 'p'; ...){
      ...
   }
}

बस उन्हें अपने दायरे में घोषित करें।


3

मुझे लगता है कि सबसे अच्छा तरीका है जियान का जवाब

परंतु...


# लूप के लिए नेस्टेड

यह दृष्टिकोण गंदा है, लेकिन सभी संस्करण में हल कर सकता है।

इसलिए, मैं अक्सर इसे मैक्रो फ़ंक्शन में उपयोग करता हूं।

for(int _int=0, /* make local variable */ \
    loopOnce=true; loopOnce==true; loopOnce=false)

    for(char _char=0; _char<3; _char++)
    {
        // do anything with
        // _int, _char
    }

अतिरिक्त १।

यह भी करने के लिए declare local variablesऔर इस्तेमाल किया जा सकता है initialize global variables

float globalFloat;

for(int localInt=0, /* decalre local variable */ \
    _=1;_;_=0)

    for(globalFloat=2.f; localInt<3; localInt++) /* initialize global variable */
    {
        // do.
    }

अतिरिक्त २।

अच्छा उदाहरण: मैक्रो फ़ंक्शन के साथ।

(यदि सर्वोत्तम दृष्टिकोण का उपयोग नहीं किया जा सकता क्योंकि यह एक लूप-मैक्रो है)

#define for_two_decl(_decl_1, _decl_2, cond, incr) \
for(_decl_1, _=1;_;_=0)\
    for(_decl_2; (cond); (incr))


    for_two_decl(int i=0, char c=0, i<3, i++)
    {
        // your body with
        // i, c
    }

# अगर-स्टेटमेंट ट्रिक

if (A* a=nullptr);
else
    for(...) // a is visible

आप के लिए इनिशियलाइज़ चाहते हैं 0या nullptrआप इस चाल का उपयोग कर सकते हैं।

लेकिन मैं कठोर पढ़ने के कारण इसकी अनुशंसा नहीं करता।

और यह बग की तरह लगता है।


यह कभी भी मुझे विस्मित नहीं करता है कि कुछ लोग दूसरों से अलग कैसे सोचते हैं। मैंने ऐसी विषमताओं के बारे में कभी नहीं सोचा होगा। दिलचस्प विचार।
डॉ। पर्सन II II

1

देखें " लूप के लिए दो प्रकार के चर को परिभाषित करने का एक तरीका है? " दूसरे तरीके से लूप के लिए कई घोंसले को शामिल करना है। जॉर्ज के "स्ट्रक्चर ट्रिक" पर दूसरे तरीके का लाभ यह है कि यह (1) आपको स्थिर और गैर-स्थिर स्थानीय चर का मिश्रण करने की अनुमति देता है और (2) यह आपको गैर-प्रतिलिपि योग्य चर रखने की अनुमति देता है। नकारात्मक पक्ष यह है कि यह बहुत कम पठनीय है और कम कुशल हो सकता है।


-2

एक मैक्रो को परिभाषित करें:

#define FOR( typeX,x,valueX,  typeY,y,valueY,  condition, increments) typeX x; typeY y; for(x=valueX,y=valueY;condition;increments)

FOR(int,i,0,  int,f,0.0,  i < 5, i++)
{
  //...
}

बस याद रखें, आपका चर स्कोप इस तरह से लूप के भीतर नहीं होगा।


आप मैक्रो में कोड को अलग-अलग दायरे में उपयोग करके {और उसके द्वारा आसानी से उस सीमा को पार कर सकते हैं }
नाथन उस्मान

4
नहीं, वह नहीं कर सकता। उनकी मैक्रो लूप बॉडी को लपेटती नहीं है। वह एक अतिरिक्त ओपनिंग ब्रैकेट जोड़ सकता है, लेकिन मैक्रो का उपयोग करते समय "अतिरिक्त" क्लोजिंग ब्रैकेट की आवश्यकता होगी।
जॉन

3
यह एक दिलचस्प विचार है, लेकिन मैं जल्द ही इस पर विचार करने से पहले किसी भी अन्य उत्तर का उपयोग करूंगा।
gregn3

-2

इसके अलावा आप सी ++ में नीचे की तरह उपयोग कर सकते हैं।

int j=3;
int i=2;
for (; i<n && j<n ; j=j+2, i=i+2){
  // your code
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.