मैं का उपयोग करना चाहिए fgets या scanf के साथ सीमित इनपुट में सी है?

0

सवाल

मैं का उपयोग करना चाहिए fgets या स्वरूपित scanf की तरह scanf("%10s", foo).

Excepted है कि scanf पढ़ा नहीं है रिक्त वर्ण है, जो हल किया जा सकता है और अधिक सामान के साथ scanset, तो मैं क्यों इस्तेमाल करना चाहिए fgets के बजाय scanf?

किसी भी मदद की सराहना की जाएगी.


संपादित करें

एक और बात मैं पूछना चाहता हूँ है: यहां तक कि जब हम का उपयोग करें fgets क्या होगा यदि उपयोगकर्ता अक्षर दर्ज करें और अधिक से अधिक सीमा (मैं एक बहुत मतलब है के अक्षर) है, यह नेतृत्व करने के लिए बफर अतिप्रवाह? तो फिर कैसे इसे से निपटने के लिए?

c fgets input scanf
2021-11-23 13:53:00
4

सबसे अच्छा जवाब

5

पर सबसे ऑपरेटिंग sytems, उपयोगकर्ता इनपुट है, डिफ़ॉल्ट रूप से, लाइन पर आधारित है । एक इस के लिए कारण है करने के लिए उपयोगकर्ता की अनुमति दें करने के लिए प्रेस बैकस्पेस कुंजी सही करने के लिए इनपुट भेजने से पहले, इनपुट के लिए कार्यक्रम.

के लिए लाइन-आधारित उपयोगकर्ता इनपुट, यह सार्थक और सहज ज्ञान युक्त के लिए एक कार्यक्रम को पढ़ने के लिए एक लाइन के साथ इनपुट एक समय में. यह है क्या समारोह fgets करता है (बशर्ते कि बफर करने के लिए काफी बड़ी दुकान की पूरी लाइन इनपुट).

समारोह scanf, दूसरे हाथ पर, आम तौर पर पढ़ा नहीं है एक लाइन इनपुट के एक समय में. उदाहरण के लिए, जब आप का उपयोग %s या %d रूपांतरण प्रारूप विनिर्देशक के साथ scanf, यह उपभोग नहीं होगा की एक पूरी लाइन इनपुट । इसके बजाय, यह केवल उपभोग के रूप में ज्यादा के रूप में इनपुट मैचों के प्रारूप रूपांतरण विनिर्देशक. इसका मतलब यह है कि newline चरित्र के अंत में लाइन पर होगा आम तौर पर सेवन नहीं किया (जो कर सकते हैं आसानी से नेतृत्व करने के लिए कीड़े प्रोग्रामिंग). इसके अलावा, scanf कहा जाता है के साथ %d रूपांतरण प्रारूप विनिर्देशक पर विचार करेंगे के रूप में इनपुट 6sldf23dsfh2 के रूप में मान्य इनपुट संख्या के लिए 6है , लेकिन किसी भी आगे कॉल करने के लिए scanf साथ ही विनिर्देशक विफल हो जाएगा, जब तक आप त्यागने के शेष से लाइन इनपुट स्ट्रीम ।

इस व्यवहार के scanf काउंटर सहज ज्ञान युक्त है, जबकि व्यवहार के fgets सहज ज्ञान युक्त है, के साथ काम कर जब रेखा-आधारित उपयोगकर्ता इनपुट.

का उपयोग करने के बाद fgets, आप कर सकते हैं इस समारोह का उपयोग करें sscanf पर, स्ट्रिंग को पार्स करने के लिए सामग्री की एक अलग लाइन है । यह अनुमति देगा करने के लिए आप का उपयोग जारी रखने scansets. या आप कर सकते हैं पार्स लाइन द्वारा कुछ अन्य अर्थ है. किसी भी तरह से, के रूप में लंबे समय के रूप में आप का उपयोग कर रहे हैं fgets के बजाय scanf पढ़ने के लिए इनपुट, आप से निपटने जाएगा एक लाइन के साथ इनपुट पर एक समय है, जो प्राकृतिक और सहज तरीके से निपटने के लिए लाइन-आधारित उपयोगकर्ता इनपुट.

जब हम का उपयोग करें fgets क्या होगा यदि उपयोगकर्ता अक्षर दर्ज करें और अधिक से अधिक सीमा (मैं एक बहुत मतलब है के अक्षर) है, यह नेतृत्व करने के लिए बफर अतिप्रवाह? तो फिर कैसे इसे से निपटने के लिए?

