fgets

2010-03-08 12 views
6

के साथ पढ़ने वाली रेखा पर strcmp मैं दो तारों की तुलना करने की कोशिश कर रहा हूं। एक फ़ाइल में संग्रहीत, दूसरा उपयोगकर्ता (stdin) से पुनर्प्राप्त।fgets

यहां एक नमूना कार्यक्रम है:

int main() 
{ 
    char targetName[50]; 
    fgets(targetName,50,stdin); 

    char aName[] = "bob"; 
    printf("%d",strcmp(aName,targetName)); 

    return 0; 
} 

इस कार्यक्रम में, strcmp -1 मान लौटाता है जब इनपुट "bob" है। यह क्यों है? मैंने सोचा कि वे बराबर होना चाहिए। मैं इसे कैसे प्राप्त कर सकता हूं ताकि वे हैं?

+0

आपको 'strcmp' का उपयोग करने से बचना चाहिए। इसके बजाए 'strncmp' का प्रयोग करें, खासकर यदि आप निश्चित-चौड़ाई वाली स्ट्रिंग के विरुद्ध तुलना कर रहे हैं। 'Strncmp (aName, targetName, strlen (aName)) का उपयोग करना आपके लिए यहां काम करना चाहिए। – bta

+0

बीटीए की टिप्पणी सिर्फ गलत है - अगर आप पूरी स्ट्रिंग के बजाय उपसर्ग के खिलाफ जांचना चाहते हैं तो strncmp का उपयोग करें, उदाहरण के लिए। "बॉबकैट" भी मेल खाएगा। –

+0

मैंने कहा कि क्योंकि 'strcmp' एक पूर्ण टर्मिनेटर तक पहुंचने तक या स्ट्रिंग अलग होने तक तुलना करना जारी रखेगा। यदि आप निश्चित नहीं हो सकते हैं कि आपके तार हमेशा ठीक से समाप्त हो जाएंगे, तो 'strcmp' बफर ओवरफ़्लो और मेमोरी एक्सेस उल्लंघनों को पेश कर सकता है। 'strncmp' सिर्फ उपसर्ग पढ़ने के लिए नहीं है; यह सुनिश्चित करने के लिए कि आप अपनी सरणी सीमाओं को बहती नहीं हैं, अपने निश्चित-लंबाई बफर के आकार में अंतिम पैरामीटर सेट करें। – bta

उत्तर

8

strcmp कुछ कार्य करता है कि सही और गलत के विपरीत परिणामों में से एक

है ... अगर तार बराबर हैं, परिणाम 0 है, नहीं 1 के रूप में आपको लगता है जाएगा ....
if (strcmp(a, b)) { 
    /* Do something here as the strings are not equal */ 
} else { 
    /* Strings are equal */ 
} 

fgets का भाषण, वहाँ एक संभावना एक नई पंक्ति स्ट्रिंग के अंत से जुड़ी है कि वहाँ है ... आप

+-+-+-+--+--+ 
|b|o|b|\n|\0| 
+-+-+-+--+--+ 

छुटकारा ओ प्राप्त करने के लिए यह से छुटकारा पाने की जरूरत है ... एफ नईलाइन यह करते हैं। चेतावनियां: उपयोग न करें "strlen (aName) - 1", क्योंकि एक लाइन fgets द्वारा दिया NUL चरित्र के साथ शुरू कर सकते हैं - इस प्रकार बफर में सूचकांक -1 हो जाता है:

aName[strcspn(aName, "\n")] = '\0'; 

+-+-+-+--+ 
|b|o|b|\0| 
+-+-+-+--+ 

अब, strcmp लौटना चाहिए 0 ...

+0

धन्यवाद, अन्य उत्तरों अच्छे थे, लेकिन आपके पास एक समाधान शामिल था (मैंने सोचा कि समस्या हो सकती है \ n, लेकिन सोचा कि यह कुछ और भी हो सकता है), क्योंकि आप एक समाधान (और एक अच्छी सरणी तस्वीर lol) शामिल हैं, मैं ' हमने तुम्हारा सबसे अच्छा चिन्हित किया है। और हाँ, अब strcmp काम करता है। – Blackbinary

