2010-08-02 7 views
14

मैंने पढ़ लिया है strlen के उपयोग इस तरह इस तरह के परीक्षण से ज्यादा महंगा है:लूप स्थिति में strlen() का उपयोग सिर्फ शून्य चरित्र की जांच करने से धीमा है?

हम एक स्ट्रिंग x 100 वर्ण लंबा है।

मुझे लगता है कि

for (int i = 0; i < strlen(x); i++) 

इस कोड से ज्यादा महंगा है:

for (int i = 0; x[i] != '\0'; i++) 

यह सच है? हो सकता है कि दूसरा कोड कुछ परिस्थितियों में काम नहीं करेगा, तो क्या पहले इसका उपयोग करना बेहतर होगा?

क्या यह नीचे के साथ बेहतर होगा?

for (char *tempptr = x; *tempptr != '\0'; tempptr++) 
+3

दूसरा लूप मोटे तौर पर 'स्ट्रेलन' आंतरिक रूप से करता है; मुझे अभी भी –

+1

प्रश्न का बिंदु नहीं दिख रहा है और इसे जांचें। मेट्रिक्स यह जानने का सबसे अच्छा तरीका है कि कौन सा बेहतर है। –

+0

यदि आपको इस तरह की चीजों के बारे में चिंता करने में समय और प्रयास करना है, तो आप तेजी से कंप्यूटर खरीदकर पैसे बचा सकते हैं। –

उत्तर

26
for (int i=0;i<strlen(x);i++) 

यह कोड strlen(x) प्रत्येक पुनरावृत्ति को कॉल कर रहा है। तो यदि x लंबाई 100 है, strlen(x) को 100 बार कहा जाएगा। यह बहुत महंगा है। इसके अलावा, strlen(x) हर बार लूप के लिए x से भी अधिक बार फिर से चल रहा है। यह ओ (एन^2) जटिलता बनाता है।

for (int i=0;x[i]!='\0';i++) 

यह कोड कोई कार्य नहीं करता है, इसलिए पिछले उदाहरण की तुलना में बहुत तेज़ होगा। चूंकि यह केवल एक बार लूप के माध्यम से पुनरावृत्ति करता है, यह ओ (एन) जटिलता है।

+0

हालांकि उत्तर में कुछ भी गलत नहीं है, फिर भी दो संस्करणों की तुलना में कोई बिंदु नहीं है क्योंकि वे एक ही एल्गोरिदम के दो अलग-अलग संस्करण नहीं हैं। वे अलग-अलग चीजें कर रहे दो नमूना कोड हैं –

+0

वे दोनों स्ट्रिंग में प्रत्येक वर्ण के लिए 1 'i' जोड़ते हैं। इसके अलावा यह बताने में थोड़ा मुश्किल है, क्योंकि लूप के अंदर कोड प्रदान नहीं किया गया है। – MatthewD

+0

+ 1 यह इंगित करने के लिए कि प्रत्येक बार फोर-लूप निष्पादित किया जाता है, जब हर बार एक ही मूल्य लौटाता है तो 'strlen() 'कहा जा रहा है। – kiamlaluno

11

मैं के हर चरण में एक्स के पहले कोड की जाँच करता लंबाई और यह हे (एन) पिछले 0 को खोजने के लिए ले जाता है, तो यह O (n^2) लेता है, दूसरे मामले हे है (एन)

+0

इसलिए लोग खुशी से मतदान कर रहे हैं क्योंकि हे (एन^2)> ओ (एन)? ;) –

+0

@ ग्रेगरी पाकोज़ कृपया उन्हें मेरी मदद करें क्योंकि मुझे उनके बीच अच्छा अंतर नहीं पता है, इसलिए इतना गुस्से में क्यों? मुझे खुशी है क्योंकि वे –

+0

को अपवित्र करने की वजह से मेरी मदद नहीं करते हैं, मैं आपको गुस्सा नहीं कर रहा हूं, मैं आपको महसूस कर रहा हूं आपका प्रश्न वास्तविक सवाल नहीं है और इसलिए यह "असली जवाब" नहीं है, हालांकि @Artyom ने –

2

मुझे लगता है कि पहले संस्करण में आप प्रत्येक पुनरावृत्ति को स्ट्रेल करते हैं, जबकि दूसरे संस्करण में आप ऐसा नहीं करते हैं। कोई संकलन अनुकूलन होती है, तो कोई

int a = strlen(x); 
for (int i = 0; i < a; i++) {...} 
2

:
इस जांच करने के लिए प्रयास करें। हां क्योंकि स्ट्रेल हर बार स्ट्रिंग के प्रत्येक बाइट पर फिर से चालू होगा और दूसरा कार्यान्वयन केवल एक बार करेगा।

