मैं तार की तुलना ठीक से कैसे करूं?


182

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

#include <stdio.h>

int main()
{
    char input[40];
    char check[40];
    int i=0;
    printf("Hello!\nPlease enter a word or character:\n");
    gets(input);
    printf("I will now repeat this until you type it back to me.\n");

    while (check != input)
    {
        printf("%s\n", input);
        gets(check); 
    }

    printf("Good bye!");


    return 0;
}

समस्या यह है कि मैं इनपुट स्ट्रिंग का मुद्रण प्राप्त करता रहता हूं, तब भी जब उपयोगकर्ता द्वारा इनपुट (चेक) मूल (इनपुट) से मेल खाता है। क्या मैं दोनों की तुलना गलत तरीके से कर रहा हूं?


13
gets( )मानक से हटा दिया गया था। fgets( )इसके बजाय उपयोग करें ।
एडवर्ड करक

1
ध्यान दें कि यह जवाब के लिए क्यों करता strcmp()वापसी शून्य जब इसकी जानकारी के बराबर हैं समानता, असमानता, कम से कम, की तुलना में अधिक के लिए तार तुलना करने के लिए कम से कम या बराबर बताते हैं, और बराबर या अधिक से अधिक। सभी स्ट्रिंग तुलना समानता के लिए नहीं हैं। केस संवेदनशील तुलना फिर से अलग हैं; अन्य विशेष तुलना (डिक्शनरी ऑर्डर, उदाहरण के लिए) को अधिक विशिष्ट तुलनाकर्ताओं की आवश्यकता होती है, और अभी भी अधिक जटिल तुलनाओं के लिए अवशेष हैं।
जोनाथन लेफ्लर

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


यह सवाल अच्छा है, लेकिन इसका उपयोग gets()न के बराबर है। यह C11 के बाद से मानक से भी हटा दिया गया है -> कृपया पढ़ें कि क्यों हो जाता है फ़ंक्शन इतना खतरनाक है कि इसका उपयोग नहीं किया जाना चाहिए?
रॉबर्ट्स

जवाबों:


274

आप (उपयोगी रूप से) तार का उपयोग करके तुलना नहीं कर सकते , !=या ==आपको उपयोग करने की आवश्यकता है strcmp:

while (strcmp(check,input) != 0)

इसका कारण यह है क्योंकि !=और ==केवल उन तार के आधार पते की तुलना करेंगे। स्वयं तार की सामग्री नहीं।


10
जावा में समान, जो केवल पते के साथ तुलना कर सकता है।
तेलिक

29
लेखन while (strcmp(check, input))पर्याप्त है और अच्छा अभ्यास माना जाता है।
शिव

आगे
जानिए

7
यह strncmp का उपयोग करने के लिए सुरक्षित है! एक बफर अतिप्रवाह नहीं चाहिए!
तैलव

@ फ्लोम यदि आपके पास वास्तव में तार नहीं हैं, लेकिन ज्ञात लंबाई के गैर-शून्य वर्णों के शून्य-गद्देदार अनुक्रम, निश्चित रूप से, यह सही झुकाव होगा। लेकिन यह पूरी तरह से अलग है!
Deduplicator

33

ठीक है कुछ चीजें: getsअसुरक्षित है और इसे इस तरह बदला जाना चाहिए fgets(input, sizeof(input), stdin)कि आपको बफर अतिप्रवाह न मिले।

अगला, स्ट्रिंग्स की तुलना करने के लिए, आपको उपयोग करना होगा strcmp, जहां 0 का रिटर्न मान इंगित करता है कि दो स्ट्रिंग्स का मिलान होता है। समानता ऑपरेटरों (यानी। !=) का उपयोग दो तारों के पते की तुलना करता है, जैसा कि charउनके अंदर व्यक्तिगत एस के विपरीत है ।

और यह भी ध्यान दें, जबकि इस उदाहरण में यह समस्या का कारण नहीं होगा, बफ़र में भी fgetsनए वर्ण को संग्रहीत करता है '\n'; gets()नहीं करता। यदि आप उपयोगकर्ता इनपुट की तुलना fgets()एक स्ट्रिंग शाब्दिक से करते हैं जैसे कि "abc"यह कभी भी मेल नहीं खाएगा (जब तक कि बफर बहुत छोटा था ताकि उसमें '\n'फिट न हो)।


क्या आप कृपया "\ n" और स्ट्रिंग शाब्दिक के संबंध / समस्या को स्पष्ट कर सकते हैं? मुझे एक फ़ाइल के तार (लाइन) की तुलना अन्य संपूर्ण फ़ाइल के साथ करने में समान परिणाम नहीं मिल रहा है।
अक्षम्य

