यदि स्थिति A का मिलान किया जाता है, तो C की कार्रवाई करने के लिए शर्त B का मिलान किया जाना चाहिए


148

मेरा सवाल यह है कि:

if (/* condition A */)
{
    if(/* condition B */)
      {
         /* do action C */
      }
    else
      /* ... */
}
else
{
   /* do action C */
}

क्या केवल दो बार के बजाय एक बार कार्रवाई सी कोड लिखना संभव है?

इसे सरल कैसे करें?


56
एक फ़ंक्शन में "एक्शन सी" के लिए कोड डालें?
CinCout

26
यह दुख की बात है कि यह वास्तव में C ++ प्रश्न से संबंधित नहीं है जो HNQ को मिला: /
YSC

2
मेरी मदद करने के लिए आप सभी को धन्यवाद! शुरुआत में, मैं सिर्फ यह सुनिश्चित करना चाहता हूं कि सब कुछ ठीक हो जाए इसलिए मैंने एक नेस्टेड का उपयोग किया। ऐसा इसलिए है क्योंकि यह सबसे सरल तरीका है जिसका मैंने अनुमान लगाया था। मैं अगली बार सवाल पूछने के बाद और प्रयास करने की कोशिश करूंगा। सभी का दिन शुभ हो :)
Starf15h

13
यह एक बहुत अच्छी रणनीति है: कोड लिखें जो पहले काम करता है, फिर बाद में इसे सुरुचिपूर्ण और कुशल बनाने की चिंता करें।
कोड-अपरेंटिस

3
@ समय पर मैंने इसे उत्तर के रूप में पोस्ट किया। एक साइड नोट पर, वहां कम वोट देखकर दुख होता है।
CinCout

जवाबों:


400

इस प्रकार की समस्याओं में आपका पहला कदम हमेशा तर्क तालिका बनाना है।

A | B | Result
-------------------
T | T | do action C
T | F | ...
F | T | do action C
F | F | do action C

एक बार जब आप तालिका बना लेते हैं, तो समाधान स्पष्ट होता है।

if (A && !B) {
  ...
}
else {
  do action C
}

ध्यान दें कि यह तर्क, जबकि कम है, भविष्य के प्रोग्रामर को बनाए रखना मुश्किल हो सकता है।


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

14
यदि मूल्यांकन Bके साइड इफेक्ट्स हैं तो लॉजिक टेबल को इसके लिए जिम्मेदार होना चाहिए।
यक्क - एडम नेवरामोंट

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

52
शायद ध्यान देने योग्य, मामले में A && !Bमामले को नो-सेशन है: !(A && !B)के बराबर है !A || Bजिसका मतलब है कि आप कर सकते हैं if (!A || B) { /* do action C */ }और एक खाली ब्लॉक से बचें।
केरेन

54
यदि if (A && !B)भविष्य के प्रोग्रामर को बनाए रखना वास्तव में मुश्किल है, तो वास्तव में उनकी कोई मदद नहीं है।
रे

65

आपके पास दो विकल्प हैं:

  1. एक फ़ंक्शन लिखें जो "एक्शन सी" करता है।

  2. अपने तर्क को पुनर्व्यवस्थित करें ताकि बयानों के दौरान आपके पास इतने सारे नेस्टेड न हों। अपने आप से पूछें कि किन स्थितियों के कारण "एक्शन सी" होता है। मुझे ऐसा लग रहा है कि ऐसा तब होता है जब या तो "स्थिति बी" सही होती है या "स्थिति ए" झूठी होती है। हम इसे "NOT A OR B" के रूप में लिख सकते हैं। सी कोड में इसका अनुवाद करते हुए, हम प्राप्त करते हैं

    if (!A || B) {
        action C
    } else {
        ...
    }
    

इस तरह के भावों के बारे में अधिक जानने के लिए, मैं सुझाव देता हूं कि "बूलियन बीजगणित", "तर्क को विधेय", और "विधेय की गणना करें"। ये गहरे गणितीय विषय हैं। आपको यह सब सीखने की जरूरत नहीं है, बस मूल बातें।

आपको "शॉर्ट सर्किट मूल्यांकन" के बारे में भी सीखना चाहिए। इस वजह से, भावों का क्रम आपके मूल तर्क की नकल करने के लिए महत्वपूर्ण है। जबकि B || !Aतार्किक रूप से समतुल्य है, इस स्थिति का उपयोग करते हुए "एक्शन सी" निष्पादित करेगा जब Bमूल्य के बिना सच है A


