この問題にアプローチする多くの方法があります。静的な2D配列またはchar(例:char lines[40][50] = {{""}};
)を宣言するか、またはという型の配列char [50]へのポインタを宣言します。これはおそらく動的割り当てにとって最も簡単です。そのアプローチでは、1つの割り当てだけが必要です。定数MAXL = 40
とMAXC = 50
で、あなたは単に必要があります:あなたが行われてい
while (i < MAXL && fgets (lines[i], MAXC, fp)) {...
は、すべてを行う必要が駒を置くfree (lines);
です:fgets
各ラインを読む
は
char (*lines)[MAXC] = NULL;
...
lines = malloc (MAXL * sizeof *lines);
の簡単な作業です
#include <stdio.h>
#include <stdlib.h>
enum { MAXL = 40, MAXC = 50 };
int main (int argc, char **argv) {
char (*lines)[MAXC] = NULL; /* pointer to array of type char [MAXC] */
int i, n = 0;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* valdiate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
if (!(lines = malloc (MAXL * sizeof *lines))) { /* allocate MAXL arrays */
fprintf (stderr, "error: virtual memory exhausted 'lines'.\n");
return 1;
}
while (n < MAXL && fgets (lines[n], MAXC, fp)) { /* read each line */
char *p = lines[n]; /* assign pointer */
for (; *p && *p != '\n'; p++) {} /* find 1st '\n' */
*p = 0, n++; /* nul-termiante */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
/* print lines */
for (i = 0; i < n; i++) printf (" line[%2d] : '%s'\n", i + 1, lines[i]);
free (lines); /* free allocated memory */
return 0;
}
注:一緒に、あなたのような何かを行うことができますます毎回fgets
で行全体が読み取られたかどうかを確認する必要があります。 (ファイル内に38文字以上の長い行があるとします)。 ヌル終了の文字で上書きする前に、*p
が'\n'
であるかどうかをチェックすることによって行います。 (例えば、if (*p != '\n') { int c; while ((c = getchar()) != '\n' && c != EOF) {} }
)。これにより、現在の行の残りの文字ではなく、次の行がfgets
で始まることが保証されます。(: Iが読み取りループ以下n = i;
を割り当てるための必要性を排除するためにn
にi
からの読み出しループカウンタを変更注)
は、次のような何かを行うことができ、チェックを含めます。 while (n < MAXL && fgets (lines[n], MAXC, fp)) { /* read each line */
char *p = lines[n]; /* assign pointer */
for (; *p && *p != '\n'; p++) {} /* find 1st '\n' */
if (*p != '\n') { /* check line read */
int c; /* discard remainder of line with getchar */
while ((c = fgetc (fp)) != '\n' && c != EOF) {}
}
*p = 0, n++; /* nul-termiante */
}
残りの行を破棄しても、配列の長さを超えて残すかはあなた次第です。ただし、常にチェックすることをお勧めします。 (私の例入力中のテキストの行は、長い行の可能性がなかったので、下記の17文字に制限されていますが、一般的に行の長さを保証することはできません。
例入力
$ cat dat/40lines.txt
line of text - 1
line of text - 2
line of text - 3
line of text - 4
line of text - 5
line of text - 6
...
line of text - 38
line of text - 39
line of text - 40
使用例/出力
$ ./bin/fgets_ptr2array <dat/40lines.txt
line[ 1] : 'line of text - 1'
line[ 2] : 'line of text - 2'
line[ 3] : 'line of text - 3'
line[ 4] : 'line of text - 4'
line[ 5] : 'line of text - 5'
line[ 6] : 'line of text - 6'
...
line[38] : 'line of text - 38'
line[39] : 'line of text - 39'
line[40] : 'line of text - 40'
は今例えば、コードの長さのチェックが含まれており、入力に長い行を追加します。
$ cat dat/40lines+long.txt
line of text - 1
line of text - 2
line of text - 3 + 123456789 123456789 123456789 123456789 65->|
line of text - 4
...
プログラムを再実行すると、ファイル内の長い行から保護されていることを確認できます。動的にあなたがあなたのファイルの行数が不明があり、lines
に40
のあなたの最初の割り当てに達した場合、その後、あなたは追加の行を読み続けるために行う必要があるすべてがあるlines
の再割り当て
realloc
lines
のストレージ。例えば:あなたのファイルにありますどのように多くの行にそれを問題ではありませんあなたの全体のファイルが読み込まれるまで
int i, n = 0, maxl = MAXL;
...
while (fgets (lines[n], MAXC, fp)) { /* read each line */
char *p = lines[n]; /* assign pointer */
for (; *p && *p != '\n'; p++) {} /* find 1st '\n' */
*p = 0; /* nul-termiante */
if (++n == maxl) { /* if limit reached, realloc lines */
void *tmp = realloc (lines, 2 * maxl * sizeof *lines);
if (!tmp) { /* validate realloc succeeded */
fprintf (stderr, "error: realloc - virtual memory exhausted.\n");
break; /* on failure, exit with existing data */
}
lines = tmp; /* assign reallocated block to lines */
maxl *= 2; /* update maxl to reflect new size */
}
}
は今、あなたは単にlines
を再割り当て続けるか、メモリが不足します。 (注:現在のコードは2回再配分のlines
の現在のメモリを再割り当てあなたが同じくらいか、あなたが好きなように少しを追加するのは自由ですたとえば、あなたは、単に40
複数行毎の時間を割り当てることmaxl + 40
を割り当てることができ
。。。 例入力
$ cat dat/80lines.txt
line of text - 1
line of text - 2
...
line of text - 79
line of text - 80
使用例/出力
$ ./bin/fgets_ptr2array_realloc <dat/80lines.txt
line[ 1] : 'line of text - 1'
line[ 2] : 'line of text - 2'
...
line[79] : 'line of text - 79'
line[80] : 'line of text - 80'
質問がある場合はそれを見て、私に知らせてください。
ポインタ配列自体のメモリを 'malloc'で割り当てます。上限に達すると、' realloc'でそれを拡張し、制限を更新します... –
私たちはこれに対して在庫がありますか?それは約尋ねられる。 3x /日。 –
@kata aside: 'fgets'は、' line'の最後に 'newline'を入力したままにしておいてください。 –