क्या `c> = '0'` या` c> = 48` की जांच करना बेहतर है?


46

मेरे कुछ सहयोगियों के साथ एक चर्चा के बाद, मैं एक 'दार्शनिक' सवाल हूं कि जावा में चार डेटा प्रकार का सबसे अच्छा व्यवहार कैसे किया जाता है।

मान लीजिए कि एक साधारण परिदृश्य (जाहिर है कि यह केवल एक बहुत ही सरल उदाहरण है , जिसमें मेरे प्रश्न का एक अभ्यास अर्थ दिया गया है ) , इनपुट के रूप में एक स्ट्रिंग 's' को देखते हुए, आपको इसमें मौजूद संख्यात्मक वर्णों की संख्या गिननी होगी।

ये 2 संभावित उपाय हैं:

1)

    for(int i=0; i<s.length(); i++) {
        if(s.charAt(i) >= 48 && s.charAt(i) <= 57) {
            n++;
        }
    }

2)

    for(int i=0; i<s.length(); i++) {
        if(s.charAt(i) >= '0' && s.charAt(i) <= '9' ) {
            n++;
        }
    }

जावा सर्वोत्तम प्रथाओं में दोनों में से कौन अधिक 'स्वच्छ' और अनुरूप है?


141
जब आप वास्तव में '0' और '9' का मतलब करेंगे तो आप 48 और 57 क्यों लिखेंगे? जैसा आपका मतलब है वैसा ही लिखिए।
ब्रैंडिन नोव

9
प्रतीक्षा करें कि आप क्या कर रहे हैं, जावा में VK_आपके द्वारा उपयोग किया जाने वाला स्थिरांक है, दूसरा चार कोड का उपयोग करने से बेहतर है चार्ट जावा एक प्रकार की सुरक्षित भाषा है जो आपके क्रॉस-टाइप चेकिंग को नहीं करना है। @ ब्रैंडिन इसे कोडिंग प्रैक्टिस कहा जाता है
मार्टिन बार्कर

12
6 से अधिक लोगों को जज करने की जहमत के बिना, यह एक अच्छा सवाल है। क्या आप संख्या के रूप में चार का उपयोग कर रहे हैं? यदि ऐसा है तो संख्या का उपयोग करें। क्या आप इसे अक्षरों के रूप में उपयोग कर रहे हैं? यदि ऐसा है तो पत्र का उपयोग करें।
एलेक चैले

17
@MartinBarker VK_*स्थिरांक कुंजियों के अनुरूप हैं चरित्र नहीं ।
कोडइन्चोसोस

2
यह निर्धारित करने में मुझे कुछ मिनट लगे कि यह कोड आपके प्रश्न के संबंध में क्या करता है। पहले से ही यह स्पष्ट नहीं है क्योंकि यह मानता है कि मैं (1) में जानता हूं कि मुझे पता है कि यह आईएसओ-लैटिन 1 की अंक सीमा है। इसलिए यह रखरखाव के दृष्टिकोण से इसे समस्याग्रस्त बनाता है।
साइबरस्कुल

जवाबों:


124

दोनों भयानक हैं, लेकिन पहला और अधिक भयानक है।

दोनों जावा की अंतर्निहित क्षमता को अनदेखा करने का निर्णय लेते हैं कि कौन से अक्षर "संख्यात्मक" हैं (विधियों के माध्यम से Character)। लेकिन पहले वाले ने न केवल स्ट्रिंग्स के यूनिकोड की प्रकृति को अनदेखा किया, यह मानते हुए कि केवल 0123456789 हो सकता है, यह चरित्र कोड का उपयोग करके इस अमान्य तर्क को भी अस्पष्ट करता है जो केवल चरित्र एन्कोडिंग के इतिहास के बारे में कुछ पता होने पर समझ में आता है।


33
आप यह क्यों मान रहे हैं कि गैर-एएससीआईआई अंकों को अस्वीकार करना गलत है? वह संदर्भ पर निर्भर करता है।
कोडइन्चोस

