Чтение символа файла символом в C
Привет всем, я пишу интерпретатор BF в C, и я столкнулся с проблемой чтения файлов. Раньше я использовал 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 в файле указателю кода, но я просто не уверен, что это такое.
Знаний моего указателя не хватает, что является точкой этого упражнения.
Интерпретатор отлично работает, все используют указатели, у меня просто проблема с чтением файлов.
(Я собираюсь реализовать только чтение "+ → < [].," в файл позже, хотя, если у кого есть хороший способ сделать это, было бы здорово, если бы вы сообщили мне!)
Заранее спасибо
Ответы
Ответ 1
В коде есть несколько ошибок:
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;
}
- Что делать, если файл больше 1000 байтов?
- Вы увеличиваете
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
.
Ответ 2
Развернутый выше код из @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;
}
Это даст вам длину файла, затем продолжит читать его по символу.
Ответ 3
Я думаю, что самая значительная проблема заключается в том, что вы увеличиваете code
при чтении файла, а затем возвращаете окончательное значение code
, то есть вы возвращаете указатель на конец строки. Вероятно, вы захотите сделать копию code
перед циклом и вместо этого вернете.
Кроме того, строки C должны быть завершены с нулевой отметкой. Вы должны убедиться, что вы поместите '\0'
непосредственно после последнего символа, который вы читаете.
Примечание.. Вы можете просто использовать fgets()
, чтобы получить всю строку за один удар.
Ответ 4
Вот один простой способ игнорировать все, кроме действительных символов мозгового мозга:
#define BF_VALID "+-><[].,"
if (strchr(BF_VALID, c))
code[n++] = c;
Ответ 5
файл открывается и не закрывается для каждого вызова функции также
Ответ 6
Любой из двух должен сделать трюк -
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 символов. Кроме того, не забудьте освободить память, когда вы закончите использовать ее.
Ответ 7
Проблема здесь двоякая: a) вы увеличиваете указатель до того, как вы проверите значение, считанное, и b) вы проигнорируете тот факт, что fgetc() возвращает int вместо char.
Первое легко фиксируется:
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
Вторая проблема более тонкая - fgetc возвращает int sonthat значение EOF можно отличить от любого возможного значения chsr. Для этого используется временный int для проверки EOF и, вероятно, регулярный цикл while вместо do/while.