15
@YakkMMorgan के नियम देखें।
कोड-अपरेंटिस

@ कोड-अपरेंटिस कृपया मेरी बुरी तार्किक सोच को क्षमा करें। मैं पूछना चाहता हूं कि क्या (A || B) और (A &&) के बीच कोई अंतर है? लगता है दोनों मेरी समस्या के लिए ठीक हैं। मेरा मतलब है आपका और QuestionC का दृष्टिकोण।
Starf15h

6
@ Starf15h एक अन्य महत्वपूर्ण अंतर है: जहां "एक्शन सी" निष्पादित होता है। यह अंतर हमारे दो समाधानों को बिल्कुल समकक्ष बनाता है। मेरा सुझाव है कि आप "डीमोरिन के नियम" को गूगल करें जो आपको यह समझने में मदद करे कि यहां क्या चल रहा है।
कोड-अपरेंटिस

5
दो समाधान बिल्कुल समतुल्य हैं, लेकिन वास्तव ...में जो है उसके आधार पर व्यावहारिक अंतर हो सकता है । यदि यह कुछ भी नहीं है (यानी, "अगर इन शर्तों को पूरा किया जाता है, तो सी करें; अन्यथा कुछ भी नहीं करें"), तो यह स्पष्ट रूप से बेहतर समाधान है, क्योंकि elseबयान को केवल पूरी तरह से छोड़ दिया जा सकता है।
Janus Bahs Jacquet

1
इसके अलावा, ए और बी के नामों के आधार पर, यह व्यवस्था प्रश्नवाचक व्यवस्था की तुलना में मानव के लिए अधिक पठनीय या कम पठनीय हो सकती है।
माइकल - व्हेयर क्ले शिर्की

15

आप इस तरह से कथन को सरल बना सकते हैं:

if ((A && B) || (!A)) // or simplified to (!A || B) as suggested in comments
{
    do C
}

अन्यथा एक अलग फ़ंक्शन में 'C' के लिए कोड डालें और इसे कॉल करें:

DoActionC()
{
    ....
    // code for Action C
}
if (condition A)
{
    if(condition B)
      {
         DoActionC(); // call the function
      }
    else
      ...
}
else
{
   DoActionC(); // call the function
}

7
या अधिक बसif (!A || B)
Tas

2
तार्किक रूप से, ((A && B) ||! A) (B ||! A) के समतुल्य है
कोड-अपरेंटिस

@ कोड-अपरेंटिस B || !Aपरिणाम होगा करने के लिए trueकेवल तभी Bहै trueवास्तव में के लिए जाँच के बिना, Aशॉर्ट-सर्किट की वजह से
CinCout

1
@CinCout अच्छी बात है। जबकि मेरा कथन एक सैद्धांतिक बूलियन तर्क के दृष्टिकोण से अभी भी सही है, मैंने शॉर्ट सर्किट बूलियन ऑपरेटरों की व्यावहारिकताओं को ध्यान में नहीं रखा। सौभाग्य से, मेरे अपने उत्तर में सही क्रम है।
कोड-अपरेंटिस

1
इसलिए एक तर्क के नजरिए से, कोई फर्क नहीं पड़ता। हालांकि, एक रखरखाव और पठनीयता के दृष्टिकोण से, वास्तव में जो कुछ है Aऔर Bउसके आधार पर बहुत बड़ा अंतर हो सकता है ।
कोड-अपरेंटिस

14

पैटर्न मिलान के साथ एक भाषा में, आप समाधान को एक तरह से व्यक्त कर सकते हैं जो प्रश्न के उत्तर में सत्य-तालिका को अधिक सीधे दर्शाता है।

match (a,b) with
| (true,false) -> ...
| _ -> action c

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


10

समस्या कथन:

यदि स्थिति A का मिलान किया जाता है, तो C की कार्रवाई करने के लिए शर्त B का मिलान किया जाना चाहिए

निहितार्थ का वर्णन करता है : एक बी का तात्पर्य , एक तार्किक प्रस्ताव के बराबर !A || B(जैसा कि अन्य उत्तरों में वर्णित है):

bool implies(bool p, bool q) { return !p || q; }

