私はそれらを処理している間にバッファに読み込む小さなテキストファイルを扱っているので、次のコードを思いつきました:
_...
char source[1000000];
FILE *fp = fopen("TheFile.txt", "r");
if(fp != NULL)
{
while((symbol = getc(fp)) != EOF)
{
strcat(source, &symbol);
}
fclose(fp);
}
...
_
これはファイルの内容をバッファに入れる正しい方法ですか?strcat()
を悪用していますか?
次に、バッファーを次のように繰り返します。
_for(int x = 0; (c = source[x]) != '\0'; x++)
{
//Process chars
}
_
_char source[1000000];
FILE *fp = fopen("TheFile.txt", "r");
if(fp != NULL)
{
while((symbol = getc(fp)) != EOF)
{
strcat(source, &symbol);
}
fclose(fp);
}
_
このコードにはいくつかの問題があります。
sizeof(source)
を超えている場合、これはバッファオーバーフローの傾向があります。
strcat()
関数は、nullで終わる文字列s2のコピーをnullで終わる文字列s1の末尾に追加してから、終了する `\ 0 'を追加します。
NULで終了する場合もしない場合もある文字列に文字(NULで終了する文字列ではありません!)を追加しています。 のみ時間は、ファイル内のすべての文字がNULで終了している場合、マンページの説明に従って動作すると想像できます。その場合、これはかなり無意味です。はい、これは間違いなくstrcat()
のひどい乱用です。
代わりに使用することを検討する2つの選択肢を次に示します。
事前に最大バッファサイズがわかっている場合:
_#include <stdio.h>
#define MAXBUFLEN 1000000
char source[MAXBUFLEN + 1];
FILE *fp = fopen("foo.txt", "r");
if (fp != NULL) {
size_t newLen = fread(source, sizeof(char), MAXBUFLEN, fp);
if ( ferror( fp ) != 0 ) {
fputs("Error reading file", stderr);
} else {
source[newLen++] = '\0'; /* Just to be safe. */
}
fclose(fp);
}
_
または、そうしない場合:
_#include <stdio.h>
#include <stdlib.h>
char *source = NULL;
FILE *fp = fopen("foo.txt", "r");
if (fp != NULL) {
/* Go to the end of the file. */
if (fseek(fp, 0L, SEEK_END) == 0) {
/* Get the size of the file. */
long bufsize = ftell(fp);
if (bufsize == -1) { /* Error */ }
/* Allocate our buffer to that size. */
source = malloc(sizeof(char) * (bufsize + 1));
/* Go back to the start of the file. */
if (fseek(fp, 0L, SEEK_SET) != 0) { /* Error */ }
/* Read the entire file into memory. */
size_t newLen = fread(source, sizeof(char), bufsize, fp);
if ( ferror( fp ) != 0 ) {
fputs("Error reading file", stderr);
} else {
source[newLen++] = '\0'; /* Just to be safe. */
}
}
fclose(fp);
}
free(source); /* Don't forget to call free() later! */
_
はい-恐らくstrcatのひどい乱用で逮捕されるでしょう!
Getline()を見てください。一度に1行ずつデータを読み取りますが、重要なことは、読み取る文字数を制限できるため、バッファがオーバーフローしないようにします。
Strcatは、文字を挿入するたびに文字列全体を検索する必要があるため、比較的低速です。通常、文字列ストレージの現在の末尾へのポインターを保持し、次の行を読み込む位置としてgetlineに渡します。
strcat
を使用したくない理由については、 JoelOnSoftwareのこの記事 を参照してください。
fread を参照してください。バイトまたは文字を読み取る場合、サイズに1を指定して使用します。
持っている文字の配列だけを使用してみませんか?これはそれを行うべきです:
source[i] = getc(fp);
i++;
Linuxシステムを使用している場合、ファイル記述子を取得すると、fstat()を使用してファイルに関する多くの情報を取得できます。
http://linux.die.net/man/2/stat
あなたは持っているかもしれない
#include <unistd.h>
void main()
{
struct stat stat;
int fd;
//get file descriptor
fstat(fd, &stat);
//the size of the file is now in stat.st_size
}
これにより、ファイルの先頭と末尾を探す必要がなくなります。
テストはされていませんが、動作するはずです。そして、はい、freadを使用することでより適切に実装できます。読者への演習として残しておきます。
#define DEFAULT_SIZE 100
#define STEP_SIZE 100
char *buffer[DEFAULT_SIZE];
size_t buffer_sz=DEFAULT_SIZE;
size_t i=0;
while(!feof(fp)){
buffer[i]=fgetc(fp);
i++;
if(i>=buffer_sz){
buffer_sz+=STEP_SIZE;
void *tmp=buffer;
buffer=realloc(buffer,buffer_sz);
if(buffer==null){ free(tmp); exit(1);} //ensure we don't have a memory leak
}
}
buffer[i]=0;