2016-01-04 37 views
3

我正在學習C編程,我必須實現一個讀取未知大小輸入字符串的程序。 我寫了這個代碼:這兩種方法在C中獲取字符串輸入有什麼區別?

int main() { 
    char *string; 
    char c; 
    int size = 1; 

    string = (char*)malloc(sizeof(char)); 

    if (string == NULL) { 
     printf("Error.\n"); 
     return -1; 
    } 
    printf("Enter a string:"); 
    while ((c = getchar()) != '\n') { 
     *string = c; 
     string = (char*)realloc(string, sizeof(char) * (size + 1)); 
     size++; 
    } 
    string[size - 1] = '\0'; 

    printf("Input string: %s\n", string); 

    free(string); 
    return 0; 
} 

但最後printf沒有顯示整個字符串,但只有最後一個字符。 所以如果我輸入hello, world最後的printf打印d

經過一番研究,我嘗試this代碼,它的工作原理!但我沒有與我的區別。

我希望我自己清楚,謝謝你的關注。

+0

請注意,一次增加字符串大小一個字節可能會導致性能下降。一般來說,你最好把字符串的大小加倍,或者在附近。如果它在結尾處顯得太大(例如,你需要2048個字節的字符串,但只能使用1080字節),那麼可以使用另一個'realloc()'將其縮小到最小。但這不太可能是一個主要問題。 –

+0

@JonathanLeffler:雖然我同意你的評論,但是'realloc'方案的效率低下是OPs問題中最少的。 – chqrlie

+1

@chqrlie:這就是爲什麼它是一個評論,而不是一個答案。 –

回答

3

有幾個問題與您的代碼:

  • 你的所有字符存儲到分配的內存
  • 你讀字符的第一個字節變成char變量,則無法正確測試EOF
  • 如果標準輸入不包含'\n'(例如從空文件重定向),則將運行無限循環,分配所有可用內存並最終崩潰。
  • 不那麼重要,您爲每個字節的讀取重新分配緩衝區,效率低下,但可以稍後進行優化。

這裏是一個修正版本:

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

int main() { 
    char *string; 
    int c; 
    int len = 0; 

    string = malloc(1); 
    if (string == NULL) { 
     printf("Error.\n"); 
     return -1; 
    } 
    printf("Enter a string:"); 
    while ((c = getchar()) != EOF && c != '\n') { 
     string[len++] = c; 
     string = realloc(string, len + 1); 
     if (string == NULL) { 
      printf("cannot allocate %d bytes\n", len + 1); 
      return -1; 
     } 
    } 
    string[len] = '\0'; 

    printf("Input string: %s\n", string); 
    free(string); 
    return 0; 
} 

關於你提到的有關使用鏈接的代碼的差異問題,它使用相同的方法,少了一個錯誤,但也多了一個錯誤:

  • 它將字符存儲在str的適當偏移量中。
  • 如果輸入文件不包含'\n',則它將與您的輸入文件一樣運行無限循環。
  • 它調用未定義的行爲,因爲c未初始化爲第一個測試。
5

在你分配的新讀取字符,c,以string的代碼版本,使用:

*string = c; 

*string點在字符串的開頭,所以你跟上替換字符串的第一個字符新讀字符。

您鏈接到該代碼執行以下操作:

str[i] = c 

基本上,它被指定的字符字符串的結尾,使用索引i

在您的代碼版本中,您可以使用size - 1而不是i

3

嘗試改變:

*string = c; 

要:

string[size-1] = c; 

這樣,你就不會只是每次覆蓋的第一個字符。

1

嘗試

*(string + size - 1) = c; 

也許這有助於

+1

爲什麼用符號代替'string [size-1] = c;'? –

+0

爲了表明這裏涉及到指針而不是數組。只要OP得知,這個「簡短」的答案就很有用。 – Michi

相關問題