यदि एक स्ट्रिंग C में दूसरे स्ट्रिंग से शुरू होती है तो कैसे जांचें?


85

क्या startsWith(str_a, str_b)मानक सी लाइब्रेरी में कुछ ऐसा है ?

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

उदाहरण:


3
मुझे लगता है कि आपके 3 उदाहरण का सही परिणाम होना चाहिए।
माइकल बूर

जवाबों:


76

जाहिर है इसके लिए कोई मानक C फ़ंक्शन नहीं है। इसलिए:


ध्यान दें कि ऊपर अच्छा और स्पष्ट है, लेकिन यदि आप इसे एक तंग पाश में कर रहे हैं या बहुत बड़े तार के साथ काम कर रहे हैं, तो यह सबसे अच्छा प्रदर्शन प्रदान नहीं करता है, क्योंकि यह दोनों तारों की पूरी लंबाई को सामने ( strlen) में स्कैन करता है । Wj32 या क्रिस्टोफ़ जैसे समाधान बेहतर प्रदर्शन की पेशकश कर सकते हैं (हालांकि वैश्वीकरण के बारे में यह टिप्पणी मेरे सी के केन से परे है)। फ्रेड फू के समाधानstrlen पर भी ध्यान दें जो str(वह सही है, यदि आप strncmpइसके बजाय उपयोग करते हैं तो यह अनावश्यक है memcmp)। केवल (बहुत) बड़े तारों के लिए या तंग छोरों में दोहराया उपयोग के लिए मायने रखता है, लेकिन जब यह मायने रखता है, तो यह मायने रखता है।


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

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

1
@TomKarzes आप यहां के memcmpलिए स्थानापन्न कर सकते strncmpहैं और यह तेज है। कोई यूबी नहीं है क्योंकि दोनों तारों को कम से कम lenpreबाइट्स के लिए जाना जाता है । strncmpएनयूएल के लिए दोनों तारों के प्रत्येक बाइट की जांच करता है, लेकिन strlenकॉल पहले से ही गारंटी देते हैं कि कोई भी नहीं है। (लेकिन यह अभी भी आपके द्वारा बताए गए प्रदर्शन को हिट करता है, जब preया strवास्तविक सामान्य प्रारंभिक अनुक्रम की तुलना में लंबा होता है।)
जिम बाल्टर

1
@JimBalter - बहुत अच्छी बात! चूँकि memcmpऊपर उपयोग करने से यहाँ दूसरे उत्तर से विनियोग नहीं होगा, इसलिए मैंने आगे जाकर उत्तर में इसे बदल दिया।
टीजे क्राउडर

1
PS यह (अब) कुछ तारों के साथ कुछ मशीनों पर सबसे तेज़ उत्तर हो सकता है, क्योंकि strlenऔर memcmpइसे बहुत तेज़ हार्डवेयर निर्देशों के साथ कार्यान्वित किया जा सकता है, और strlens दोहरे कैश की मार से बचने के लिए तार को कैश में डाल सकता है। ऐसी मशीनों पर, strncmpइसे दो strlenएस और एक के रूप में लागू किया जा सकता है memcmp, लेकिन यह एक पुस्तकालय लेखक के लिए ऐसा करना जोखिम भरा होगा, क्योंकि यह छोटे आम ​​उपसर्गों के साथ लंबे समय तक तार पर अधिक समय ले सकता है। यहाँ वह हिट स्पष्ट है, और strlenएस केवल एक बार किया जाता है (फ्रेड फू strlen+ strncmp3 करेगा)।
जिम बाल्टर

160

इसके लिए कोई मानक कार्य नहीं है, लेकिन आप इसे परिभाषित कर सकते हैं

हमें चिंता करने की जरूरत नहीं है strpre सी मानक (7.21.4.4/2) के अनुसार कम होने की :

strncmpसमारोह से अधिक नहीं तुलना nवर्ण (अक्षर हैं जो एक अशक्त चरित्र का पालन तुलना नहीं कर रहे हैं) सरणी से द्वारा की ओर इशारा s1करने के लिए सरणी द्वारा की ओर इशारा किया s2। "


12
जवाब क्यों नहीं है? स्पष्ट रूप से, इसका उत्तर हां है, इसे कहा जाता है strncmp
जैस्पर

7
^ यह स्पष्ट होना चाहिए कि उत्तर क्यों नहीं है। एक एल्गोरिथ्म जो नियोजित करता है strncmpऔर strlenजिसे "strncmp" नहीं कहा जाता है।
जिम बाल्टर

34

मैं शायद साथ जाऊंगा strncmp(), लेकिन सिर्फ एक मज़ेदार कार्यान्वयन के लिए:


6
मुझे यह सबसे अच्छा लगता है - लंबाई के लिए स्ट्रिंग्स को स्कैन करने का कोई कारण नहीं है।
माइकल बूर

1
मैं शायद strlen + strncmp के साथ भी जाऊंगा, लेकिन हालांकि यह वास्तव में काम करता है, लेकिन यह अस्पष्ट परिभाषा के सभी विवाद मुझे दूर कर रहे हैं। तो मैं इसका उपयोग करूंगा, धन्यवाद।
सैम वाटकिंस

4
यह strncmpतब तक धीमा होने की संभावना है , जब तक कि आपका कंपाइलर
वैश्वीकरण

3
यदि उपसर्ग मेल नहीं खाता है, तो यह संस्करण strlen + strncmp संस्करण से अधिक तेज़ होना चाहिए, खासकर यदि पहले से ही पहले वर्णों में अंतर हो।
dpi

1
^ वह फंक्शन ऑप्ट इनलाइन होने पर ही लागू होगा।
जिम बैटर

5

मैं सुरुचिपूर्ण कोड लिखने में कोई विशेषज्ञ नहीं हूं, लेकिन ...


5

strstr()फ़ंक्शन का उपयोग करें । Stra == strstr(stra, strb)


3
ऐसा लगता है कि कुछ हद तक यह करने का तरीका है - आप पूरे स्ट्रैप से गुजरेंगे, भले ही यह बहुत ही कम शुरुआती सेगमेंट से स्पष्ट हो, अगर स्ट्रोब कोई उपसर्ग है या नहीं।
स्टैसम

1
सभी बुराईयो की जड़ समयपूर्व इष्टतमीकरण है। मुझे लगता है कि यह सबसे अच्छा समाधान है, अगर यह समय महत्वपूर्ण कोड या लंबा तार नहीं है।
फ्रैंक बुस

1
@ilw यह प्रसिद्ध कंप्यूटर वैज्ञानिकों द्वारा एक प्रसिद्ध कहावत है - इसे Google। यह अक्सर गलत होता है (जैसा कि यहाँ है) ... joshbarczak.com/blog/?p=580
जिम

2

अनुकूलित (v.2 - सही किया गया):


2
मतदान नकारात्मक: startsWith("\2", "\1")1 रिटर्न, 1 startsWith("\1", "\1")भी लौटाता है
thejh

यह निर्णय क्लैंग में अनुकूलन का उपयोग नहीं करेगा, क्योंकि इंस्ट्रिंस का उपयोग नहीं करते हैं।
सॉकेटपेयर

^ आंतरिक यहां मदद नहीं करते हैं, खासकर अगर लक्ष्य स्ट्रिंग उपसर्ग की तुलना में अधिक लंबा है।
जिम बाल्टर

1

क्योंकि मुझे स्वीकृत संस्करण भागा था और बहुत लंबे समय से समस्या थी, इसलिए मुझे निम्नलिखित तर्क में जोड़ना पड़ा:


1

या दो दृष्टिकोणों का एक संयोजन:

EDIT: नीचे दिया गया कोड काम नहीं करता है क्योंकि यदि strncmp 0 देता है तो यह ज्ञात नहीं होता है कि एक समाप्ति 0 या लंबाई (block_size) तक पहुँच गई थी या नहीं।

एक अतिरिक्त विचार ब्लॉक-वार की तुलना करना है। यदि ब्लॉक समान नहीं है तो मूल फ़ंक्शन के साथ उस ब्लॉक की तुलना करें:

स्थिरांक 13, 64, 4096, साथ ही की घातांक block_sizeसिर्फ अनुमान है। इसे इस्तेमाल किए गए इनपुट डेटा और हार्डवेयर के लिए चुनना होगा।


ये अच्छे विचार हैं। ध्यान दें कि पहले वाला तकनीकी रूप से अपरिभाषित व्यवहार है यदि उपसर्ग 12 बाइट्स (NUL सहित 13) से छोटा है क्योंकि भाषा मानक तुरंत बाइट के अलावा अन्य स्ट्रिंग के बाहर एक पते की गणना के परिणाम को परिभाषित नहीं करता है।
जिम बाल्टर

@JimBalter: क्या आप एक संदर्भ जोड़ सकते हैं? यदि पॉइंटर को डिफाइन किया गया है और 0 समाप्त होने के बाद है तो डिफरेंशियल पॉइंटर वैल्यू अपरिभाषित है। लेकिन पता खुद को अपरिभाषित क्यों होना चाहिए? यह सिर्फ एक गणना है।
shpc

हालांकि एक सामान्य बग था: block_sizeसूचक वृद्धि के बाद वेतन वृद्धि होनी चाहिए। अब तय हो गया।
shpc
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.