c++ - रचन - विवरण चिन्ह के उदाहरण




सी अल्पविराम ऑपरेटर का उपयोग (14)

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

MyVector foo = 2, 3, 4, 5, 6;

इस प्रश्न का उत्तर यहां दिया गया है:

आप इसे लूप कथन के लिए उपयोग करते हैं, लेकिन यह कहीं भी कानूनी वाक्यविन्यास है। अन्यत्र, यदि कोई हो, तो आपने इसके लिए क्या उपयोग किए हैं?


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

foo=bar*2, plugh=hoo+7;

इस पर कोई स्पष्ट लाभ नहीं देता है:

foo=bar*2;
plugh=hoo+7;

लूप के अलावा एक जगह जहां मैंने इसे इस्तेमाल किया है, अगर / अन्य संरचनाओं में, जैसे:

if (a==1)
... do something ...
else if (function_with_side_effects_including_setting_b(), b==2)
... do something that relies on the side effects ...

आप फ़ंक्शन को IF से पहले रख सकते हैं, लेकिन यदि फ़ंक्शन को चलाने में लंबा समय लगता है, तो यदि आप आवश्यक नहीं हैं, तो आप इसे करने से बचना चाहेंगे, और यदि फ़ंक्शन को तब तक नहीं किया जाना चाहिए जब तक कोई नहीं! = 1, तो यह नहीं है विकल्प। विकल्प आईएफ की एक अतिरिक्त परत घोंसला है। यह वास्तव में मैं आमतौर पर करता हूं क्योंकि उपरोक्त कोड थोड़ा सा गूढ़ है। लेकिन मैंने इसे अब कॉमा रास्ता किया है और फिर क्योंकि घोंसले भी गूढ़ है।


एकमात्र बार मैंने कभी देखा है , एक लूप के बाहर इस्तेमाल किया ऑपरेटर एक तीसरे वक्तव्य में एक आकलन करना था। यह बहुत समय पहले था इसलिए मैं सटीक बयान वापस नहीं कर सकता लेकिन यह ऐसा कुछ था:

int ans = isRunning() ? total += 10, newAnswer(total) : 0;

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

उनका कोड बहुत तेज़ लेकिन अस्पष्ट था, मुझे खुशी है कि मुझे इसके साथ काम करने की ज़रूरत नहीं है।


क्यूमु में कुछ कोड है जो लूप के सशर्त हिस्से के भीतर अल्पविराम ऑपरेटर का उपयोग करता है (qemu-queue.h में QTAILQ_FOREACH_SAFE देखें)। उन्होंने निम्नलिखित में क्या उबाल दिया:

#include <stdio.h>

int main( int argc, char* argv[] ){
  int x = 0, y = 0;

  for( x = 0; x < 3 && (y = x+1,1); x = y ){
    printf( "%d, %d\n", x, y );
  }

  printf( "\n%d, %d\n\n", x, y );

  for( x = 0, y = x+1; x < 3; x = y, y = x+1 ){
    printf( "%d, %d\n", x, y );
  }

  printf( "\n%d, %d\n", x, y );
  return 0;
}

... निम्नलिखित आउटपुट के साथ:

0, 1
1, 2
2, 3

3, 3

0, 1
1, 2
2, 3

3, 4

इस लूप के पहले संस्करण में निम्नलिखित प्रभाव हैं:

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

मानक से निकोलस गोय का उद्धरण दिया गया, तो ऐसा लगता है जैसे आप लूप के लिए एक-लाइनर लिख सकते हैं जैसे:

int a, b, c;
for(a = 0, b = 10; c += 2*a+b, a <= b; a++, b--);
printf("%d", c);

लेकिन अच्छा भगवान, आदमी, क्या आप वास्तव में अपने सी कोड को इस तरह से अधिक अस्पष्ट बनाना चाहते हैं?


मुझे लगता है कि आम तौर पर सी का कॉमा केवल उपयोग करने के लिए एक अच्छी शैली नहीं है क्योंकि यह याद करने में बहुत आसान है - या तो किसी और द्वारा आपके कोड को पढ़ने / समझने / ठीक करने की कोशिश कर रहा है, या आप स्वयं लाइन के नीचे एक महीने हैं। परिवर्तनीय घोषणाओं के बाहर और लूप के लिए, ज़ाहिर है, जहां यह मूर्खतापूर्ण है।

