一般的に、あなたはあなたの関数にメモリmax
の現在の割り当てにFILE *
ポインタ、array
、index
へのポインタ、ポインタを渡すことになるでしょう。あなたの関数がファイルから配列に値を読み取ることができるように、現在の割り振りサイズと比較するために現在のインデックスの数を保持します。値の数が現在の割り振りを超えた場合はrealloc
になります。最後に、あなたのindex
とあなたmax
割り当ての両方にポインタを使用しての仮想により、いずれかへの変更は、一般的にmain()
これらの短い例のために(バックあなたの呼び出し元の関数ですぐに利用できます。
が一緒にすべてのそれらの作品を置く、あなたが行うことができます以下のようなもの:
/* read array of unknown size int 'a' from 'fp' */
int *readarr (FILE *fp, int *a, size_t *idx, size_t *max)
{
int tmp;
if (!a) /* if a not allocated -- allocate/validate */
if (!(a = calloc (1, *max * sizeof *a))) {
fprintf (stderr, "readarr() virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
while (fscanf (fp, " %d", &tmp) == 1) { /* for each int in file */
if (*idx == *max) { /* check idx and max */
void *ap = realloc (a, 2 * *max * sizeof *a); /* realloc */
if (!ap) { /* validate realloc success */
fprintf (stderr, "realloc() error: memory exhausted.\n");
break; /* if failure, return with exising data */
}
a = ap; /* assign new mem block, zero new mem */
memset (ap + *max * sizeof *a, 0, *max * sizeof *a);
*max *= 2; /* update allocation size */
}
a[(*idx)++] = tmp; /* add int to array, update index */
}
return a; /* return array */
}
(注:機能は、必要に応じて再割り当て/割り当てられた配列、またはNULL
を受け入れ、割り当てられますしかし、あなたの配列a
の値が原因に静的に宣言された配列にすることはできません。に電話するが発生します。さらに、array
に関数からの戻り値をmain()
に割り当てる必要があります。 'a'
はそもそもNULL
ある、またはrealloc
が発生した場合、新しいポインタアドレスが返された場合。)
realloc
後に新しいメモリをゼロに必須ではありませんが、それはあなた場合は初期化されていない値からの不用意な読み取りを防ぐことができます後で最後に格納された値のインデックスよりも大きいインデックスで配列を反復処理します。
また、現在の再割り当てスキームは、realloc
を呼び出すたびにメモリ量を2倍にします。必要に応じて少しずつ追加するか、または必要なだけ追加するかを選択できます。それと
、短い例では、すべて一緒にそれを置くことが考えられます。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXI 64
int *readarr (FILE *fp, int *a, size_t *idx, size_t *max);
int main (int argc, char **argv) {
int *array = NULL; /* pointer to array */
size_t i = 0, n = 0, maxi = MAXI; /* index, initial elements */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* valildate file pointer */
fprintf (stderr, "error: file open failed. '%s'\n",
argc > 1 ? argv[1] : "stdin");
return 1;
}
array = readarr (fp, array, &n, &maxi); /* read values from file */
if (fp != stdin) fclose (fp); /* close file */
for (i = 0; i < n; i++) /* print array */
printf (" array[%3zu] : %d\n", i, array[i]);
free (array); /* free memory */
return 0;
}
/* read array of unknown size int 'a' from 'fp' */
int *readarr (FILE *fp, int *a, size_t *idx, size_t *max)
{
int tmp;
if (!a) /* if a not allocated -- allocate/validate */
if (!(a = calloc (1, *max * sizeof *a))) {
fprintf (stderr, "readarr() virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
while (fscanf (fp, " %d", &tmp) == 1) { /* for each int in file */
if (*idx == *max) { /* check idx and max */
void *ap = realloc (a, 2 * *max * sizeof *a); /* realloc */
if (!ap) { /* validate realloc success */
fprintf (stderr, "realloc() error: memory exhausted.\n");
break; /* if failure, return with exising data */
}
a = ap; /* assign new mem block, zero new mem */
memset (ap + *max * sizeof *a, 0, *max * sizeof *a);
*max *= 2; /* update allocation size */
}
a[(*idx)++] = tmp; /* add int to array, update index */
}
return a; /* return array */
}
例入力100のInt
$ cat dat/100int.txt
27086
29317
32736
...
16892
8270
6444
使用例/出力
$ ./bin/fscanf_array_dyn dat/100int.txt
array[ 0] : 27086
array[ 1] : 29317
array[ 2] : 32736
array[ 3] : 3356
...
array[ 97] : 16892
array[ 98] : 8270
array[ 99] : 6444
メモリエラーチェック
メモリに動的に割り当てられるコードでは、割り当てられたメモリブロックに関する2つの責任があります。(1)常にメモリブロックの開始アドレスへのポインタを保持するので、 )、不要になったときに解放することができます。
メモリエラーチェックプログラムを使用して、割り振られたメモリブロックの外側または外側に書き込まれていないことを確認し、初期化されていない値の読み込みまたはベースを試み、最後に解放したことを確認することが不可欠ですあなたが割り当てたすべてのメモリ。
Linuxの場合valgrind
が通常の選択です。新しいメモリブロックを誤用する方法はたくさんあります。メモリエラーチェッカーを使用すると、問題を特定して、segfault
を介して問題を発見するのではなく、割り当てたメモリの適切な使用を検証できます。すべてのプラットフォームに同様のメモリチェッカーがあります。それらはすべて使いやすく、プログラムを実行するだけです。
$ valgrind ./bin/fscanf_array_dyn dat/100int.txt
==7273== Memcheck, a memory error detector
==7273== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7273== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==7273== Command: ./bin/fscanf_array_dyn dat/100int.txt
==7273==
array[ 0] : 27086
array[ 1] : 29317
array[ 2] : 32736
...
array[ 97] : 16892
array[ 98] : 8270
array[ 99] : 6444
==7273==
==7273== HEAP SUMMARY:
==7273== in use at exit: 0 bytes in 0 blocks
==7273== total heap usage: 3 allocs, 3 frees, 1,336 bytes allocated
==7273==
==7273== All heap blocks were freed -- no leaks are possible
==7273==
==7273== For counts of detected and suppressed errors, rerun with: -v
==7273== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
必ず確認すべてのヒープブロックが解放された - 何の漏れがERROR概要可能と同様に重要ではない:0エラーを0コンテキストから。
ご質問がありましたら教えてください。メモリの基本的な割り当てと解放は、Cの多くの基礎となります。コードを完全に理解するために時間をとってから、後であなたの机に頭を打つのが良いでしょう...あなたのコーディングで幸運を祈る。
いいですね。それは動作しますか? –
あなたは何か間違っているという印象を与えますか?それは完全にうまくいくようです。 – Dolda2000
ファイル内の整数の数をstatで得ることができます。そうすれば、より多くの/ mallocの部屋で240以上の整数を読み取ることができます。 'struct stat st;のようなものです。 stat(ファイル名:&st); int numOfIntegers = st.st_size; ' – Turtle