みなさん、CでBFインタープリターを書いていますが、ファイルの読み取りで問題が発生しました。以前は最初の文字列を読み取るためにscanfを使用していましたが、BFコードにスペースやコメントを含めることはできませんでした。
今ここに私が持っているものがあります。
char *readFile(char *fileName)
{
FILE *file;
char *code = malloc(1000 * sizeof(char));
file = fopen(fileName, "r");
do
{
*code++ = (char)fgetc(file);
} while(*code != EOF);
return code;
}
ファイル内の次の文字をコードポインターに割り当てる方法で問題が発生することは知っていますが、それが何であるかはわかりません。
この演習のポイントであるポインターの知識が不足しています。インタープリターはすべて正常に動作し、すべてポインターを使用していますが、ファイルの読み取りに問題があります。
(後でファイルに「+-> <[]。」を読み込むだけを実装しますが、誰かがそれを行う良い方法を持っているなら、私に知らせてくれれば素晴らしいでしょう!)
前もって感謝します
コードには多くの問題があります:
_char *readFile(char *fileName)
{
FILE *file;
char *code = malloc(1000 * sizeof(char));
file = fopen(fileName, "r");
do
{
*code++ = (char)fgetc(file);
} while(*code != EOF);
return code;
}
_
code
を増やし、呼び出し元にcode
を返します(ただし、メモリブロックの最初のバイトを指すようになった場合でも) malloc
)。fgetc(file)
の結果をchar
にキャストしています。結果をEOF
にキャストする前に、char
を確認する必要があります。後で解放できるように、malloc
によって返された元のポインターを維持することが重要です。ファイルサイズを無視しても、次の方法でこれを実現できます。
_char *readFile(char *fileName)
{
FILE *file = fopen(fileName, "r");
char *code;
size_t n = 0;
int c;
if (file == NULL)
return NULL; //could not open file
code = malloc(1000);
while ((c = fgetc(file)) != EOF)
{
code[n++] = (char) c;
}
// don't forget to terminate with the null character
code[n] = '\0';
return code;
}
_
ファイルのサイズを示すさまざまなシステムコールがあります。一般的なものは stat
です。
@dreamlaxから上記のコードを展開する
char *readFile(char *fileName) {
FILE *file = fopen(fileName, "r");
char *code;
size_t n = 0;
int c;
if (file == NULL) return NULL; //could not open file
fseek(file, 0, SEEK_END);
long f_size = ftell(file);
fseek(file, 0, SEEK_SET);
code = malloc(f_size);
while ((c = fgetc(file)) != EOF) {
code[n++] = (char)c;
}
code[n] = '\0';
return code;
}
これにより、ファイルの長さがわかり、1文字ずつ読み取ることができます。
有効なブレーンファックキャラクター以外のすべてを無視する1つの簡単な方法を次に示します。
#define BF_VALID "+-><[].,"
if (strchr(BF_VALID, c))
code[n++] = c;
ファイルは、関数の呼び出しごとに開かれ、閉じられません
最も重要な問題は、ものを読み込むときにcode
をインクリメントし、code
の最終値を返すことです。つまり、文字列のend。おそらく、ループの前にcode
のコピーを作成し、代わりにそれを返したいでしょう。
また、C文字列はnullで終了する必要があります。読み込む最終文字の直後に_'\0'
_を配置することを確認する必要があります。
注:fgets()
を使用して、1回のヒットで行全体を取得できます。
2つのいずれかがトリックを行う必要があります-
char *readFile(char *fileName)
{
FILE *file;
char *code = malloc(1000 * sizeof(char));
char *p = code;
file = fopen(fileName, "r");
do
{
*p++ = (char)fgetc(file);
} while(*p != EOF);
*p = '\0';
return code;
}
char *readFile(char *fileName)
{
FILE *file;
int i = 0;
char *code = malloc(1000 * sizeof(char));
file = fopen(fileName, "r");
do
{
code[i++] = (char)fgetc(file);
} while(code[i-1] != EOF);
code[i] = '\0'
return code;
}
他のポスターが指摘したように、ファイルサイズが1000文字を超えないようにする必要があります。また、メモリの使用が終わったら、メモリを解放することを忘れないでください。
ここでの問題は2つあります。a)読み込まれた値をチェックする前にポインタをインクリメントし、b)fgetc()がcharではなくintを返すという事実を無視します。
最初の問題は簡単に修正できます。
char *orig = code; // the beginning of the array
// ...
do {
*code = fgetc(file);
} while(*code++ != EOF);
*code = '\0'; // nul-terminate the string
return orig; // don't return a pointer to the end
2番目の問題はさらに微妙です-fgetcは、EOF値が可能なchsr値と区別できるintを返します。これを修正するには、EOF =チェックし、おそらくdo/whileの代わりに通常のwhileループ。