2011-10-20 13 views
19

सीसी में उपयोगकर्ता इनपुट प्राप्त करने का सबसे आसान तरीका क्या है?

में उपयोगकर्ता इनपुट प्राप्त करने के कई तरीकों से ऐसा लगता है कि कम कोड की आवश्यकता सबसे आसान तरीका क्या है?

मूल रूप से मैं इस प्रदर्शित करने के लिए की जरूरत है:

Enter a file name: apple.text 

मूल रूप से मैं एक फ़ाइल नाम के लिए उपयोगकर्ता पूछने के लिए की जरूरत है। तो मुझे ऐसा कुछ चाहिए जो सिर्फ उस शब्द को प्राप्त करे जो उपयोगकर्ता इनपुट करेगा।

+0

संभावित उपयोग नकल http://stackoverflow.com/questions/314401/how-to-read-a-line-from-the-console-in-c –

उत्तर

22

सरल "सही" तरीका शायद इस एक, Bjarne Stroustrup पेपर Learning Standard C++ As A New Language से लिया है।

(नोट: मैं while(true) के बजाय while(1) उपयोग करने के लिए @ matejkramny की टिप्पणी के कारण के बजाय isspace() के लिए जाँच बस लाइन के अंत में Bjarne का कोड बदल इसके अलावा, ... और इतने लंबे समय हम पर्याप्त विधर्मी जा रहा है कर रहे हैं के रूप में। Stroustrup के कोड को संपादित करने के लिए, मैं C89 भी सी के बजाय ++ शैली टिप्पणी में subbed गया है :-P)

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

void quit() /* write error message and quit */ 
{ 
    fprintf(stderr, "memory exhausted\n"); 
    exit(1); 
} 

int main() 
{ 
    int max = 20; 
    char* name = (char*) malloc(max); /* allocate buffer */ 
    if (name == 0) quit(); 

    printf("Enter a file name: "); 

    while (1) { /* skip leading whitespace */ 
     int c = getchar(); 
     if (c == EOF) break; /* end of file */ 
     if (!isspace(c)) { 
      ungetc(c, stdin); 
      break; 
     } 
    } 

    int i = 0; 
    while (1) { 
     int c = getchar(); 
     if (isspace(c) || c == EOF) { /* at end, add terminating zero */ 
      name[i] = 0; 
      break; 
     } 
     name[i] = c; 
     if (i == max - 1) { /* buffer full */ 
      max += max; 
      name = (char*) realloc(name, max); /* get a new and larger buffer */ 
      if (name == 0) quit(); 
     } 
     i++; 
    } 

    printf("The filename is %s\n", name); 
    free(filename); /* release memory */ 
    return 0; 
} 

को शामिल किया गया है कि:।

  • खाली स्थान के लंघन जब तक आप में चरित्र तक पहुँचने
  • डाल स्ट्रिंग बफर के विस्तार गतिशील मनमाने ढंग से आकार तार फिट करने के लिए
  • जब स्मृति

आवंटित नहीं किया जा सकता से निपटने की स्थिति वहाँ सरल लेकिन टूटी समाधान कर रहे हैं, जो भी एक सा तेजी से चला सकता है? पूर्ण रूप से!!

यदि आप स्कैनफ़ को एक बफर में पढ़ने के आकार पर कोई सीमा नहीं देते हैं, तो आपका इनपुट बफर के आकार से अधिक है, यह एक सुरक्षा छेद और/या क्रैश बनाएगा।

पढ़ने के आकार को सीमित करने के लिए कहें, फ़ाइल नाम के केवल 100 अद्वितीय वर्ण क्रैश होने से बेहतर प्रतीत हो सकते हैं। लेकिन यह बदतर हो सकता है; उदाहरण के लिए यदि उपयोगकर्ता का अर्थ (...)/dir/foo/bar.txt था, लेकिन आप bar.t नामक फ़ाइल को ओवरराइटर करना चाहते हैं और शायद वे इसकी परवाह करते हैं।

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

+0