21
@CodesInChaos यदि आप वास्तव में संख्यात्मक वर्णों को खोजना चाहते हैं , तो 0123456789 के लिए स्कैनिंग बिल्कुल गलत है। यदि आप वास्तव में केवल इन दस पात्रों के लिए स्कैन करना चाहते हैं, तो वे अनिवार्य रूप से अर्थहीन टोकन हैं जो केवल गलती से उन लोगों के लिए परिचित हैं जो केवल ASCII / ISO-Latin को जानते हैं। इसमें कुछ भी गलत नहीं है - मुझे अक्सर ऐसा करना पड़ता है, जैसे कि विरासत सॉफ्टवेयर के साथ बातचीत करना जो वास्तव में केवल उन दस पात्रों को स्वीकार करता है। लेकिन फिर आपको matches("[0-9]+")ऐतिहासिक रूप से प्रेरित रेंज ट्रिक का फायदा उठाने के बजाय कुछ का उपयोग करके अपने इरादे स्पष्ट करना चाहिए ।
किलियन फोथ

15
कर रहे हैं पूरी चौड़ाई अंक , जो ASCII अंकों के रूप में एक ही तरह लग रही है, और सॉफ्टवेयर के सामान्य एक बहुत में उन्हें ASCII अंक के स्थान पर स्वीकार करना आवश्यक है। (जाहिर है कि बहुत सारे सॉफ़्टवेयर टूट गए हैं, "बहुत कुछ" की परिभाषा के आधार पर। आप आसानी से बता सकते हैं क्योंकि एक देश में सॉफ़्टवेयर विक्रेताओं को दूसरे देश को बेचना असंभव लगता है क्योंकि विक्रेता दूसरे देशों की आवश्यकताओं का सम्मान नहीं करते हैं। )
rwong

37
A a a a a a a a a a a a a a a a
ब्लूराजा - डैनी पफ्लुगुफ़ेते

14
"दोनों भयानक हैं", लेकिन आप सही समाधान कहना भूल गए ;-)
क्रॉम्स्टर का कहना है कि मोनिका

163

न तो। जावा के बिल्ट-इन कैरेक्टर क्लास को आपके लिए बता दें ।

for (int i = 0; i < s.length(); ++i) {
  if (Character.isDigit(s.charAt(i))) {
    ++n;
  }
}

ASCII अंकों की तुलना में कुछ अधिक वर्ण श्रेणियां हैं जो अंकों के रूप में गणना करते हैं, और न ही आपके द्वारा पोस्ट किए गए उदाहरण उन्हें गिनेंगे। JavaDoc के लिए Character.isDigit()सूचियों मान्य अंक होने के रूप में इन चरित्र पर्वतमाला:

कुछ यूनिकोड वर्ण श्रेणियाँ जिनमें अंक होते हैं:

  • '\ u0030' '\ u0039' के माध्यम से, ISO-LATIN-1 अंक ('0' '9') के माध्यम से
  • '\ u0669', अरबी-इंडिक अंकों के माध्यम से '\ u0660'
  • '\ u06F9' के माध्यम से '\ u06F9', विस्तारित अरबी-इंडिक अंक
  • देवनागरी अंकों के माध्यम से '\ u0966'
  • '\ uFF10' 'पूर्णांक अंकों' के माध्यम से

कई अन्य वर्ण श्रेणियों में भी अंक होते हैं।

यह कहा जा रहा है, Character.isDigit()इस सूची के साथ भी एक प्रतिनिधि करना चाहिए । जैसे ही नए यूनिकोड विमानों को आबाद किया जाता है, जावा कोड को अपडेट किया जाएगा। JVM को अपग्रेड करने से पुराने अंकों के काम को नए अंकों के अक्षर के साथ सहज रूप से किया जा सकता है। यह DRY भी है : कहीं और संदर्भित एक स्थान पर "यह एक अंक है" कोड को स्थानीय करके, कोड दोहराव (यानी बग) के नकारात्मक पहलुओं से बचा जा सकता है। अंत में, अंतिम पंक्ति पर ध्यान दें: यह सूची संपूर्ण नहीं है, और अन्य अंक हैं।

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


