在C中逐个字符地读取文件

时间:2011-01-27 23:27:07

标签: c file-io io iostream

嘿大家,我正在用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;
}

我知道问题出现在我如何将文件中的下一个字符分配给代码指针但是我不确定那是什么。
我的指针知识缺乏,这是本练习的重点。 解释器工作正常,都使用指针,我只是在读取文件时遇到问题。

(我稍后只会在文件中读取“+ - >< []。”,但是如果有人有好的方法,那么如果你让我这么做会很棒知道!)

提前致谢

7 个答案:

答案 0 :(得分:35)

您的代码存在许多问题:

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;
}
  1. 如果文件大于1,000字节怎么办?
  2. 每次读取一个字符时,您都在增加code,并将code返回给调用者(即使它不再指向内存块的第一个字节,因为它已返回malloc)。
  3. 您正在将fgetc(file)的结果投射到char。在将结果投射到EOF之前,您需要检查char
  4. 保持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

答案 1 :(得分:8)

扩展@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;
}

这将为您提供文件的长度,然后逐个字符地读取它。

答案 2 :(得分:2)

我认为最重要的问题是你在读取内容时递增code,然后返回code的最终值,即你将返回一个指针< em>结束字符串。你可能想在循环之前复制code,然后返回它。

此外,C字符串需要以空值终止。您需要确保在您阅读的最后一个字符后直接放置'\0'

注意:您可以使用fgets()一次性获取整行。

答案 3 :(得分:2)

这是一种简单的方法来忽略除了有效的脑筋字符之外的所有内容:

#define BF_VALID "+-><[].,"

if (strchr(BF_VALID, c))
    code[n++] = c;

答案 4 :(得分:2)

文件正在打开,并且每次调用该函数时都不会关闭

答案 5 :(得分:1)

两者中的任何一个都应该做到 -

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个字符。此外,请记住在使用完毕后释放内存。

答案 6 :(得分:1)

这里的问题有两个 - 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,即可以将EOF值与任何可能的chsr值区分开来。修复它使用临时int进行EOF检查,可能是常规while循环而不是do / while。