यदि उपयोगकर्ता में प्रवेश करती है और अधिक से पात्रों में फिट बफर द्वारा निर्दिष्ट के रूप में दूसरी fgets समारोह तर्क है, तो यह नहीं होगा अतिप्रवाह के बफर. इसके बजाय, यह केवल निकालने के रूप में कई वर्ण इनपुट स्ट्रीम से फिट के रूप में बफर में. आप निर्धारित कर सकते हैं पूरे रेखा के द्वारा पढ़ा था कि क्या जाँच स्ट्रिंग शामिल हैं एक newline चरित्र '\n' अंत में.

2021-11-23 15:13:39

बहुत बहुत धन्यवाद, अपने जवाब के लिए वास्तव में मददगार ।
Becker

के व्यवहार fgets() केवल सहज ज्ञान युक्त आदानों के लिए नहीं कर रहे हैं कि लंबे समय तक की तुलना में उम्मीद है.
supercat
2

यह एक अधिक चर्चा की विषय है, पूरा राय की लेकिन दिलचस्प कोई भी कम है. मैंने देखा है कि एक बड़े बहुमत के उन है कि पहले से ही जवाब दिया के लिए इसी तरह के सवाल इस साइट पर गिर के किनारे पर fgets(). मैं उनमें से एक हूँ. मैं खोजने के लिए fgets() किया जा करने के लिए ज्यादा बेहतर है का उपयोग करने के लिए उपयोगकर्ता इनपुट के लिए की तुलना में scanf() कुछ अपवादों के साथ. scanf() कई द्वारा माना जाता है के रूप में के रूप में उप-इष्टतम विधि से निपटने के लिए उपयोगकर्ता इनपुट. उदाहरण के लिए

"...यह आपको बता देगा कि क्या यह सफल रहा या विफल रहा है, लेकिन आप बता सकते हैं केवल लगभग, जहां यह विफल रहा है, और सब पर नहीं कैसे या क्यों. आप बहुत कम अवसर ऐसा करने के लिए किसी भी त्रुटि वसूली."
(jamesdlin). लेकिन ब्याज के प्रयास में संतुलन शुरू होगा, का हवाला देते हुए इस चर्चा.

उपयोगकर्ता इनपुट के लिए से आता है कि stdinयानी , कुंजीपटल इनपुट, fgets() एक बेहतर विकल्प हो जाएगा. यह बहुत अधिक क्षमा है कि स्ट्रिंग इसे पढ़ता है हो सकता है पूरी तरह से मान्य करने से पहले रूपांतरण का प्रयास किया है

एक बार कुछ का उपयोग कर एक फार्म के scanf(): fscanf() ठीक हो जाएगा का उपयोग करने के लिए हो सकता है जब परिवर्तित इनपुट से एक बहुत ही नियंत्रित स्रोत, यानी पढ़ने से एक सख्ती से स्वरूपित फ़ाइल के साथ दोहरा उम्मीद के मुताबिक खेतों ।

अधिक चर्चा के लिए, इस तुलना के दो पर प्रकाश डाला गया अतिरिक्त के फायदे और नुकसान दोनों है ।

संपादित करें: के लिए पता सेशन अतिरिक्त प्रश्न के बारे में अतिप्रवाह:

"एक और बात मैं पूछना चाहता हूँ है: यहां तक कि जब हम का उपयोग करें fgets क्या होगा यदि उपयोगकर्ता अक्षर दर्ज करें और अधिक से अधिक सीमा (मैं एक बहुत मतलब है की अक्षर) है, यह नेतृत्व करने के लिए बफर अतिप्रवाह? तो कैसे के साथ सौदा करने के लिए यह क्या है?"

