1

割り当てのために、私がしなければならないことの一部には、mallocとの使用が含まれますrealloc。最初に char の 2D 配列を作成します。次元は行数と文字数です。次にmalloc、いくつかのファイルからの入力を格納するのに十分なメモリを割り当てるために使用します。を使用fgetsして、一度に 1 行ずつ読み取り、配列に格納します。この部分はうまく機能します(またはそう思います)。必要に応じてより多くの行にメモリを再割り当てしようとすると、問題が発生します。プログラム フローは次のようになっているはずです。

1 行あたり 80 文字で、50 行の文字配列を作成します (機能)

fgets一度に 1 行ずつ読み取り、配列に保存するために使用します (作業中)。

50行が読み取られたら、配列を再割り当てして100行を許可します(機能しません)

必要に応じて再割り当てを続ける (機能しない)

これは私がこれまでに持っているものです(少なくともその核心、無関係なコードを省略しました):

#define NUMBER_OF_LINES 50
#define CHARACTERS_PER_LINE 80

FILE *inputFile = fopen("some.text", "r");

char **lines;
lines = malloc(NUMBER_OF_LINES * sizeof(*lines));
int i;
for (i = 0; i < NUMBER_OF_LINES; i++)
  *(lines+i) = malloc(CHARACTERS_PER_LINE * sizeof(char));

int linesRemaining = NUMBER_OF_LINES;
int reallocCount = 1;
i = 0;
while (!feof(inputFile)) {
  if (!linesRemaining) {
    reallocCount++;
    lines = realloc(lines, (NUM_OF_LINES * reallocCount) * sizeof(*lines));
    linesRemaining = NUM_OF_LINES;
  }
  fgets(*(lines+i), CHARS_PER_LINE, inputFile);
  i++;
  linesRemaining--;
}

私の直感では、realloc問題.

realloc(lines, (NUM_OF_LINES * reallocCount) * sizeof(*lines));

最初の引数 はlines、一定量のメモリを再割り当てしたいポインタです。NUM_OF_LINESサイズを大きくしたい量です。これに を掛けますreallocLinesCount。これは、必要な 50 行のセット数を追跡​​するカウンターです。部分は、へのsizeof(*lines)ポインターのサイズですchar

読んでいただきありがとうございます。どんな助けでも大歓迎です:)

編集: 返信ありがとうございます。今すぐすべての回答を読む時間はありませんが、この差し迫った締め切りが過ぎれば、すべての回答をより完全に読んで理解することができます :D

4

5 に答える 5

2

私のモットーは「言いたいことを言う」です。あなたの場合、データを保持するのに十分な大きさでないときに配列を拡大することを意味します。

FILE *in;      // you fill this in
int nlines=50; // initial value
char **buffer=malloc(nlines * sizeof *buffer);
int i=0;

for(int i=0; !feof(in); ++i)
{
  if(i>=nlines)
    buffer=realloc(buffer, (nlines+=50)*sizeof *buffer);

  buffer[i]=malloc(80);
  fgets(buffer[i], 80, in);
}
于 2011-04-09T02:55:32.120 に答える
2

realloc()多くの場合、既存のアレイをインプレースで拡張するのに十分なスペースがないことがわかります。その場合、指定されたサイズのまったく新しい配列を作成し、古い配列の内容を新しい配列にコピーし、古い配列の割り当てを解除して、新しい配列へのポインターを返します。だからあなたは書くべきです

char **oldLines = lines;
lines = realloc(...);

(の目的は、@Brian L のヒントによると、メモリが不足して が返されoldLinesた場合に備えて元のポインターを保持することです)。realloc()NULL

于 2011-04-09T02:52:47.947 に答える
1

これは、再割り当てする方法です。

char **new_lines = realloc(lines, (NUM_OF_LINES * ++reallocLinesCount) * sizeof(*lines));
if (new_lines)
{
    lines = new_lines;
}
else
{
    // Memory allocation fails. Do some error handling.
}

詳細については、再割り当てのリファレンスを参照してください。

編集

新しい行ごとに、より多くの割り当てが必要です。

于 2011-04-09T02:54:50.277 に答える
1

より多くのポインターを行に割り当てていますが、行自体には割り当てていません。それは最初のコードにあります:

for (i = 0; i < NUMBER_OF_LINES; i++)
   *(lines+i) = malloc(CHARACTERS_PER_LINE * sizeof(char));

したがって、各行に行数を割り当てた後、行自体にスペースを割り当てます。再割り当てするときに、新しい行に対してこれを行うのを忘れました。

于 2011-04-09T03:09:41.497 に答える
1

まずがどのようにrealloc()機能するかを見てみましょう。 成功時と失敗時に新しいメモリへのポインターを返します。NULL失敗すると、古いメモリには触れず、成功するとfree()、データを新しい場所にコピーした後です。

したがって、realloc()安全に使用する方法は次のとおりです。

/* allocate memory using malloc() */
ptr = malloc(N * sizeof *ptr);
/* make sure malloc succeeded */
...
/* call realloc() */
new_ptr = realloc(ptr, M * sizeof *new_ptr);
/* see if it succeeded */
if (new_ptr) {
    /* okay, we can set ptr */
    ptr = new_ptr;
} else {
    /* realloc failed, old pointer still valid */
}

ですから、まずあなたの使い方がrealloc()間違っているということです。 失敗した場合は に代入し、古い記憶が失われるため、決してと言うべきではありません。これはメモリ リークです。x = realloc(x, ...);realloc()xNULL

さて、あなたの問題に進みましょう。行の読み取りに成功したとしましょう NUMBER_OF_LINES。ここで、行を追加するためのスペースを確保したいと考えています NUMBER_OF_LINES。あなたがするだろう:

char **new_lines = realloc(lines, NUMBER_OF_LINES*reallocCount*sizeof *new_lines);
if (new_lines) {
    lines = new_lines;
} else {
    fprintf(stderr, "realloc failed!\n");
    return;
}

/* Now, lines[NUMBER_OF_LINES] to lines[2*NUMBER_OF_LINES-1] are
 * available to point someplace useful.  They don't point anywhere
 * useful yet.  We have to allocate memory for them, just like earlier */

start = NUMBER_OF_LINES*reallocCount;
for (i=0; i < NUMBER_OF_LINES; ++i) {
    /* You weren't allocating memory here, and were writing to
     * lines[0] through lines[NUMBER_OF_LINES-1], which is not what
     * you want. */
    lines[start+i] = malloc(CHARS_PER_LINE * sizeof *lines[start+i]);
    /* check the result of malloc here */
}
fgets(lines[start+i], CHARS_PER_LINE, inputFile);

最後に 1 つ: ファイルから行を読み取るために使用するのは、ほとんどの場合間違っています。while (!feof(fp))

于 2011-04-09T03:15:18.940 に答える