आप इसका उपयोग कर सकते हैं, उदाहरण के लिए, एक टर्नरी ऑपरेटर (? :), ala में एकाधिक कथन पैक करने के लिए:

int x = some_bool ? printf("WTF"), 5 : fprintf(stderr, "No, really, WTF"), 117;

लेकिन मेरे देवता, क्यों?! (मैंने इसे वास्तविक कोड में इस तरह से उपयोग किया है, लेकिन दुर्भाग्यवश दिखाने के लिए इसका उपयोग नहीं है)


मैंने इसे एक मैक्रो के लिए इस्तेमाल किया है "किसी भी प्रकार का मान किसी आउटपुट बफर को चार * द्वारा इंगित किया गया है, और उसके बाद बाइट्स की आवश्यक संख्या से पॉइंटर बढ़ाएं", इस तरह:

#define ASSIGN_INCR(p, val, type)  ((*((type) *)(p) = (val)), (p) += sizeof(type))

अल्पविराम ऑपरेटर का उपयोग करना मतलब है कि मैक्रो को अभिव्यक्तियों में या वांछित विवरणों के रूप में उपयोग किया जा सकता है:

if (need_to_output_short)
    ASSIGN_INCR(ptr, short_value, short);

latest_pos = ASSIGN_INCR(ptr, int_value, int);

send_buff(outbuff, (int)(ASSIGN_INCR(ptr, last_value, int) - outbuff));

इसने कुछ दोहराए गए टाइपिंग को कम कर दिया लेकिन आपको सावधान रहना होगा कि यह बहुत पढ़ा नहीं जा सकता है।

कृपया इस उत्तर here मेरा अत्यधिक लंबा संस्करण here


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

सरलीकृत उदाहरण:

#define SomeMacro(A) ( DoWork(A), Permute(A) )

यहां B=SomeMacro(A) का परिणाम "रिटर्न" करता है और इसे "बी" असाइन करता है।


यह कभी-कभी मैक्रोज़ में उपयोग किया जाता है, जैसे डीबग मैक्रोज़ इस तरह:

#define malloc(size) (printf("malloc(%d)\n", (int)(size)), malloc((size)))

(लेकिन इस भयानक विफलता को देखो, वास्तव में, इसके लिए क्या हो सकता है जब आप इसे अधिक करते हैं।)

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


लूप के बाहर, और यहां तक ​​कि कोड गंध की सुगंध भी हो सकती है, एकमात्र जगह जिसे मैंने अल्पविराम ऑपरेटर के लिए एक अच्छा उपयोग के रूप में देखा है, हटाए जाने के हिस्से के रूप में है:

 delete p, p = 0;

विकल्प पर एकमात्र मूल्य यह है कि यदि आप दो लाइनों पर हैं तो आप इस ऑपरेशन के केवल आधा गलती से कॉपी / पेस्ट कर सकते हैं।

मुझे यह भी पसंद है क्योंकि यदि आप इसे आदत से बाहर करते हैं, तो आप शून्य असाइनमेंट को कभी नहीं भूलेंगे। (बेशक, क्यों auto auto_ptr के somekind के अंदर नहीं है, smart_ptr, shared_ptr, आदि wrapper एक अलग सवाल है।)


सी ++ में दो हत्यारा कॉमा ऑपरेटर विशेषताएं:

ए) जब तक विशिष्ट स्ट्रिंग का सामना नहीं किया जाता है तब तक स्ट्रीम से पढ़ें (कोड DRY रखने में मदद करता है):

 while (cin >> str, str != "STOP") {
   //process str
 }

बी) कन्स्ट्रक्टर प्रारंभकर्ताओं में जटिल कोड लिखें:

class X : public A {
  X() : A( (global_function(), global_result) ) {};
};