[fgets()](https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm अच्छी तरह से बनाया गया है को रोकने के लिए बफर अतिप्रवाह, का उपयोग करके बस अपने मानकों को ठीक से, जैसे:

char buffer[100] = {0};
...
while fgets(buffer, sizeof buffer, stdin);  

इस से बचाता है इनपुट की तुलना में अधिक बफर आकार में संसाधित किया जा रहा से, इस प्रकार की रोकथाम अतिप्रवाह.

यहां तक कि का उपयोग कर scanf()को रोकने के बफर अतिप्रवाह है बहुत सीधे आगे का उपयोग करें: एक चौड़ाई विनिर्देशक में प्रारूप स्ट्रिंग है । यदि आप पढ़ने के लिए चाहते हैं के लिए इनपुट के उदाहरण और सीमित इनपुट से आकार करने के लिए उपयोगकर्ता 100 अक्षर मैक्स, कोड होगा निम्न शामिल हैं:

char buffer[101] = {0};// includes space for 100 + 1 for NULL termination

scanf("%100s", buffer);
        ^^^  width specifier 

हालांकि, संख्या के साथ अतिप्रवाह नहीं है, तो अच्छा उपयोग scanf(). प्रदर्शित करने के लिए, का उपयोग इस सरल कोड inputting दो मूल्यों का संकेत दिया टिप्पणी में प्रति एक चलाएँ:

int main(void)
{
    int val = 0;
    // test with 2147483647 & 2147483648
    scanf("%d", &val);
    printf("%d\n", val);
    
    return 0;
}

दूसरे के लिए मूल्य, अपने सिस्टम फेंकता है निम्नलिखित:

NON-FATAL RUN-TIME ERROR: "test.c", line 11, col 5, thread id 22832: Function scanf: (errno == 34 [0x22]). Range error `

यहाँ आप की जरूरत है पढ़ने के लिए एक स्ट्रिंग में है, तो साथ पालन करने के लिए एक स्ट्रिंग संख्या रूपांतरण में से एक का उपयोग strto_() कार्य: strtol(), strtod(), ...). दोनों की क्षमता शामिल करने के लिए परीक्षण के लिए अतिप्रवाह से पहले के कारण एक रन-समय पर चेतावनी या त्रुटि । ध्यान दें कि का उपयोग कर atoi(), atod() से रक्षा नहीं करेगा अतिप्रवाह या तो.

2021-11-23 14:10:20

धन्यवाद, मैं वास्तव में सराहना करते हैं अपने जवाब.
Becker

एक सवाल है, "पूर्ण की राय"? मैं सम्मान से असहमत हैं. यह राय की बात नहीं है कि scanf लगभग पूरी तरह से बेकार है, अच्छा है पर पढ़ने के लिए सबसे अच्छा एकल, सरल आदानों में पहचान करने के लिए सी कार्यक्रम, लेकिन बेहद मुश्किल कुछ भी करने के लिए दूर से परिष्कृत के साथ — इन तथ्यों को स्पष्ट कर रहे हैं! :-)
Steve Summit
1

अब तक, सारे सवालों के जवाब यहाँ प्रस्तुत की पेचीदगियों scanf और fgetsहै , लेकिन मैं क्या विश्वास है, उल्लेख के लायक है कि उन दोनों के कार्यों पदावनत में वर्तमान C के लिए मानक है । Scanf विशेष रूप से खतरनाक है, क्योंकि यह सभी प्रकार की सुरक्षा के मुद्दों के साथ बफर overflows. fgets नहीं है के रूप में समस्याग्रस्त है, लेकिन मेरे अनुभव से, यह एक सा हो जाता है भद्दा और नहीं, तो कुछ उपयोगी अभ्यास में.

सच है, अक्सर आप सच में पता नहीं कैसे लंबे समय के उपयोगकर्ता इनपुट होगा. आप प्राप्त कर सकते हैं चारों ओर का उपयोग करके इस fgets के साथ मुझे आशा है कि यह होगा काफी बड़ा बफर है, लेकिन नहीं है कि वास्तव में ellegant. इसके बजाय, क्या आप अक्सर ऐसा करना चाहते हैं के लिए है गतिशील बफर होगा कि विकसित करने के लिए काफी बड़ा हो सकता है स्टोर करने के लिए जो कुछ भी उपयोगकर्ता इनपुट वितरित करेंगे । और जब यह है getline समारोह में खेलने में आता है । यह करने के लिए इस्तेमाल किया पढ़ने के किसी भी संख्या से पात्रों के उपयोगकर्ता हैं, जब तक \n का सामना करना पड़ा है. अनिवार्य रूप से, यह भार पूरी लाइन के लिए अपनी स्मृति, एक स्ट्रिंग के रूप में.

size_t getline(char **lineptr, size_t *n, FILE *stream);

इस समारोह में लेता है एक सूचक को एक गतिशील रूप से आवंटित स्ट्रिंग के रूप में पहला तर्क है, और करने के लिए एक सूचक का एक आकार आवंटित बफ़र के रूप में एक दूसरे तर्क और धारा के रूप में एक तीसरा तर्क. (आप अनिवार्य रूप से जगह stdin वहाँ के लिए कमांड लाइन इनपुट). और रिटर्न की संख्या को पढ़ने के पात्रों सहित, \n अंत में, लेकिन नहीं समाप्त अशक्त.

यहाँ, आप देख सकते हैं उदाहरण के उपयोग के इस समारोह में:

int main() {

printf("Input Something:\n");  // asking user for input

size_t length = 10;                   // creating "base" size of our buffer
char *input_string = malloc(length);  // allocating memory based on our initial buffer size
size_t length_read = getline(&input_string, &length, stdin);  // loading line from console to input_string
// now length_read contains how much characters we read
// and length contains new size of our buffer (if it changed during the getline execution)

printf("Characters read (including end of line but not null at the end)"
       ": %lu, current size of allocated buffer: %lu string: %s"
       , length_read, length, input_string);

free(input_string);    // like any other dynamically-allocated pointer, you must free it after usage
return 0;
}

बेशक, इस समारोह का उपयोग कर की आवश्यकता के बारे में बुनियादी ज्ञान के सूचक और गतिशील स्मृति C, हालांकि थोड़ा और अधिक जटिल प्रकृति की getline निश्चित रूप से लायक है, क्योंकि यह प्रदान की सुरक्षा और लचीलापन.

आप और अधिक पढ़ सकते हैं इस समारोह के बारे में, और अन्य इनपुट में उपलब्ध कार्यों C, इस वेबसाइट पर: https://www.studymite.com/blog/strings-in-c मैं यह विश्वास का सार की पेचीदगियों C इनपुट बहुत अच्छी तरह से.

2021-11-23 19:18:00

धन्यवाद आपकी सलाह के लिए और लिंक, यह मुझे एक बहुत मदद मिलती.
Becker
1

यदि आप उदाहरण के लिए एक चरित्र सरणी घोषित तरह

char s[100];

और पढ़ने के लिए चाहते हैं एक स्ट्रिंग में एम्बेडेड रिक्त स्थान है, तो आप उपयोग कर सकते हैं या तो scanf निम्नलिखित तरीके:

scanf( "%99[^\n]", s );

या fgets जैसे:

fgets( s, sizeof( s ), stdin );

इन दोनों के बीच अंतर कहता है कि कॉल के scanf पढ़ा नहीं है नई लाइन चरित्र '\n' से इनपुट बफर. जबकि fgets पढ़ता नई लाइन चरित्र '\n' अगर वहाँ है पर्याप्त जगह में चरित्र सरणी.

को दूर करने के लिए नई लाइन चरित्र '\n' में संग्रहित है कि चरित्र सरणी का उपयोग करने के बाद fgets आप लिख सकते हैं उदाहरण के लिए:

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

यदि इनपुट स्ट्रिंग की तुलना में अधिक है 99 अक्षर तो दोनों कॉल केवल पढ़ने के लिए 99 अक्षर और संलग्न पात्रों के अनुक्रम के साथ समाप्त शून्य चरित्र '\0'. शेष सभी वर्ण हो जाएगा अभी भी में इनपुट बफर.

वहाँ के साथ एक समस्या है fgets. उदाहरण के लिए इससे पहले कि यदि fgets वहाँ प्रयोग किया जाता है scanf उदाहरण के रूप में:

scanf( "%d", &x );
fgets( s, sizeof( s ), stdin );

और उपयोगकर्ता इनपुट है:

10
Hello World

फिर कॉल के fgets पढ़ा होगा केवल नई लाइन चरित्र '\n' संग्रहीत किया जाता है कि बफर में दबाने के बाद कुंजी दर्ज करें जब पूर्णांक मूल्य के कॉल में scanf पढ़ा था.

इस मामले में आप की जरूरत लिखने के लिए एक कोड को हटाने जाएगा कि नई लाइन चरित्र '\n' फोन करने से पहले fgets.

आप कर सकते हैं इस उदाहरण के लिए निम्नलिखित तरीके हैं:

scanf( "%d", &x );
scanf( " " );
fgets( s, sizeof( s ), stdin );

यदि आप उपयोग कर रहे हैं scanf तो ऐसी स्थिति में आप लिख सकते हैं:

scanf( "%d", &x );
scanf( " %99[^\n]", s );
       ^^ 
2021-11-23 14:05:15

अन्य भाषाओं में

यह पृष्ठ अन्य भाषाओं में है

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................

इस श्रेणी में लोकप्रिय

लोकप्रिय सवाल इस श्रेणी में