इस नियम का एकमात्र अपवाद यह है कि क्या आपको वास्तव में शाब्दिक ASCII अंकों के लिए परीक्षण करने की आवश्यकता है, न कि अन्य अंकों की। उदाहरण के लिए, यदि आप एक स्ट्रीम पार्स कर रहे हैं और केवल ASCII अंक (अन्य अंकों के विपरीत) का विशेष अर्थ है, तो इसका उपयोग करना उचित नहीं होगा Character.isDigit()

उस मामले में, मैं एक और विधि लिखूंगा, उदाहरण के लिए MyClass.isAsciiDigit()और तर्क को वहां डालूंगा। आपको कोड पुन: उपयोग के समान लाभ मिलते हैं, नाम सुपर स्पष्ट है कि यह क्या जाँच कर रहा है, और तर्क सही है।


4
वास्तव में चाल को करने वाले स्वच्छ कोड प्रदान करने के लिए महान जवाब।
पियरे अरलाउड

27

यदि आप कभी भी C में एक एप्लिकेशन लिखते हैं जो EBCDIC का उपयोग मूल चरित्र सेट के रूप में करता है और ASCII वर्णों को संसाधित करने की आवश्यकता होती है तो उपयोग करें 48और 57। क्या आप ऐसा कर रहे हैं? मुझे ऐसा नहीं लगता।

उपयोग करने के बारे में isDigit(): यह निर्भर करता है। क्या आप JSON पार्सर लिख रहे हैं? केवल 0करने के लिए 9अंकों के रूप में स्वीकार कर रहे हैं, तो उपयोग नहीं करते हैं isDigit(), के लिए जाँच >= '0'और <= '9'। क्या आप उपयोगकर्ता इनपुट संसाधित कर रहे हैं? isDigit()जब तक आपके बाकी कोड वास्तव में स्ट्रिंग को संभाल सकते हैं और इसे सही ढंग से नंबर में बदल सकते हैं, तब तक उपयोग करें ।


3
वास्तव में आप जावा में एप्लिकेशन लिख सकते हैं जो ईबीसीडीआईसी को प्राप्त और रिटर्न करता है। यह कोई मज़ा नहीं है।
Thorbjørn रेवन एंडरसन

इसी तरह का 'नॉट फन' कोड के माध्यम से चल रहा था जिसे EBCDIC वर्णों के दशमलव मानों का उपयोग करते हुए लिखा गया था, जब इसे एक क्रॉस-प्लेटफॉर्म वातावरण में परिवर्तित किया गया ...
Gwyn Evans

1
यदि आप जावा में EBCDIC डेटा संसाधित कर रहे हैं, तो संभवतः आपको इसे वर्णों के प्रसंस्करण से पहले जावा देशी UTF-16 वर्णक्रम में परिवर्तित करना चाहिए। लेकिन मुझे लगता है कि वास्तव में आवेदन पर निर्भर करता है; उम्मीद है कि यदि आपके कार्यक्रम को EBCDIC से निपटना है, तो आप समझेंगे कि क्या करने की आवश्यकता है।
माइकल बूर

1
मुख्य बिंदु यह है कि जावा में EBCDIC के प्रसंस्करण के लिए '0' और 48 दोनों एक अंक शून्य का पता लगाने के लिए गलत हैं । अधिक वर्तमान में, C, C ++ आदि में '\ n' और 'r' कार्यान्वयन को परिभाषित किया गया है, यदि आप एक गैर-विंडोज संकलक का उपयोग करके किसी फ़ाइल में एक विंडोज सीआर / एलएफ जोड़ी का पता लगाना चाहते हैं, तो इसके बजाय दशमलव मानों की बेहतर जांच करें '\ n' और '\ r' के लिए जाँच कर रहा है।
gnasher729

12

दूसरा उदाहरण स्पष्ट रूप से श्रेष्ठ है। जब आप कोड को देखते हैं तो दूसरे उदाहरण का अर्थ तुरंत स्पष्ट होता है। पहले उदाहरण का अर्थ केवल स्पष्ट है यदि आपने अपने सिर में पूरे ASCII तालिका को याद किया है।

