2012-03-17 103 views
3

我想從控制檯讀取一個字符串。從標準輸入讀取任意大小的字符串?

然而,使用scanf或者fgets,在我看來,它只能讀取固定最大大小的字符串。更糟糕的是,似乎沒有辦法檢查用戶輸入太多情況下輸入的字符數(在這種情況下,我可以簡單地重新分配數組,以使字符串適合數組)。

我讀過我應該在this question的回答中一次讀出一個字符,但是我不知道如何一次讀取一個字符,而不必讓用戶在每個字符後按回車。

我該怎麼辦?

+1

用戶輸入的字符會被緩衝,直到用戶按下回車鍵,但您仍然可以一次讀取一個字符。直到用戶按下回車鍵,讀數纔會開始。 – 2012-03-17 14:59:59

回答

1

嘗試運行這個..

#include <stdio.h> 

int main(){ 
    char next; 
    while((next=getchar())!=EOF) 
     printf("%c\n",next); 

} 

然後檢查手冊頁的getchar(),看看手頭什麼是真正的。

+0

謝謝。這是最簡單的答案,證明我需要解決問題。 – TravisG 2012-03-17 16:00:36

+0

應該是'int next',否則你不能分辨EOF和'\ xff'之間的區別(或者如果char是無符號的,你將永遠循環)。 – zaphod 2016-02-25 01:06:28

1
char c = NULL; 
while (c != 0x0D) 
{ 
    scanf("%c", &c); 
    // do stuffs with c 
} 
4

GCC的文檔says說:

標準C具有的功能要做到這一點,但他們也不是很安全:空字符,甚至(對gets)長行可以迷惑他們。所以GNU庫提供了非標準的getline函數,可以很容易地可靠地讀取行。

[getline]是GNU擴展,但它是讀取從流線的推薦方法。替代標準功能不可靠。

所以如果你使用GCC,我會說你應該使用getline。如果你不使用GCC,你應該看看你的編譯器是否提供了類似的功能。如果它不是—或者如果你真的喜歡使用標準—,那麼你需要一次讀取一個字符。

我不知道如何一次讀取一個字符,而不需要用戶在每個字符後按回車。

是的,你這樣做。用戶輸入一系列字符,然後按Enter鍵。您的第一個fgetc呼叫將阻止,直到用戶按下Enter鍵,但在此之後,後續的fgetc呼叫將立即返回,直到您閱讀換行符。 (然後它會再次阻止,直到用戶再次按Enter。)一次讀取「一個字符」並不意味着您必須在用戶鍵入下一個字符之前閱讀每個字符;它只是意味着,一旦用戶輸入完一行,就可以一次讀取該行的一個字符。

1

您可以使用一個循環和realloc fgets()如果最後一個字符不是一個\n

/* UNTESTED: MAY HAVE OFF-BY-ONE ERRORS */ 
char *buffer; 
size_t bufsiz = 100; 
size_t buflen = 100; 
size_t bufcur = 0; 
buffer = malloc(bufsiz); 
for (;;) { 
    fgets(buffer + bufcur, bufsiz, stdin); 
    buflen = bufcur + strlen(buffer + bufcur); 
    if (buffer[buflen - 1] == '\n') break; 
    tmp = realloc(buffer, bufsiz * 2); 
    if (tmp == NULL) /* deal with error */; 
    buffer = tmp; 
    bufcur = buflen - 1; 
    bufsiz *= 2; 
} 
/* use buffer (and bufsiz and buflen) */ 
free(buffer); 
0

接受的答案應該注意的getchar()返回一個int。 char數據類型不足以容納EOF。

我們可以讀取預定量的文本,然後丟棄其餘的輸入。這種方法比批評者的份額多(我們如何敢於知道要拋棄什麼)。另一種選擇是使用getline或編寫自定義函數。我想我會嘗試後者。

這並不妨礙用戶使用cat large_file填充內存。

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <errno.h> 
#define MAX 50 
#define JUSTDO(a) if (!(a)) {perror(#a);exit(1);} 
/** char *get_line FILE *f 
* reads an arbitrarily long line of text or until EOF 
* caller must free the pointer returned after use 
*/ 
char *get_line (FILE *f) { 
    int len=MAX; 
    char buf[MAX],*e=NULL,*ret;JUSTDO (ret=calloc(MAX,1)); 
    while (fgets (buf,MAX,f)) { 
     if (len-strlen(ret)<MAX) JUSTDO (ret=realloc(ret,len*=2)); 
     strcat (ret,buf) ;if ((e=strrchr (ret,'\n'))) break; 
    } if (e) *e='\0'; 
    return ret; 
} 
/* main */ 
int main (void) { 
    char *s; 
    printf ("enter a line of text:\n"); 
    printf ("line was '%s'\n",s=get_line(stdin)) ;free (s); 
    return 0; 
} 
+0

只是......錯了。 http://linux.die.net/man/3/getchar。手冊頁CLEARLY指出fgetc(),getc()和getchar()將讀取的字符作爲無符號字符轉換爲文件或錯誤結尾處的int或EOF。依賴於系統的EOF通常是-1(或全1位的字)。 – FrankieTheKneeMan 2012-08-10 16:43:43