@incompetent - यदि आप किसी फ़ाइल के साथ एक लाइन पढ़ते हैं fgets(), तो स्ट्रिंग हो सकती है "abc\n"क्योंकि fgets()नई लाइन रहती है। यदि आप इसके साथ तुलना करते हैं "abc", तो आपको एक शून्य बाइट समाप्त होने "abc"और रीड डेटा में नई रेखा के बीच अंतर के कारण 'बराबर नहीं' मिलेगा । तो, आपको newline को zap करना होगा। ऐसा करने के लिए विश्वसनीय एक-लाइन तरीका है, buffer[strcspn(buffer, "\n")] = '\0';जिसमें बफर में कोई भी डेटा है या चाहे वह डेटा एक नई पंक्ति के साथ समाप्त होता है या नहीं, इसकी परवाह किए बिना सही ढंग से काम करने का गुण है। न्यूलाइन को जप करने के अन्य तरीके आसानी से क्रैश हो जाते हैं।
जोनाथन लेफ़लर

यह उत्तर कोड के मुद्दों को सटीक रूप से संबोधित करता है, जबकि सबसे ऊपर और स्वीकृत उत्तर केवल प्रश्न के शीर्षक का उत्तर देने के लिए है। विशेष रूप से अंतिम पैराग्राफ का उल्लेख करना सुपर है। +1
रॉबर्ट्स

11

का उपयोग करें strcmp

यह string.hलाइब्रेरी में है, और बहुत लोकप्रिय है। strcmpवापसी 0 अगर तार बराबर हैं। क्या रिटर्न की बेहतर व्याख्या के लिए इसे देखें strcmp

मूल रूप से, आपको करना होगा:

while (strcmp(check,input) != 0)

या

while (!strcmp(check,input))

या

while (strcmp(check,input))

आप इस पर एक ट्यूटोरियल देख सकते हैं strcmp


7

आप इस तरह से सीधे सरणियों की तुलना नहीं कर सकते

array1==array2

आपको उनकी तुलना चार-चार-चार से करनी चाहिए; इसके लिए आप एक फ़ंक्शन का उपयोग कर सकते हैं और एक बूलियन वापस कर सकते हैं (सही: 1, गलत: 0) मान। तब आप इसे लूप की परीक्षण स्थिति में उपयोग कर सकते हैं।

इसे इस्तेमाल करे:

#include <stdio.h>
int checker(char input[],char check[]);
int main()
{
    char input[40];
    char check[40];
    int i=0;
    printf("Hello!\nPlease enter a word or character:\n");
    scanf("%s",input);
    printf("I will now repeat this until you type it back to me.\n");
    scanf("%s",check);

    while (!checker(input,check))
    {
        printf("%s\n", input);
        scanf("%s",check);
    }

    printf("Good bye!");

    return 0;
}

int checker(char input[],char check[])
{
    int i,result=1;
    for(i=0; input[i]!='\0' || check[i]!='\0'; i++) {
        if(input[i] != check[i]) {
            result=0;
            break;
        }
    }
    return result;
}

1
क्या आप अपने समाधान के बारे में अधिक जानकारी जोड़ सकते हैं?
अबरिसन

हाँ इस strcmp समारोह और solition के लिए प्रतिस्थापन string.h हैडर @Jongware का उपयोग किए बिना है
mugetsu

2
यह काम नहीं करता। जब एक तार में checkerपाया '\0'जाता है, तो यह दूसरे स्ट्रिंग की जांच नहीं करता है '\0'। फ़ंक्शन लौटता है 1("बराबर") भले ही एक स्ट्रिंग दूसरे के उपसर्ग (उदाहरण के लिए, "foo"और "foobar") हो।
लुकासरोज

1
के ||बदले मैं उपयोग करूंगा &&
लुकासरोज़

3

सूचक की अवधारणा में आपका स्वागत है शुरुआत के प्रोग्रामर की पीढ़ियों ने अवधारणा को मायावी पाया है, लेकिन यदि आप एक सक्षम प्रोग्रामर के रूप में विकसित होना चाहते हैं, तो आपको अंततः इस अवधारणा को पूरा करना होगा - और इसके अलावा, आप पहले से ही सही सवाल पूछ रहे हैं। अच्छी बात है।

क्या यह आपके लिए स्पष्ट है कि पता क्या है? इस आरेख को देखें:

----------     ----------
| 0x4000 |     | 0x4004 |
|    1   |     |    7   |
----------     ----------

चित्र में, पूर्णांक 1 को मेमोरी में 0x4000 पते पर संग्रहीत किया जाता है । एक पते पर क्यों? क्योंकि स्मृति बड़ी है और कई पूर्णांकों को संग्रहीत कर सकती है, जैसे कि एक शहर बड़ा है और कई परिवारों को घर दे सकता है। प्रत्येक पूर्णांक मेमोरी स्थान पर संग्रहीत किया जाता है, क्योंकि प्रत्येक परिवार एक घर में रहता है। प्रत्येक मेमोरी स्थान की पहचान एक पते से होती है , क्योंकि प्रत्येक घर की पहचान एक पते से होती है।