आपको किसी विशिष्ट वर्ण की जाँच, या वर्णों की श्रेणी या वर्णों की जाँच करनी चाहिए।

1) एक विशिष्ट चरित्र के लिए जाँच करना।

साधारण पात्रों के लिए, अक्षर शाब्दिक, जैसे, का उपयोग करें if(ch=='z')...। यदि आप टैब या लाइन ब्रेक जैसे विशेष वर्णों के खिलाफ जांच करते हैं, तो आपको पलायन का उपयोग करना चाहिए, जैसे if (ch=='\n')...। यदि आप जिस चरित्र की जाँच कर रहे हैं वह असामान्य है (उदाहरण के लिए तुरंत पहचाने जाने योग्य नहीं या मानक कीबोर्ड पर उपलब्ध नहीं), तो आप शाब्दिक वर्ण के बजाय हेक्स वर्ण कोड का उपयोग कर सकते हैं। लेकिन चूंकि एक हेक्स कोड एक "जादू मूल्य" है, आप इसे एक निरंतर और दस्तावेज़ में निकाल देंगे:

const char snowman = 0x2603; // snowman char used to detect encoding issues
...
if (ch==showman)...

हेक्स कोड वर्ण कोड निर्दिष्ट करने का मानक तरीका है।

2) एक चरित्र वर्ग या सीमा के लिए जाँच

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

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


1
मैं यह भी '\x2603'स्पष्ट करने के बजाय हेक्स में वर्ण शाब्दिक लिखने की सिफारिश करूंगा कि आप एक हेक्साडेसिमल एन्कोडिंग के साथ एक चरित्र के लिए मूल्य का परीक्षण कर रहे हैं और न केवल किसी भी यादृच्छिक संख्या।
wefwefa3

-4

यह हमेशा उपयोग करने के लिए बेहतर है c >= '0'क्योंकि c >= 48आपको एससी कोड में कन्वर्ट करने की आवश्यकता है।


3
यह उत्तर क्या कहता है जो पहले से ही एक सप्ताह से पहले के उत्तर में नहीं कहा गया था?

-5

रेग्युलर एक्सप्रेशंस ( RegEx s) में अंकों के लिए एक विशिष्ट वर्ण वर्ग होता है - \d- जिसका उपयोग आपके स्ट्रिंग से किसी अन्य वर्ण को निकालने के लिए किया जा सकता है। परिणामी स्ट्रिंग की लंबाई वांछित मूल्य है।

public static int countDigits(String str) {
    str = Objects.requireNonNull(str).trim();

    return str.replaceAll("[^\\d]", "").length();
}

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


जाँच करने के लिए बहुत ही सुंदर तरीका!
केविन रॉबेल 15

Regexes इस तरह के एक कार्य के लिए ओवरकिल हैं
Pharap

2
@StefanoBragaglia आपके जवाब को दोबारा पढ़ने के बाद मुझे लगता है कि यह वास्तव में सवाल का जवाब नहीं देता है।
छपरा

2
आपका जवाब "मैं एक स्ट्रिंग में अंकों की गणना कैसे करता हूं" की समस्या को हल करने का एक अलग तरीका प्रदान करता है। यह कोड के नमूने और स्थिरांक के निरूपण के साथ अंतर्निहित समस्या का उत्तर नहीं देता है - या तो संख्याओं या वर्णों के रूप में।

2
यह वास्तव में अंकों की गणना नहीं करता है (यह सिर्फ आपको बताता है कि आपके द्वारा सभी अंकों को हटाने के बाद स्ट्रिंग की लंबाई क्या है, जो न तो यहां है और न ही है), लेकिन मैं मानता हूं कि यह वास्तव में सवाल का जवाब नहीं देता है। उदाहरण के लिए, कोई भी पात्रों को तार से हटाने के बारे में नहीं पूछ रहा था। सवाल यह है कि एक चरित्र के संख्यात्मक की जांच करने के लिए उचित सर्वोत्तम अभ्यास के तरीके के बारे में पूछ रहा है।
doppelgreener 7
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.