भले ही आपकी कक्षा आपको स्कैनफ और आगे बढ़ना चाहती है, फिर भी मैं सुझाव देता हूं कि कहीं भी आप जानबूझकर कुछ टूटा/लाभकारी करें। तो आपके पढ़ने के संचालन के बगल में बस एक टिप्पणी में रहें जैसे '/ * समीक्षा: इनपुट शुद्धता, http://stackoverflow.com/questions/7831755/what-is-the-simplest-way-of-getting-user-input देखें -इन-सी/*/'यह दिखाता है कि आप अपना शोध करते हैं, बाद में पढ़ने के लिए लिंक रखता है। इसके अलावा कोई भी व्यक्ति जो एक क्रैश क्रैश प्राप्त कर रहा है उसे कोडबस डिबग करने पर उनका ध्यान खींचा जा सकता है - न केवल चेतावनी को देखते हुए बल्कि सही समाधान की चर्चा के लिए एक सूचक। – HostileFork

+1

बीटीडब्ल्यू सवाल सी के लिए पूछता है सी ++ –

+1

@matejkramny पेपर में उद्धरण और उद्धरण, Bjarne Stroustrup "सी ++ रास्ता" के लिए "सी रास्ता" का विरोध करता है। यह उसका "सी रास्ता" कोड है जिसे मैं प्रस्तुत कर रहा हूं। यह सी ++ कोड नहीं है। पेपर का मुद्दा यह है कि यह "सही" सी कोड सी ++ में अधिक सहनशील रूप से व्यक्त किया जा सकता है और दक्षता की कोई हानि नहीं होती है; जो मरने वाले सी प्रोग्रामर को आश्चर्यचकित कर सकता है। मैं आपको आश्वासन देता हूं कि मैं सवाल पढ़ सकता हूं; मैंने सोचा कि सबसे अच्छे उत्तरों में से एक मैंने सोचा था कि "सही" सी संस्करण को कैसे लिखना है, जो डिफ़ॉल्ट रूप से आपके लिए सी ++ करता है, वह एक पेपर से आया है जो सी ++ सुसमाचार का काम था। आपको पेपर पढ़ना चाहिए, हालांकि यह पुराना है। – HostileFork

1
#include <iostream> 
#include <string> 

using namespace std; 

int main() 
{ 
    cout << "Enter a file name:"; 

    string filepath; 
    cin >> filepath; 
} 
+2

यह तो * सी ++ * थे, यकीन है .... उन छोटे * + * * प्रासंगिक हैं ;-) –

+0

वैसे यह सी ++ में है, जिसे आपने मूल रूप से अपना प्रश्न टैग किया था। – Ayjay

+0

वह सी ++ है? मैं C++ – antonpug

3
#include <stdio.h> 
int main(void) 
{ 
    char file[100]; 
    printf("File Name?: \n"); 
    fgets(file, 100, stdin); 
    printf("Your input: %s", file); 
} 
+0

बीमार में 'स्कैनएफ' का प्रयोग करें! मुझे सही लग रहा है! – antonpug

+1

संबंधित: http://stackoverflow.com/questions/1252132/difference-between-scanf-and-fgets – HostileFork

7

scanf एक गैर शत्रुतापूर्ण वातावरण में काम करने लगता है। दूसरे शब्दों में, आप अपने लिए एक सरल उपयोगिता कार्यक्रम बना रहे हैं।

BUFSIZ आमतौर पर यूनिक्स पथनामों की आकार सीमा से अधिक है।

#include <stdio.h> 

int main(void) { 
    char str[BUFSIZ];                                            

    printf("Enter a file name: ");                                         
    scanf("%s", str);                                            

    printf("You entered: %s\n", str);                                        
} 

आप एक प्रोग्राम है कि बफर सीमा से अधिक का लक्ष्य हो सकता है में डेटा जमा करने के लिए की जरूरत है, तो आप थोड़ा अधिक आवश्यकता हो सकती है।

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

char * prompt_and_read(const char * prompt) { 
    char * response; 
    char * bufsize; 

    printf("%s", prompt); 
    asprintf(&bufsize, "%%%us", BUFSIZ); 

    if((response = malloc(BUFSIZ + 1)) == NULL) { 
    fprintf(stderr,"out of memory\n"); 
    exit(1); 
    } 
    scanf(bufsize, response); 
    free(bufsize); 
    return response; 
} 