+1

strcmp सही और गलत के परिणामों को उलट नहीं करता है। strcmp एक बूलियन वापस नहीं करता है, यह एक तार को एक दूसरे से संबंधित कैसे करता है इस पर आधारित एक अभिन्न मूल्य देता है। "अगर (strcmp (ए, बी))" काम करता है, लेकिन अभिन्न मूल्यों से निपटने के बाद से इस तथ्य को अस्पष्ट करता है, "अगर" कथन इसे "if (n! = 0)" के रूप में मानता है। यह लिखने का एक और स्पष्ट तरीका होगा "अगर (strcmp (ए, बी)! = 0)" जो स्पष्ट रूप से राज्य का परीक्षण किया जा रहा है। – Torlack

+0

@ टोरलैक: या अगर (! Strcmp (ए, बी)) .... आप जो कहते हैं उसके बावजूद, गैर-शून्य जो कुछ भी सत्य है, और शून्य गलत है इसलिए मेरा जोर ... – t0mm13b

1

क्योंकि fgets वैरिएबल targetName में न्यूलाइन वर्ण को एम्बेड कर रहा है। यह तुलना को फेंक रहा है।

0

fgets स्ट्रिंग में नई लाइन जोड़ता है, तो आप bob\n\0 के साथ समाप्त हो जाएंगे जो bob\0 जैसा नहीं है।

0

अधिकतर सिस्टम जैसे यूनिक्स के तहत इनपुट \ n "में लाइन चार के अंत की वजह से।

5

fgets तब तक पढ़ता है जब तक कि यह एक नई लाइन नहीं देखता है, तो जब आप बॉब टाइप करते हैं, तो कंसोल में targetName में "बॉब \ n" होता है जो "बॉब" से मेल नहीं खाता है। fgets documenation से: (बोल्ड जोड़ा)

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

आपको तुलना करने से पहले आपको लक्ष्य नाम के अंत से नई लाइन को हटाने की आवश्यकता है।

int cch = strlen(targetName); 
if (cch > 1 && targetName[cch-1] == '\n') 
    targetName[cch-1] = '\0'; 

या अपनी परीक्षण स्ट्रिंग में नई लाइन जोड़ें।

char targetName[50]; 
fgets(targetName,50,stdin); 

char aName[] = "bob\n"; 
printf("%d",strcmp(aName,targetName)); 
+0

मैं 'sizeof (targetName) 'का उपयोग करने का सुझाव दूंगा, इसे' fgets()' में हार्डकोड न करें। – mctylr

1

fgets उस स्ट्रिंग में \n जोड़ रहा है जिसे आप एंटर दबाते समय उपयोगकर्ता से खींच रहे हैं।आप strcspn का उपयोग करके या बस अपनी स्ट्रिंग के अंत में \n जोड़कर इसे प्राप्त कर सकते हैं, जिसे आप तुलना करने की कोशिश कर रहे हैं।

printf("Please enter put FILE_NAME (foo1, 2, or 3), ls, or exit: \n"); 
fgets(temp, 8, stdin); 
temp[strcspn(temp, "\n")] = '\0'; 
if(strcmp(temp, "ls") == 0 || strcmp(temp, "exit") == 0) 

यह सिर्फ एक \0 साथ \n बदल देता है, लेकिन अगर आप आलसी होना चाहते हैं तो आप सिर्फ यह कर सकते हैं:

printf("Please enter put FILE_NAME (foo1, 2, or 3), ls, or exit: \n"); 
fgets(temp, 8, stdin); 
if(strcmp(temp, "ls\n") == 0 || strcmp(temp, "exit\n") == 0) 

लेकिन यह रूप में सुंदर नहीं है।

संबंधित मुद्दे