2011-10-20 95 views
19

似乎有很多方法可以獲得用戶輸入C.在C中獲取用戶輸入的最簡單方法是什麼?

什麼是最簡單的方法,只需要很少的代碼?

基本上我需要顯示此:

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拍攝。

(注:我改變了Bjarne的代碼來檢查isspace(),而不是僅僅行尾此外,由於@ matejkramny的評論,使用while(1),而不是while(true) ......等等,只要我們是足夠的異端。編輯Stroustrup的代碼,我的埋入在C89的意見,而不是C++風格太:-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; 
} 

這包括:

  • 跳過空白,直到你到達字符把
  • 擴大字符串緩衝區動態地適應任意大小的字符串時內存無法分配

  • 操作條件是否有簡單,但破碎的解決方案,甚至可能運行快一點?絕對!!

    如果您將scanf用於讀取大小沒有限制的緩衝區,那麼您的輸入會超過緩衝區的大小,這會造成安全漏洞和/或崩潰。

    將讀數的大小限制爲比方說只有100個文件名的唯一字符看起來好於崩潰。但可能會更糟;例如,如果用戶的意思是(...)/dir/foo/bar.txt,但最終會誤解他們的輸入並覆蓋可能關心的名爲bar.t的文件。

    最好在處理這些問題時儘早進入良好習慣。 我的觀點是,如果你的要求證明某些東西接近於金屬和「類C」,那麼考慮跳轉到C++是非常值得的。它旨在精確管理這些問題 - 使用強大且可擴展的技術,但仍然表現良好。

  • +0

    即使你的班級希望你瀏覽並繼續前進,我也會建議在任何你明知故障的地方做筆記。所以旁邊的閱讀操作只是堅持像'/ * REVIEW:輸入正確性的評論,請參閱http://stackoverflow.com/questions/7831755/what-is-the-simplest-way-of-getting-user-input -in-c/* /'它顯示你做你的研究,保留鏈接供以後閱讀。另外,任何調試正在發生神祕崩潰的代碼庫的人都可以將他們的注意力吸引過來 - 不僅看到警告,而且看到指向討論正確解決方案的指針。 – HostileFork

    +1

    順便提一下,問題要求C不是C++ –

    +1

    @matejkramny在我引用和引用的論文中,Bjarne Stroustrup將「C方式」與「C++方式」進行了對比。這是他提出的「C方式」代碼。它不是C++代碼。論文的要點是,這個「正確」的C代碼可以用C++更加突出地表達,而且不會損失效率;這可能讓頑固的C程序員感到驚訝。我向你保證我可以閱讀這個問題;我只是認爲我讀過的最好的答案之一是如何編寫C++爲你默認的「正確」C語言版本,它來自於一篇撰寫C++傳福音文章的論文。你應該閱讀報紙,雖然它很老。 – HostileFork

    1
    #include <iostream> 
    #include <string> 
    
    using namespace std; 
    
    int main() 
    { 
        cout << "Enter a file name:"; 
    
        string filepath; 
        cin >> filepath; 
    } 
    
    +2

    如果* C++ *,肯定......那些小* *的*是相關的;-) – 2011-10-20 06:10:35

    +0

    那麼這是C++,你最初有你的問題標記爲。 – Ayjay

    +0

    是C++嗎?我不能使用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

    中使用'scanf'生病!看起來很對我! – antonpug

    +1

    相關:http://stackoverflow.com/questions/1252132/difference-between-scanf-and-fgets – HostileFork

    7

    scanf似乎在非敵對的環境中工作。換句話說,你正在爲自己製作一個簡單的實用程序。

    BUFSIZ通常遠遠超過UNIX路徑名的大小限制。

    #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

    *用戶*是敵對的...... :( – 2011-10-20 06:51:17

    1

    你應該寫自己與fgets()包裝函數讀取一行輸入到指定大小的緩衝區,並且消除了換行字符是FGETS()也讀取。您也可以返回整行是否能夠放入緩衝區的狀態(即,是緩衝區末尾的換行符)。除非你想要溢出,否則你不應該使用scanf或者獲取它。

    編輯:想我可能會提供一些基本代碼:

    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

    'scanf'具有字符限制,如'scanf(「%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); 
         }                                
    
    相關問題