आरेख में दो बक्से दो अलग-अलग मेमोरी स्थानों का प्रतिनिधित्व करते हैं। आप उनके बारे में सोच सकते हैं जैसे कि वे घर थे। पूर्णांक 1 पता 0x4000 के मेमोरी स्थान पर रहता है (विचार करें, "4000 एल्म सेंट")। पूर्णांक 7 पता 0x4004 पर मेमोरी स्थान में रहता है (सोचें, "4004 एल्म सेंट")।

आपने सोचा था कि आपका कार्यक्रम 1 से 7 की तुलना कर रहा था, लेकिन यह नहीं था। यह 0x4000 की तुलना 0x4004 से कर रहा था। तो क्या होता है जब आपके पास यह स्थिति होती है?

----------     ----------
| 0x4000 |     | 0x4004 |
|    1   |     |    1   |
----------     ----------

दो पूर्णांक समान हैं, लेकिन पते भिन्न हैं। आपका प्रोग्राम पतों की तुलना करता है।


2

जब भी आप स्ट्रिंग्स की तुलना करने की कोशिश कर रहे हैं, तो उनकी तुलना प्रत्येक चरित्र से करें। इसके लिए आप स्ट्रिंग फ़ंक्शन (इनपुट 1, इनपुट 2) नामक स्ट्रिंग फ़ंक्शन में उपयोग कर सकते हैं; और आपको हेडर फ़ाइल का उपयोग करना चाहिए जिसे कहा जाता है#include<string.h>

इस कोड को आज़माएं:

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h>  

int main() 
{ 
    char s[]="STACKOVERFLOW";
    char s1[200];
    printf("Enter the string to be checked\n");//enter the input string
    scanf("%s",s1);
    if(strcmp(s,s1)==0)//compare both the strings  
    {
        printf("Both the Strings match\n"); 
    } 
    else
    {
        printf("Entered String does not match\n");  
    } 
    system("pause");  
} 

0

मैं तार की तुलना ठीक से कैसे करूं?

char input[40];
char check[40];
strcpy(input, "Hello"); // input assigned somehow
strcpy(check, "Hello"); // check assigned somehow

// insufficient
while (check != input)

// good
while (strcmp(check, input) != 0)
// or 
while (strcmp(check, input))

आइए हम यह देखने के लिए गहराई से खुदाई करें कि check != inputपर्याप्त क्यों नहीं है

सी में, स्ट्रिंग एक मानक पुस्तकालय विनिर्देश है।

एक स्ट्रिंग वर्णों का एक सन्निहित अनुक्रम है, जिसमें पहले अशक्त चरित्र को शामिल किया गया है।
C11 .17.1.1 1

inputऊपर एक तार नहीं है । inputहै चार की सरणी 40

की सामग्री inputएक स्ट्रिंग बन सकती है ।

ज्यादातर मामलों में, जब एक एक्सप्रेशन का उपयोग किसी एक्सप्रेशन में किया जाता है, तो इसे उसके 1 एलिमेंट के एड्रेस में बदल दिया जाता है।

धर्मान्तरित नीचे checkऔर inputपहला तत्व की उनके संबंधित पते पर है, तो उन पतों की तुलना में कर रहे हैं।

check != input   // Compare addresses, not the contents of what addresses reference

स्ट्रिंग्स की तुलना करने के लिए , हमें उन पतों का उपयोग करने की आवश्यकता है और फिर उनके द्वारा इंगित किए गए डेटा को देखें।
strcmp()काम करता है । §7.23.4.2

int strcmp(const char *s1, const char *s2);

strcmpसमारोह से स्ट्रिंग की ओर इशारा किया तुलना s1करने के लिए स्ट्रिंग द्वारा की ओर इशारा किया s2

strcmpसमारोह रिटर्न की तुलना में एक पूर्णांक अधिक से अधिक, के बराबर, या शून्य से भी कम समय, तदनुसार के रूप में स्ट्रिंग द्वारा की ओर इशारा किया s1बड़ा है के बराबर, या कम से कम स्ट्रिंग द्वारा इंगित किए गए से s2

न केवल कोड पा सकते हैं कि क्या तार एक ही डेटा के हैं, लेकिन जब वे भिन्न होते हैं तो कम / अधिक होता है।

स्ट्रिंग भिन्न होने पर नीचे सच है।

strcmp(check, input) != 0

अंतर्दृष्टि के लिए, अपना स्वयं का फ़ंक्शन बनाना देखेंstrcmp()


-2
    #include<stdio.h>
    #include<string.h>
    int main()
    {
        char s1[50],s2[50];
        printf("Enter the character of strings: ");
        gets(s1);
        printf("\nEnter different character of string to repeat: \n");
        while(strcmp(s1,s2))
        {
            printf("%s\n",s1);
            gets(s2);
        }
        return 0;
    }

यह बहुत ही सरल उपाय है जिसमें आप अपना आउटपुट प्राप्त करेंगे जैसा आप चाहते हैं।


2
gets();C11 के बाद से मानक C का हिस्सा नहीं है।
chux -

2
strcmp(s1,s2)UB s2पहली सामग्री के रूप में निर्दिष्ट नहीं है।
chux -

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