2017-02-04 2 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 = newStringinputStringポイントがnewStringのメモリにあることを意味します。ときにfree(newString)それはまたinputStringのメモリです。

代わりに、のポインタをコピーする前に、古いメモリfree(inputString)にしてください。

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

いくつかの注意。

容量が1の文字列はnullバイトしか保持できないため、容量は2以上で開始してください。

strncpyで文字列のコピーをよりうまく行うことができます。

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

newStringinputStringの内容を保持するのに十分な大きさにもかかわらず、我々はまだinputStringは終了nullではないので限度とstrncpyを使用する必要があります。さもなければ、文字列の最後からガーベジが読み込まれます。

strncpyは特に安全ではありませんが、コピーを停止すると終了しませんが、この特定のインスタンスでは、終了時にnullで終了します。

次に、これはすべて不要です。これは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; else {... handle error ...} 'というエラーメッセージが表示されます。 –

+0

@JonathanLefflerありがとう、私は何かを逃したことを知っていた。 'memcpy'と' strncpy'の利点はありますか?もし私が 'realloc'エラー処理について少し詮索するなら、あなたは私を許します、それはそれ自身の主題です。 – Schwern

+0

それは限界があるでしょうが、そうです。 'strncpy()'はヌルバイト(見つからないでしょう)をカウントしてチェックする必要がありますが、 'memcpy()'はカウントするだけです。 –

関連する問題