सवाल कैसे जांचें कि स्ट्रिंग सी में किसी अन्य स्ट्रिंग के साथ शुरू होती है या नहीं?


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

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

उदाहरण:

"abc", "abcdef" -> true
"abcdef", "abc" -> false
"abd", "abdcef" -> true
"abc", "abc"    -> true

59
2018-01-22 22:15


मूल


मुझे लगता है कि आपके तीसरे उदाहरण का सही परिणाम होना चाहिए। - Michael Burr
@ बूर: हाँ, ठीक है। - thejh


जवाब:


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

bool startsWith(const char *pre, const char *str)
{
    size_t lenpre = strlen(pre),
           lenstr = strlen(str);
    return lenstr < lenpre ? false : strncmp(pre, str, lenpre) == 0;
}

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


55
2018-01-22 22:17



मुझे इसका जिक्र करना चाहिए सामान्य स्ट्रिंग के लिए पहली पैरामीटर होने के लिए चीज होगी, और दूसरा होने के लिए उपसर्ग होगा। लेकिन मैंने उन्हें उपर्युक्त रखा क्योंकि ऐसा लगता था कि आपका प्रश्न कैसे तैयार किया गया था ... आदेश पूरी तरह से आपके ऊपर है, लेकिन मुझे वास्तव में इसे अन्य तरीके से करना चाहिए था - अधिकांश स्ट्रिंग फ़ंक्शंस पूर्ण स्ट्रिंग लेते हैं पहला तर्क, दूसरे के रूप में सबस्ट्रिंग। - T.J. Crowder
यह एक सुरुचिपूर्ण समाधान है, लेकिन इसमें कुछ प्रदर्शन समस्याएं हैं। एक अनुकूलित कार्यान्वयन कभी भी प्रत्येक स्ट्रिंग से न्यूनतम (स्ट्रेल (प्री), स्ट्रेल (स्ट्र)) वर्णों से अधिक नहीं देखेगा, न ही यह पहले मेल के पीछे कभी भी दिखता है। यदि तार लंबे थे, लेकिन शुरुआती विसंगतियां आम थीं, तो यह बहुत हल्का होगा। लेकिन चूंकि यह कार्यान्वयन दोनों स्ट्रिंग्स की पूरी लंबाई को सामने ले जाता है, इसलिए यह सबसे खराब-केस प्रदर्शन को मजबूर करता है, भले ही स्ट्रिंग्स पहले अक्षर में भिन्न हों। चाहे यह मायने रखता है वास्तव में परिस्थितियों पर निर्भर करता है, लेकिन यह एक संभावित समस्या है। - Tom Karzes
@ टॉमकर्ज़: बिलकुल, मैं उन भाषाओं / वातावरण से खराब हो गया हूं जहां स्ट्रिंग लम्बाई एक ज्ञात मान है, जिसे हमें समझना है। :-) wj32 का समाधान बहुत बेहतर प्रदर्शन प्रदान करता है। केवल (बहुत) बड़े तारों या तंग लूप के लिए महत्वपूर्ण है, लेकिन जब यह महत्वपूर्ण है, तो यह महत्वपूर्ण है। - T.J. Crowder


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

bool prefix(const char *pre, const char *str)
{
    return strncmp(pre, str, strlen(pre)) == 0;
}

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

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


107
2018-01-22 23:45



जवाब नहीं है क्यों? जाहिर है, जवाब हाँ है, इसे कहा जाता है strncmp। - Jasper


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

_Bool starts_with(const char *restrict string, const char *restrict prefix)
{
    while(*prefix)
    {
        if(*prefix++ != *string++)
            return 0;
    }

    return 1;
}

23
2018-01-22 22:30



मुझे यह सबसे अच्छा लगता है - लंबाई के लिए तारों में से किसी एक को स्कैन करने का कोई कारण नहीं है। - Michael Burr
मैं शायद strlen + strncmp के साथ भी जाऊंगा, लेकिन वास्तव में यह वास्तव में काम करता है, लेकिन इसकी अस्पष्ट परिभाषा पर सभी विवाद मुझे दूर कर रहा है। तो मैं इसका इस्तेमाल करूंगा, धन्यवाद। - Sam Watkins
यह धीमा होने की संभावना है strncmp, जब तक आपका कंपाइलर वेक्टरनाइज़ेशन में वास्तव में अच्छा न हो, क्योंकि ग्लिब लेखकों को यकीन है कि :-) - Ciro Santilli 新疆改造中心 六四事件 法轮功
यदि उपसर्ग मेल नहीं खाता है, तो विशेष रूप से पहले कुछ वर्णों में अंतर होने पर यह संस्करण strlen + strncmp संस्करण से तेज़ होना चाहिए। - dpi


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

int prefix(const char *pre, const char *str)
{
    char cp;
    char cs;

    if (!*pre)
        return 1;

    while ((cp = *pre++) && (cs = *str++))
    {
        if (cp != cs)
            return 0;
    }

    if (!cs)
        return 0;

    return 1;
}

5
2018-01-22 22:30





उपयोग strstr() समारोह। Stra == strstr(stra, strb)


4
2017-10-26 01:13



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


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

bool longEnough(const char *str, int min_length) {
    int length = 0;
    while (str[length] && length < min_length)
        length++;
    if (length == min_length)
        return true;
    return false;
}

bool startsWith(const char *pre, const char *str) {
    size_t lenpre = strlen(pre);
    return longEnough(str, lenpre) ? strncmp(str, pre, lenpre) == 0 : false;
}

1
2017-11-05 00:58





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

uint32 startsWith( const void* prefix_, const void* str_ ) {
    uint8 _cp, _cs;
    const uint8* _pr = (uint8*) prefix_;
    const uint8* _str = (uint8*) str_;
    while ( ( _cs = *_str++ ) & ( _cp = *_pr++ ) ) {
        if ( _cp != _cs ) return 0;
    }
    return !_cp;
}

1
2018-02-08 10:50



मतदान नकारात्मक: startsWith("\2", "\1") 1 लौटाता है, startsWith("\1", "\1") 1 भी देता है - thejh
आप सही हे। एक गलत रेखा थी। - Zloten
अब अच्छा लग रहा है! :) - thejh
यह निर्णय क्लैंग में अनुकूलन का उपयोग नहीं करेगा, क्योंकि instrisincs का उपयोग नहीं करते हैं। - socketpair


अनुकूलित:

boolean StartsWith(char *s1, char *s2)
{
  while (*s1++ == *s2++)
  {
  }

  return *s2 == 0;
}

-5



क्या आप ने कोशिश की StartsWith("", "")? - Neil