int main (void) { 
    char * pathname; 

    pathname = prompt_and_read("Enter a file name: "); 
    printf("You entered: [%s]\n", pathname); 
    free(pathname); 

    return 0; 
} 
+1

तो क्या होता है यदि स्ट्रिंग BUFSIZ से अधिक हो ...? – HostileFork

+0

यह वास्तव में संभव है, लेकिन मैं इस धारणा के तहत था कि वह गैर-शत्रुतापूर्ण वातावरण में फ़ाइल नाम इनपुट करना चाहता था। ;-) यदि यह शत्रुतापूर्ण था, तो उसे कुछ और अधिक शामिल करना होगा। और उसने एक ऐसे समाधान के लिए कहा जो केवल एक छोटा कोड शामिल था। – karrick

+4

* उपयोगकर्ता * शत्रुतापूर्ण हैं ... :( –

1

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

संपादित करें: सोचा मैं कुछ बुनियादी कोड प्रदान कर सकते हैं:

typedef unsigned char BOOL; 
#define TRUE 1 
#define FALSE 0 

/* wraps fgets, returns FALSE if the whole line couldn't fit into the buffer */ 
BOOL read_input(char *dest, size_t len) 
{ 
    /* our temp buffer needs to hold the extra new line char (len + 1) 
     * should also add error checking to malloc */ 
    BOOL bSuccess = TRUE; 
    size_t total_len = len + 1; 
    char *temp = (char*) malloc(total_len * sizeof(char)); 

    fgets(temp, total_len, stdin); 

    /* if the whole line wasn't read, we'll return FALSE but still copy temp into dest */ 
    if (temp[strlen(temp) - 1] != '\n') 
     bSuccess = FALSE; 
    else 
     temp[strlen(temp) - 1] = '\0'; /* overwrite the '\n' if it does infact exist */ 

    strcpy(dest, temp); 

    free(temp); 
    return bSuccess; 
} 
+0

वैसे यह एक सरल (ठीक है, इतना आसान नहीं) प्रोग्रामिंग असाइनमेंट के लिए है। बस इस बिंदु पर कक्षा उत्तीर्ण करना चाहते हैं। जटिल पर नहीं जा रहा है। हालांकि धन्यवाद! – antonpug

+0

उपरोक्त आसानी से 10 लाइनों के तहत किया जा सकता है, यह वास्तव में इस बात पर निर्भर करता है कि कार्यक्षमता को दोहराने के लिए आपको कितनी बार आवश्यकता होगी। आपके इनपुट के उपयोग के आधार पर, वह न्यूलाइन चार कभी-कभी समस्याएं भी पैदा कर सकता है। और यह भी ध्यान देने योग्य है कि यदि fgets आपके बफर में पूरी लाइन को फिट करने में असमर्थ है, तो आप अतिरिक्त इनपुट को तब तक हटाना चाहेंगे जब तक आपको कोई नई लाइन (लूप में fgetc) न हो। – AusCBloke

+0

'स्कैनफ़' में वर्ण सीमाएं हैं, जैसे' स्कैनफ़ ("% 99s", mySize100Buffer); '। लेकिन 'fgets' के विपरीत बाउंड को अंक स्ट्रिंग द्वारा निर्दिष्ट किया गया है, इसलिए BUFSIZE-1 संबंध को कैप्चर करने में कस्टम प्रारूप स्ट्रिंग उत्पन्न करना शामिल है। कुछ हद तक अव्यवहारिक ... – HostileFork

0

इस सरल कोड

#include"stdio.h" 
#include"stdlib.h" 
main() 
{ 
    int i=0,j=0; 
    char c,buf[100]; 

start: 
    printf("Enter the name:"); 
    while ((c=getchar()) != '\n') 
    { 
      buf[i++]=c; 
      buf[i]='\0'; 
    } 
    if (buf[0] == '\0') 
    { 
    printf("invalid name\n"); 
    goto start; 
    } 
    else 
    printf("Your name is valid\nName = %s\n",buf); 
     }                                
संबंधित मुद्दे

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