if (implies(/* condition A */,
            /* condition B */))
{
    /* do action C */
}

शायद इसे inlineसी के लिए और constexprसाथ ही सी ++ के लिए चिह्नित करें ?
einpoklum

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

6

उह, इसने मुझे भी उलझाया , लेकिन जैसा कि कोड-अपरेंटिस द्वारा बताया गया है कि हमें do action Cनेस्टेड elseब्लॉक को चलाने या चलाने की गारंटी है, इस प्रकार कोड को सरल बनाया जा सकता है:

if (not condition A or condition B) {
    do action C
} else {
    ...
}

इस तरह हम 3 मामलों को मार रहे हैं:

  1. नेस्ट do action Cअपने प्रश्न के तर्क में आवश्यक condition Aऔर condition Bहोना करने के लिए true- इस तर्क में, अगर हम 2 तक पहुँचने nd में अवधि if-statement तो हम जानते हैं कि condition Aहै trueइस प्रकार हम सभी का मूल्यांकन करने कि है की जरूरत condition Bहैtrue
  2. नेस्टेड elseअपने प्रश्न के तर्क में -block आवश्यक condition Aहोने के लिए trueऔर condition Bहोना करने के लिए false- एक ही रास्ता है कि हम तक पहुँच सकते हैं elseइस तर्क में -block अगर होगा condition Aथे trueऔर condition Bथेfalse
  3. elseआपके प्रश्न के लॉजिक में आउटर -ब्लॉक condition Aहोना आवश्यक है false- इस लॉजिक में यदि condition Aगलत है तो हम भीdo action C

मुझे यहाँ सीधा करने के लिए कोड-अपरेंटिस के लिए सहारा। मैं उनके उत्तर को स्वीकार करने का सुझाव दूंगा , क्योंकि उन्होंने बिना संपादन के इसे सही ढंग से प्रस्तुत किया: /


2
ध्यान दें कि "स्थिति ए" को फिर से मूल्यांकन करने की आवश्यकता नहीं है। C ++ में, हमारे पास बहिष्कृत मध्य का कानून है। यदि "कंडीशन ए" गलत नहीं है, तो "ए कंडीशन" जरूरी है।
कोड-अपरेंटिस

1
शॉर्ट-सर्किट मूल्यांकन के कारण, Bकेवल !Aगलत होने पर मूल्यांकन किया जाएगा । इसलिए elseबयानों को निष्पादित करने के लिए दोनों को विफल होना चाहिए ।
कोड-अपरेंटिस

यहां तक कि शॉर्ट सर्किट के बिना मूल्यांकन !A || Bगलत है वास्तव में दोनों जब !Aऔर Bझूठे हैं। इसलिए, निष्पादित Aहोने पर सच होगा else। पुनर्मूल्यांकन की आवश्यकता नहीं है A
कोड-अपरेंटिस

@ कोड-अपरेंटिस खैर बदबू, उत्कृष्ट अवलोकन, मैंने अपना उत्तर सही कर दिया है, लेकिन सुझाव दिया कि आपका स्वीकार किया जाएगा। मैं सिर्फ यह बताने की कोशिश कर रहा हूं कि आपने पहले से क्या रखा है।
जोनाथन मी

काश, मैं आपको प्रत्येक मामले को समझाने के लिए एक और वोट दे सकता।
कोड-अपरेंटिस

6

तर्क अवधारणा में, आप इस समस्या को हल कर सकते हैं:

f = ab +! a
f =?

एक सिद्ध समस्या के रूप में, यह परिणाम है f = !a + b। समस्या को साबित करने के कुछ तरीके हैं जैसे कि सत्य सारणी, कर्णघट मानचित्र आदि।

तो सी आधारित भाषाओं में आप निम्नानुसार उपयोग कर सकते हैं:

if(!a || b)
{
   // Do action C
}

पुनश्च: कर्णघट मानचित्र का उपयोग परिस्थितियों की अधिक जटिल श्रृंखला के लिए भी किया जाता है। यह बूलियन बीजगणित के भावों को सरल बनाने की एक विधि है।


6

हालांकि पहले से ही अच्छे उत्तर हैं, मैंने सोचा कि यह दृष्टिकोण किसी ऐसे व्यक्ति के लिए और भी सहज हो सकता है जो बूलियन बीजगणित के लिए नया है, फिर एक सत्य तालिका का मूल्यांकन करने के लिए।

