2009-03-23 20 views
8

मैं सी सीख रहा हूँ और एक साधारण प्रोग्राम है कि प्रत्येक होना द्विआधारी संख्या मान लिया 2 स्ट्रिंग मानों को लेकर अंकगणितीय संचालन प्रदर्शन करेंगे उपयोगकर्ता चयन के अनुसार लेखन:सी में बाइनरी अंकगणित करने का सबसे अच्छा तरीका?

  • दो मान जोड़ें,
  • घटाना इनपुट 2 इनपुट 1 से, या
  • दो मानों को गुणा करें।

मेरा कार्यान्वयन मानता है कि स्ट्रिंग में प्रत्येक वर्ण एक बाइनरी बिट है, उदा। char bin5 = "0101";, लेकिन यह एक समय में एक चरित्र स्ट्रिंग के माध्यम से पार्स करने के लिए एक दृष्टिकोण बहुत मूर्ख लगता है। आदर्श रूप में, मैं सीधे द्विआधारी मूल्यों के साथ काम करना चाहता हूं।

सी में ऐसा करने का सबसे प्रभावी तरीका क्या है? इनपुट को scanf() के बजाय बाइनरी मानों के रूप में इलाज करने का एक बेहतर तरीका है और स्ट्रिंग से प्रत्येक बिट प्राप्त करें?

मैंने कुछ शोध किया लेकिन मुझे कोई ऐसा दृष्टिकोण नहीं मिला जो शुरुआत के परिप्रेक्ष्य से स्पष्ट रूप से बेहतर था। किसी भी सुझाव की सराहना की जाएगी!

उत्तर

12

सलाह:
वहाँ काफी नहीं है कि स्पष्ट रूप से एक समय में स्ट्रिंग के माध्यम से एक चरित्र अग्रसर और यह सुनिश्चित करें उपयोगकर्ता केवल लोगों को और शून्य में प्रवेश कर रही है की तुलना में बेहतर है। ध्यान रखें कि भले ही आप वास्तव में तेजी से असेंबली दिनचर्या लिख ​​सकते हैं यदि आप मानते हैं सबकुछ 1 या 0 है, तो आप वास्तव में ऐसा नहीं करना चाहते हैं। उपयोगकर्ता कुछ भी दर्ज कर सकता है, और यदि आप खराब हो जाते हैं या नहीं तो आप उन्हें बताने में सक्षम होना चाहते हैं।

यह सच है कि यह वास्तव में वास्तविक संख्याओं को जोड़ने के लिए जोड़े गए चक्रों की तुलना में दिमागी दबदबा धीमा लगता है, लेकिन क्या वास्तव में कोई फर्क नहीं पड़ता कि आपको नैनोसेकंद या मिलीसेकंड में आपका जवाब मिल जाए? मनुष्य वैसे भी विलंबता के 30 मिलीसेकंड का पता लगा सकते हैं।

अंत में, उपयोगकर्ता से इनपुट प्राप्त करने के लिए पहले से ही अधिक समय लगता है और स्ट्रिंग को पार्स करने या संख्याओं को जोड़ने के लिए स्क्रीन पर आउटपुट लिखने के लिए पहले से ही अधिक समय लगता है, इसलिए आपका एल्गोरिदम शायद ही यहां बाधा है। वास्तव में computationally गहन चीजों के लिए अपने फैंसी अनुकूलन सहेजें :-)।

आपको यहां पर ध्यान देना चाहिए कि कार्य कम मानव शक्ति-गहन बना रहा है। और, यह पता चला है कि किसी ने आपके लिए पहले से ही ऐसा किया है।

समाधान:
the strtol() manpage पर एक नज़र डालें:

long strtol(const char *nptr, char **endptr, int base); 

यह आपको एक लंबे के लिए किसी भी आधार में एक स्ट्रिंग (nptr) में परिवर्तित करने देगा। यह भी त्रुटियों की जांच करता है। एक द्विआधारी स्ट्रिंग परिवर्तित करने के लिए नमूना उपयोग:

#include <stdlib.h> 

char buf[MAX_BUF]; 
get_some_input(buf); 

char *err; 
long number = strtol(buf, &err, 2); 
if (*err) { 
    // bad input: try again? 
} else { 
    // number is now a long converted from a valid binary string. 
} 

आपूर्ति बेस 2 strtol बताता द्विआधारी शाब्दिक कन्वर्ट करने के लिए।

+0

नकारात्मक बाइनरी संख्या तार असामान्य हैं, इसलिए आप शायद strtoul (3) – camh

0

तारों को पूर्णांक में पार्स करना आसान नहीं होगा, और फिर पूर्णांक पर अपने गणित निष्पादित करना आसान नहीं होगा?

मुझे लगता है कि यह एक स्कूल असाइनमेंट है, लेकिन मैं आपको ऊपर उठा रहा हूं क्योंकि आप इसे एक अच्छा प्रयास दे रहे हैं।

+0

यह वास्तव में मैंने किया है। चूंकि मुझे एक संख्यात्मक डेटाटाइप (हेक्स के 0xFF के विपरीत) में बाइनरी रेडिक्स में संख्याओं का प्रतिनिधित्व करने का कोई तरीका नहीं मिला, इसलिए मैं दशमलव संख्याओं पर संचालन कर रहा हूं और बाइनरी मानों में परिवर्तित कर रहा हूं। मेरे प्रश्न की उत्पत्ति एक असाइनमेंट से संबंधित है, लेकिन अब यह किया जाता है। – jmlane

