Подтвердить что ты не робот

Чтение символа файла символом в 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 в файле указателю кода, но я просто не уверен, что это такое.
Знаний моего указателя не хватает, что является точкой этого упражнения. Интерпретатор отлично работает, все используют указатели, у меня просто проблема с чтением файлов.

(Я собираюсь реализовать только чтение "+ → < [].," в файл позже, хотя, если у кого есть хороший способ сделать это, было бы здорово, если бы вы сообщили мне!)

Заранее спасибо

4b9b3361

Ответ 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.