पहली चीज़ जो आप करना चाहते हैं, वह है, सी। को निष्पादित करने के लिए किन शर्तों के तहत आप यह चाहते हैं (a & b)। इसके अलावा जब !a। तो आपके पास है (a & b) | !a

यदि आप कम से कम करना चाहते हैं तो आप जा सकते हैं। जैसे "सामान्य" अंकगणित में, आप बाहर गुणा कर सकते हैं।

(a & b) | !a = (a | !a) & (b | !a)। ए | ए हमेशा सच होता है, इसलिए आप बस इसे पार कर सकते हैं, जो आपको न्यूनतम परिणाम के साथ छोड़ देता है b | !a:। मामले में आदेश में फर्क पड़ता है, क्योंकि आप केवल b की जांच करना चाहते हैं! अगर यह सही है (उदाहरण के लिए कब! और एक nullpointer चेक है और b पॉइंटर पर एक ऑपरेशन है जैसे @LordFarquaad ने अपनी टिप्पणी में बताया है, तो आप कर सकते हैं दो स्विच करना चाहते हैं।

अन्य मामला (/ * ... * /) हमेशा निष्पादित किया जाएगा जब सी निष्पादित नहीं किया जाता है, इसलिए हम इसे दूसरे मामले में डाल सकते हैं।

यह भी ध्यान देने योग्य है कि यह संभवत: एक्शन सी को एक विधि में डालने का एक तरीका है।

जो हमें निम्नलिखित कोड के साथ छोड़ देता है:

if (!A || B)
{
    doActionC()  // execute method which does action C
}
else
{
   /* ... */ // what ever happens here, you might want to put it into a method, too.
}

इस तरह आप अधिक ऑपरेंड वाले शब्दों को भी कम कर सकते हैं, जो जल्दी से सत्य तालिकाओं के साथ बदसूरत हो जाता है। एक और अच्छा तरीका है कर्णघट मानचित्र। लेकिन मैं अब इसमें गहराई तक नहीं जाऊंगा।


4

कोड को टेक्स्ट की तरह दिखने के लिए, बूलियन झंडे का उपयोग करें। यदि तर्क विशेष रूप से अस्पष्ट है, तो टिप्पणी जोड़ें।

bool do_action_C;

// Determine whether we need to do action C or just do the "..." action
// If condition A is matched, condition B needs to be matched in order to do action C
if (/* condition A */)
{
    if(/* condition B */)
      do_action_C = true; // have to do action C because blah
    else
      do_action_C = false; // no need to do action C because blarg
}
else
{
  do_action_C = true; // A is false, so obviously have to do action C
}

if (do_action_C)
  {
     DoActionC(); // call the function
  }
else
  {
  ...
  }


2

मैं सी को एक विधि में निकालूंगा, और फिर सभी मामलों में जल्द से जल्द फ़ंक्शन को बाहर कर दूंगा। elseअंत में एक ही चीज के साथ क्लॉस को हमेशा संभव होने पर उल्टा होना चाहिए। यहाँ एक कदम से कदम उदाहरण है:

निकालें C:

if (A) {
   if (B)
      C();
   else
      D();
} else
   C();

पहले ifसे छुटकारा पाने के लिए पहले पलटे else:

if (!A) {
   C();
   return;
}

if (B)
   C();
else
   D();

दूसरे से छुटकारा पाएं else:

if (!A) {
   C();
   return;
}

if (B) {
   C();
   return;
} 

D();

और फिर आप देख सकते हैं कि दो मामलों में एक ही शरीर है और संयुक्त किया जा सकता है:

if (!A || B) {
   C();
   return;
}

D();

वैकल्पिक चीजें बेहतर होंगी:

  • संदर्भ पर निर्भर करता है, लेकिन अगर !A || Bभ्रामक है, तो इरादे को स्पष्ट करने के लिए इसे एक या अधिक चर पर निकालें

  • जो भी हो C()या D()गैर-असाधारण मामला अंतिम होना चाहिए, इसलिए यदि D()अपवाद है, तो ifपिछली बार एक पलटना चाहिए


2

झंडे का उपयोग करके भी इस समस्या को हल किया जा सकता है

int flag = 1; 
if ( condition A ) {
    flag = 2;
    if( condition B ) {
        flag = 3;
    }
}
if(flag != 2) { 
    do action C 
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.