2017-02-04 51 views
0
#include <stdio.h> 

char* getString() 
{ 
    char buffer; 
    int size = 0; 
    int capacity = 1; 

    char* inputString = (char*)malloc(capacity*sizeof(char)); 
    char* newString; 

    while(1) 
    { 
     buffer = getchar(); 
     if(buffer == '\n') 
      break; 
     if((capacity-1) <= size) 
     { 
      capacity *= 2; 
      newString = (char*)malloc(capacity*sizeof(char)); 
      int i; 
      for(i = 0; i < size; i++) 
       newString[i] = inputString[i]; 
      inputString = newString; 
      free(newString); 
     } 
     inputString[size] = buffer; 
     size++; 
    } 
    inputString[size] = '\0'; 
    return inputString; 
} 

int main() 
{ 
    char* str; 
    str = getString(); 
    printf("%s", str); 
} 

我寫了這個C程序來獲取一個字符串作爲C中的用戶輸入並將其存儲在一個可動態調整大小的數組中。但是,每次運行此程序時,它都會崩潰。 我經歷了這個程序的類似實現,但不能準確找出我的代碼有什麼問題爲什麼我在C中寫的下面的getString()函數不起作用?

+1

你使用調試器嗎?這是調試這些問題的方法(並且作爲最後的手段在Stackoverflow上發佈)。 – kaylum

+2

'* buffer = getchar();'查看你的代碼來回答:'buffer'指向哪裏?試試'char buffer = getchar();' – kaylum

+0

@kalyum試過了,仍然沒有用 – Sahil

回答

1

問題在這裏。

 capacity *= 2; 
     newString = (char*)malloc(capacity*sizeof(char)); 
     int i; 
     for(i = 0; i < size; i++) 
      newString[i] = inputString[i]; 
     inputString = newString; 
     free(newString); 

這是試圖做的是...

  1. 分配一個更大的字符串。
  2. 將舊字符串複製到新字符串。
  3. 使用新的字符串。
  4. 釋放舊的字符串。

但事實並非如此。問題是inputString = newString意味着inputString點在newString的記憶。當你接着free(newString)那也是inputString的記憶。

你想要的是free(inputString),舊存儲器,複製newString的指針前。

 capacity *= 2; 
     newString = (char*)malloc(capacity*sizeof(char)); 
     int i; 
     for(i = 0; i < size; i++) 
      newString[i] = inputString[i]; 
     free(inputString); 
     inputString = newString; 

的一些注意事項。

您應該從容量至少爲2開始,因爲容量爲1的字符串只能容納空字節。

字符串複製可以用strncpy更好地完成。

 capacity *= 2; 
     newString = (char*)malloc(capacity*sizeof(char)); 
     strncpy(newString, inputString, size); 
     free(inputString); 
     inputString = newString; 

即使newString是大到足以容納的inputString內容,我們仍然需要使用strncpy有限制,因爲inputString不是空終止。否則,它會讀取字符串末尾的垃圾。

strncpy不是特別安全,它不會在它停止複製時終止,但是對於這個特定的實例,您將在終止時終止它是正常的。

接下來,這是沒有必要的。它可以通過realloc完成。這會增大,縮小或重新分配內存,並在必要時進行復制。

 capacity *= 2; 
     inputString = realloc(inputString, capacity * sizeof(char)); 
     if(inputString == NULL) { 
      fprintf(stderr, "Reallocation failed.\n"); 
      exit(1); 
     } 
+0

'inputString'在循環結束之前不是空終止的;使用'strcpy()'是不可靠的。使用'memmove()'或'memcpy()'會更合適。而'oldptr = realloc(oldptr,newsize);'meme是等待中的內存泄漏 - 你應該有'newptr = realloc(oldptr,newsize); if(newptr!= 0)oldptr = newptr;其他{...處理錯誤...}爲了安全。 –

+0

@JonathanLeffler謝謝,我知道我錯過了什麼。 'memcpy'和'strncpy'在這裏有什麼優勢嗎?如果我在'realloc'錯誤處理上吝嗇一點,那麼你會原諒我,這是它自己的主題。 – Schwern

+0

這將是微不足道的,但是; 'strncpy()'必須計數並檢查空字節(它不會找到),而'memcpy()'只需要計數。 –

相關問題