सी भाषा (साथ ही सी ++) ऐतिहासिक रूप से दो पूरी तरह से अलग प्रोग्रामिंग शैलियों का मिश्रण है, जिसे कोई "कथन प्रोग्रामिंग" और "अभिव्यक्ति प्रोग्रामिंग" के रूप में संदर्भित कर सकता है। जैसा कि आप जानते हैं, प्रत्येक प्रक्रियात्मक प्रोग्रामिंग भाषा सामान्य रूप से अनुक्रमिक और शाखाकरण के रूप में ऐसी मौलिक संरचनाओं का समर्थन करती है। ये मौलिक संरचनाएं सी / सी ++ भाषाओं में दो रूपों में मौजूद हैं: एक कथन प्रोग्रामिंग के लिए, एक अभिव्यक्ति प्रोग्रामिंग के लिए दूसरा।

उदाहरण के लिए, जब आप बयान के संदर्भ में अपना प्रोग्राम लिखते हैं, तो आप अलग-अलग बयान के अनुक्रम का उपयोग कर सकते हैं ; । जब आप कुछ ब्रांचिंग करना चाहते हैं, तो आप कथन का उपयोग करते हैं। आप चक्र और अन्य प्रकार के नियंत्रण हस्तांतरण विवरणों का भी उपयोग कर सकते हैं।

अभिव्यक्ति प्रोग्रामिंग में वही संरचनाएं आपके लिए भी उपलब्ध हैं। यह वास्तव में है , ऑपरेटर खेल में आता है। ऑपरेटर , अभिव्यक्ति प्रोग्रामिंग में अनुक्रमिक अभिव्यक्तियों के विभाजक से अलग कुछ भी नहीं, यानी ऑपरेटर प्रोग्रामिंग में समान भूमिका निभाता है ; स्टेटमेंट प्रोग्रामिंग में करता है। अभिव्यक्ति प्रोग्रामिंग में ब्रांचिंग के माध्यम से किया जाता है?: ऑपरेटर और, वैकल्पिक रूप से, && और || शॉर्ट-सर्किट मूल्यांकन गुणों के माध्यम से ऑपरेटरों। (अभिव्यक्ति प्रोग्रामिंग में कोई चक्र नहीं है। और उन्हें रिकर्सन के साथ बदलने के लिए आपको कथन प्रोग्रामिंग लागू करना होगा।)

उदाहरण के लिए, निम्नलिखित कोड

a = rand();
++a;
b = rand();
c = a + b / 2;
if (a < c - 5)
  d = a;
else
  d = b;

जो पारंपरिक कथन प्रोग्रामिंग का एक उदाहरण है, अभिव्यक्ति प्रोग्रामिंग के संदर्भ में फिर से लिखा जा सकता है

a = rand(), ++a, b = rand(), c = a + b / 2, a < c - 5 ? d = a : d = b;

या के रूप में

a = rand(), ++a, b = rand(), c = a + b / 2, d = a < c - 5 ? a : b;

या

d = (a = rand(), ++a, b = rand(), c = a + b / 2, a < c - 5 ? a : b);

या

a = rand(), ++a, b = rand(), c = a + b / 2, (a < c - 5 && (d = a, 1)) || (d = b);

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

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

एक और अतिरिक्त नोट के रूप में: सी ++ भाषा में फ़ैक्टर-आधारित प्रोग्रामिंग एक महत्वपूर्ण भूमिका निभाती है, जिसे "अभिव्यक्ति प्रोग्रामिंग" के दूसरे रूप के रूप में देखा जा सकता है। सी ++ डिजाइन में मौजूदा रुझानों के मुताबिक, इसे कई स्थितियों में पारंपरिक स्टेटमेंट प्रोग्रामिंग पर बेहतर माना जा सकता है।


बूस्ट असाइनमेंट लाइब्रेरी एक उपयोगी, पठनीय तरीके से अल्पविराम ऑपरेटर को अधिभारित करने का एक अच्छा उदाहरण है। उदाहरण के लिए:

using namespace boost::assign;

vector<int> v; 
v += 1,2,3,4,5,6,7,8,9;

ASSERT मैक्रोज़ में कुछ टिप्पणी जोड़ने में यह बहुत उपयोगी है:

ASSERT(("This value must be true.", x));

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





comma-operator