2

मुझे लगता है कि संकलक अनुकूलन (चेक ग्रेगरी Pakosz टिप्पणी) कर सकता है पाश के लिए अपना पहला तो यह है कि आप इस तरह होगा:

int len = strlen(x); 
for (int i = 0; i < len; i++) 

अब भी है कौन सा O(n)

वैसे भी, मुझे लगता है कि आपका दूसरा for लूप तेज होगा।

+0

हां, लेकिन 2 * ओ (एन), जबकि दूसरा 1 * ओ (एन) है। – falstro

+3

कंपाइलर लूप से स्ट्रेल() कॉल को स्थानांतरित नहीं कर सकता है जब तक कि यह नहीं जानता कि स्ट्रेल() का कोई दुष्प्रभाव नहीं है और स्ट्रिंग की लंबाई लूप के अंदर नहीं बदल सकती है। – JeremyP

+2

वास्तव में जीसीसी लूप के बाहर 'strlen' को अनुकूलित कर सकता है क्योंकि इसे अंतर्निहित फ़ंक्शन के रूप में पहचाना जाता है, http://ridiculousfish.com/blog/archives/2010/07/23/will-it-optimize/ –

0

बेशक पहला व्यक्ति दूसरे से अधिक समय लेगा। वे वास्तव में वही काम नहीं करते हैं - पहला व्यक्ति प्रत्येक बार स्ट्रिंग की लंबाई की गणना कर रहा है; दूसरा एक (प्रभावशाली) केवल एक बार कर रहा है।

पहले संस्करण इस के बराबर है: "यह एक पुस्तकालय strlen() अपने ही लागू करने के लिए की तुलना में कॉल करने के लिए कुशल है"

for (int i=0; x[i] != 0; i++) 
    for (int j=0; j<i; j++) 
    ; 

हो सकता है कि आप कहते हैं कि करने के लिए होती इसका उत्तर, ज़ाहिर है, "यह निर्भर करता है"। आपके कंपाइलर में स्ट्रेल() के आंतरिक संस्करण हो सकते हैं जो आप स्रोत से अपेक्षा करते हैं, आप प्लेटफॉर्म पर हो सकते हैं, जिस पर फ़ंक्शन कॉल महंगे हैं (दुर्लभ आजकल) आदि

एकमात्र उत्तर जो दोनों सामान्य है और सही "प्रोफ़ाइल और पता लगाना" है।

4

हां आपका दूसरा समय 100% प्रतिशत काम नहीं कर सकता है लेकिन यह काफी मामूली होगा। ऐसा इसलिए है क्योंकि strlen() का उपयोग करते समय आपको हर बार विधि को कॉल करना होगा। एक बेहतर तरीका

int strLength = strlen(x); 
for (int i = 0; i < strLength; i++) 

उम्मीद है कि इससे मदद मिलती है।

+1

आकर्षक। आपके मन में क्या परिदृश्य है जिसमें दूसरा संस्करण काम नहीं करता है लेकिन पहला करता है? (Elided loop सामग्रियों को मानते हुए 'i' या स्ट्रिंग का कोई और संशोधन नहीं है।) –

+2

@john, यदि लूप का शरीर स्ट्रिंग की लंबाई बदलता है ...उदाहरण के लिए – mb14

+0

स्ट्रिंग "दुनिया सर्वोत्तम है" के बारे में क्या है? –

0

यह ध्यान देने योग्य है कि आप ओवरफ्लो समस्याओं को बफर करने के लिए स्वयं को खोल सकते हैं यदि आप स्ट्रिंग वाले बफर के आकार के विरुद्ध इंडेक्स का परीक्षण भी नहीं करते हैं। इस कोड के साथ आप जो कर रहे हैं उसके आधार पर, यह एक व्यावहारिक मुद्दा हो सकता है या नहीं भी हो सकता है, लेकिन इसमें शायद ही कभी अतिरिक्त चेक होने के लिए दर्द होता है, और इसमें प्रवेश करने की अच्छी आदत है। के लिए (; मैं buf_size < & & एक्स [मैं] = '\ 0'; मैं = 0 i ++)

कहाँ:

मेरा सुझाव था

  • buf_size पूर्व निर्धारित है बफर का आकार। यदि x एक सरणी है, तो यह sizeof(x) होगा; यदि x एक सूचक है, तो आपके पास बफर आकार उपलब्ध होना चाहिए।
  • मैंने लूप से i की घोषणा को हटा दिया है क्योंकि यह केवल वैध सी 99 है। यदि आप केवल सी 99 के तहत संकलित हैं, तो इसे वापस रखने में संकोच न करें।
संबंधित मुद्दे