1

私はcでのプログラミングに慣れていないので、配列を作成してから、ファイル内の可変量の変数と、配列内のこれらのファイルを読み取る方法を考えています。

//how do I declare an array whose sizes varies
do {
     char buffer[1000];
     fscanf(file, %[^\n]\n", buffer);
     //how do i add buffer to array
}while(!feof(file)); 
4

4 に答える 4

2
int nlines = 0
char **lines = NULL; /* Array of resulting lines */
int curline = 0;
char buffer[BUFSIZ]; /* Just alloocate this once, not each time through the loop */
do {
     if (fgets(buffer, sizeof buffer, file)) { /* fgets() is the easy way to read a line */
       if (curline >= nlines) { /* Have we filled up the result array? */
         nlines += 1000; /* Increase size by 1,000 */
         lines = realloc(lines, nlines*sizeof(*lines); /* And grow the array */
       }
       lines[curline] = strdup(buffer); /* Make a copy of the input line and add it to the array */
       curline++;
     }
}while(!feof(file)); 
于 2012-10-23T02:52:33.887 に答える
1

Cでは、配列は常に固定サイズです。サイズを変更することはできません。できることは、事前に必要なスペースの量を見積もり、そのスペースを動的に(を使用してmalloc())割り当てることです。スペースが足りなくなった場合は、再割り当てします。そのためのドキュメントを参照してくださいrealloc()。基本的に、あなたはします:

buffer = realloc(size);

新しいサイズは、以前のサイズよりも大きくしたり小さくしたりできます(つまり、配列を「拡大」または「縮小」できます)。したがって、最初に5000文字のスペースが必要な場合は、次のようにします。

char* buffer = malloc(5000);

後でスペースが不足し、さらに2000文字が必要な場合(新しいサイズは7000になります)、次のようにします。

buffer = realloc(7000);

の既存のコンテンツbufferは保持されます。realloc()メモリブロックを実際に拡張できない可能性があるため、最初に完全に新しいブロックを割り当て、次に古いメモリの内容を新しいブロックにコピーしてから、古いメモリを解放する可能性があることに注意してください。つまり、bufferポインタのコピーを別の場所に保存すると、もう存在しない古いメモリブロックを指すことになります。例えば:

char* ptr = buffer;
buffer = realloc(7000);

その時点で、ptrが有効である場合にのみ有効ですがptr == buffer、これが当てはまるとは限りません。

于 2012-10-23T02:24:18.060 に答える
0

文字列データが配列エントリにある配列は、通常、最適ではありません。データの完全なセットがメモリに快適に収まり、エントリ数に妥当な上限がある場合は、ポインタ配列が1つの選択肢です。

ただし、最初に、明示的な長さのないscanf%sおよび%[]形式は避けてください。例のバッファサイズ1000を使用すると、読み取ることができる最大文字列長は999なので、次のようになります。

/* Some needed data */
int n;
struct ptrarray_t
{
    char **strings;
    int  nalloc; /* number of string pointers allocated */
    int  nused;  /* number of string pointers used */
} pa_hdr; /* presume this was initialized previously */
...
n = fscanf(file, "%999[\n]", buffer);
if (n!=1 || getc(file)!='\n')
{
    there's a problem
}
/* Now add a string to the array */
if (pa_hdr.nused < pa_hdr.nalloc)
{
    int len = strlen(buffer);
    char *cp = malloc(len+1);
    strcpy(cp, buffer);
    pa_hdr.strings[pa_hdr.nused++] = cp;
}

以降の任意の文字列への参照はpa_hdr.strings[i]であり、適切な設計では、関数呼び出しまたはマクロを使用してヘッダーを管理します。ヘッダーは、インラインではなくヘッダーファイルに含まれます。配列を使い終わったら、malloc()されたすべてのポインターを解放するdelete関数が必要になります。

小さな文字列が多数ある場合、malloc()は時間とスペースの両方のオーバーヘッドでコストがかかる可能性があります。ホストOSのメモリ割り当てとページングとうまく連携する大きなブロックで文字列のプールを管理する場合があります。関数のセットを使用して、この文字列配列からオブジェクトを効果的に作成すると、開発に役立ちます。上記のように単純な戦略を選択し、後で実装を最適化することができます。

于 2012-10-23T03:25:06.240 に答える
0

改行を読むまで読み込もうとしているようです。

これを行う最も簡単な方法は、getlineを使用することです。

char *buffer = NULL;
int buffer_len;
int ret = getline(&buffer, &buffer_len, file);

...これにより、ファイルから1行のテキストが読み取られますfile(エラーret-1ある場合、またはファイルの最後にいる場合を除く)。

于 2012-10-23T02:12:43.303 に答える