3

別の関数によって読み取られた文字列を含む配列、たとえばテキストがあります。弦の長さは不明で、その量も不明です。文字列の配列にメモリを割り当てるにはどうすればよいですか (別の配列として既に存在する文字列自体には割り当てません)。

私が今セットアップしたものは、文字列を問題なく読み取っているようで、正しく実行したい後処理を行っているようです (静的配列でこれを試しました)。ただし、テキストの要素を印刷しようとすると、セグメンテーション違反が発生します。より正確には、text[3] や text[5] などの特定のテキスト要素を出力しようとすると、セグメンテーション違反が発生します。これは、メモリをテキストに正しく割り当てておらず、読み取ったすべての文字列がテキストに正しく保存されていないことを意味していると思いますか?

size_t=k , k*sizeof(char)これまでのところ、最初にいくつかのセット量を割り当ててから、より多くのメモリを再割り当てするなど、さまざまなアプローチを試してきました( realloc k*sizeof(char)) if cnt == (k-2)cnt は **text.

これを検索しようとしましたが、私が見つけた唯一の同様の問題は、長さが不明な一連の文字列に関するものでした。

自分でできる限り理解したいので、実際のコードは投稿しませんでした。ただし、これが意味をなさない場合は、投稿します。

編集:これがコードです

int main(void){
  char **text;
  size_t k=100;
  size_t cnt=1;
  int ch;
  size_t lng;

  text=malloc(k*sizeof(char));

  printf("Input:\n");

  while(1) {

    ch = getchar();
    if (ch == EOF) {
      text[cnt++]='\0';
        break;
    }

    if (cnt == k - 2) {
      k *= 2;
      text = realloc(text, (k * sizeof(char))); /* I guess at least this is incorrect?*/
    }

    text[cnt]=readInput(ch); /* read(ch) just reads the line*/
    lng=strlen(text[cnt]);
    printf("%d,%d\n",lng,cnt);
    cnt++;
  }

  text=realloc(text,cnt*sizeof(char));
  print(text); /*prints all the lines*/

  return 0;
}
4

3 に答える 3

5

簡単に言えば、割り当てる量がわからない限り、メモリを直接割り当てることはできません。

ただし、割り当てる必要がある金額を決定するにはさまざまな方法があります。

これには 2 つの側面があります。1 つは、処理する必要がある文字列の数を知ることです。知るための明確な方法がなければなりません。カウントが与えられるか、最後に到達したことを知らせる特定のポインター値 (通常は NULL) があります。

ポインターの配列をポインターに割り当てるには、必要なポインターの数を数えてからスペースを割り当てるのがおそらく最も簡単です。null で終了するリストを想定すると、次のようになります。

size_t i;
for (i = 0; list[i] != NULL; i++)
    ;
char **space = malloc(i * sizeof(*space));
...error check allocation...

文字列ごとにstrdup();を使用できます。文字列は整形式で、null で終了していると想定します。または、独自の の類似物を作成することもできますstrdup()

for (i = 0; list[i] != NULL; i++)
{
    space[i] = strdup(list[i]);
    ...error check allocation...
}

別のアプローチでは、ポインターのリストを 1 回スキャンしますが、malloc()and をrealloc()複数回使用します。これはおそらく全体的に遅いです。

文字列のリストがいつ終了するか、または文字列自体がいつ終了するかを確実に判断できない場合は、うんざりしています。完全にそして完全にホース。

于 2012-11-12T20:32:27.100 に答える
1

Cには文字列がありません。(通常はnullで終了する)文字シーケンスへのポインタがあり、それらを文字列と呼びます。

したがって、最初にポインタの配列を割り当てるだけです。

 size_t nbelem= 10; /// number of elements
 char **arr = calloc(nbelem, sizeof(char*));

その配列を本当にクリアしたいcallocので、本当に必要です。したがって、各ポインターにはがありNULLます。もちろん、あなたはそれがcalloc成功したことをテストします:

 if (!arr) perror("calloc failed"), exit(EXIT_FAILURE);

最後に、配列のいくつかの要素を入力します。

 arr[0] = "hello";
 arr[1] = strdup("world");

free(の結果strdupとの結果を忘れないでくださいcalloc)。

でアレイを拡張できます(ただし、失敗するとデータが失われる可能性がreallocあるため、これを行うことはお勧めしません)。reallocより大きなコピーを割り当てて内部にコピーし、ポインタを再定義することで、単純に拡張できます。

 { size_t newnbelem = 3*nbelem/2+10;
   char**oldarr = arr;
   char**newarr = calloc(newnbelem, sizeof(char*));
   if (!newarr) perror("bigger calloc"), exit(EXIT_FAILURE);
   memcpy (newarr, oldarr, sizeof(char*)*nbelem);
   free (oldarr);
   arr = newarr;
 }

gcc -Wall -gLinuxでコンパイルすることを忘れないでください(警告が表示されなくなるまでコードを改善してください)。そして、gdbデバッガーとvalgrindメモリリーク検出器の使用方法を学びます。

于 2012-11-12T20:30:26.573 に答える
0

c では、文字列の配列を直接割り当てることはできません。文字列の配列として使用するには、char 配列へのポインターを使用する必要があります。だから使う

char* strarr[length];

そして、文字の配列を維持するには、次のようなアプローチを取ることができます。


  1. への呼び出しによってメモリのブロックを割り当てますmalloc()
  2. 入力のサイズを追跡する
  3. バッファサイズの呼び出しでインクリメントが必要なときはいつでもrealloc(ptr,size)
于 2012-11-12T20:31:34.600 に答える