3

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

लेकिन चूंकि आप सी सीख रहे हैं, मैंने स्ट्रेटोल के बिना थोड़ा संस्करण किया है, यह न तो तेज़ या सुरक्षित है, लेकिन मैंने उदाहरण के रूप में थोड़ा हेरफेर के साथ थोड़ा सा खेला।

int main() 
{ 
    unsigned int data = 0; 
    int i = 0; 

    char str[] = "1001"; 

    char* pos; 
    pos = &str[strlen(str)-1]; 

    while(*pos == '0' || *pos == '1') 
    { 
     (*pos) -= '0'; 
     data += (*pos) << i; 

     i++; 
     pos--; 
    } 

    printf("data %d\n", data); 
    return 0; 
} 
1

सर्वश्रेष्ठ प्रदर्शन प्राप्त करने के लिए, आपको अपने कार्यों में भरोसेमंद और अविश्वसनीय इनपुट के बीच अंतर करने की आवश्यकता है।

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

// Check untested number, return NULL if bad. 
char *checkBinNum (char *num) { 
    char *ptr; 

    // Check for valid number. 
    for (ptr = num; *ptr == '0'; ptr++) 
     if ((*ptr != '1') && (*ptr != '0')) 
      return NULL; 

    return num; 
} 

:

// General purpose compression removes leading zeroes. 
void compBinNum (char *num) { 
    char *src, *dst; 

    // Find first non-'0' and move chars if there are leading '0' chars. 
    for (src = dst = num; *src == '0'; src++); 
    if (src != dst) { 
     while (*src != '\0') 
      *dst++ = *src++; 
     *dst = '\0'; 
    } 

    // Make zero if we removed the last zero. 
    if (*num == '\0') 
      strcpy (num, "0"); 
} 

फिर एक चेकर समारोह है कि या तो रिटर्न मूल्य में पारित कर दिया, या शून्य अगर यह अवैध था प्रदान करते हैं: सबसे पहले, हम एक सामान्य प्रयोजन यथा-स्थान संपीड़न समारोह दिखाता हूँ इनपुट समारोह में ही:

#define MAXBIN 256 

// Get number from (untrusted) user, return NULL if bad. 
char *getBinNum (char *prompt) { 
    char *num, *ptr; 

    // Allocate space for the number. 
    if ((num = malloc (MAXBIN)) == NULL) 
     return NULL; 

    // Get the number from the user. 
    printf ("%s: ", prompt); 
    if (fgets (num, MAXBIN, stdin) == NULL) { 
     free (num); 
     return NULL; 
    } 

    // Remove newline if there. 
    if (num[strlen (num) - 1] == '\n') 
     num[strlen (num) - 1] = '\0'; 

    // Check for valid number then compress. 
    if (checkBinNum (num) == NULL) { 
     free (num); 
     return NULL; 
    } 
    compBinNum (num); 

    return num; 
} 

अन्य कार्यों को जोड़ने या गुणा इनपुट ग्रहण करने के लिए लिखा जाना चाहिए करने के लिए पहले से ही मान्य है, क्योंकि यह वीं में कार्यों में से एक द्वारा बनाया गया है जाएगा पुस्तकालय है यह सवाल करने के लिए प्रासंगिक नहीं है के बाद से मैं उनके लिए कोड प्रदान नहीं करेगा: उपयोगकर्ता के अलावा अन्य कहीं से अपने डेटा स्रोत के लिए चुनता

char *addBinNum (char *num1, char *num2) {...} 
char *mulBinNum (char *num1, char *num2) {...} 

, तो आप उन्हें यह प्रमाणित करने के लिए checkBinNum() कॉल करने के लिए अनुमति दे सकता है।

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

-1

मानते हैं कि एक स्ट्रिंग एक द्विआधारी संख्या है क्योंकि इसमें केवल सेट {0,1} से अंक खतरनाक हैं। उदाहरण के लिए, जब आपका इनपुट "11" होता है, तो उपयोगकर्ता दशमलव में ग्यारह का मतलब हो सकता है, तीन बाइनरी में नहीं। यह इस प्रकार की लापरवाही है जो भयानक बग को जन्म देती है। आपका इनपुट अस्पष्ट रूप से अपूर्ण है और आपको वास्तव में अनुरोध करना चाहिए कि उपयोगकर्ता आधार भी निर्दिष्ट करता है।

+0

पीएस का उपयोग करना चाहते हैं। आम तौर पर जब लोग 11 देखते हैं या टाइप करते हैं, तो वे तीन से अधिक और पुरानी आदतों को गहराई से मरने का अनुमान लगाते हैं। – Liberius

+0

एक अच्छा बिंदु। यदि मैं एक जेनेरिक-उपयोग स्क्रिप्ट बना रहा था, तो उपयोगकर्ता को पसंद की रेडिक्स चुनने की अनुमति देना इनपुट त्रुटियों को कम करने के लिए आदर्श होगा। इस विशेष उपयोग-मामले में, यह अच्छी तरह से स्थापित किया गया था कि बाइनरी मान केवल इनपुट के लिए उपयोग किया जाएगा। उस ने कहा, उन मामलों में विशिष्टता की अनुमति देना सबसे अच्छा है जहां इनपुट अस्पष्टता संभव है। – jmlane

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