在C中逐个字符地读取文件
大家好,我正在用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; }
- 如果文件大于1,000字节怎么办?
- 每次读取字符时都会增加
code
,并将code
返回给调用者(即使它不再指向内存块的第一个字节,因为它是由malloc
返回的)。 - 您正在将
fgetc(file)
的结果转换为char
。 在将结果转换为char
之前,您需要检查EOF
。
保持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; }
这将为您提供文件的长度,然后逐个字符地读取它。
我认为最重要的问题是你在读取内容时递增code
,然后返回code
的最终值,即你将返回一个指向字符串末尾的指针。 您可能希望在循环之前复制code
,然后返回该code
。
此外,C字符串需要以空值终止。 您需要确保在读入的最后一个字符后直接放置'\0'
。
注意:您可以使用fgets()
在一次点击中获取整行。
这里有一个简单的方法来忽略除了有效的brainfuck字符之外的所有东西:
#define BF_VALID "+-><[].," if (strchr(BF_VALID, c)) code[n++] = c;
文件正在打开,并且每次调用该函数时也不会关闭
这两个中的任何一个应该做的 –
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个字符。 此外,请记住在使用完内存后释放内存。
这里的问题是双重的 – 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。