为什么这段代码的输出是内存中的一些随机字?
void conc()
{
FILE *source = fopen("c.txt", "r+");
if(!source)
{
printf("Ficheiro não encontrado");
return;
}
short i = 0;
while(fgetc(source) != EOF)
i++;
char tmp_str[i];
fgets(tmp_str, i, source);
fclose(source);
printf("%s", tmp_str);
}
我认为这应该给我文件的内容。
答案 0 :(得分:7)
因为在使用fgetc()
浏览文件后,位置指示符位于文件末尾。 fgets()
没有什么可读的。您需要重置它,使其指向使用rewind(source);
。
顺便说一下,不要使用fgetc()
遍历文件,这是一个非常难看的解决方案。使用fseek()
和ftell()
或lseek()
来获取文件的大小:
fseek(source, SEEK_END, 0);
long size = ftell(source);
fseek(source, SEEK_SET, 0); // or rewind(source);
替代:
off_t size = lseek(source, SEEK_END, 0);
rewind(source);
答案 1 :(得分:1)
在rewind(source);
fgets(tmp_str, i, source);
答案 2 :(得分:0)
在fgetc()
- 循环后,您已达到EOF,如果您没有fseek( source, 0l, SEEK_SET )
回到开头,则不会再获得任何数据。
无论如何,你应该避免两次阅读文件。请改用fstat( fileno(source), ... )
来确定文件大小。
答案 3 :(得分:0)
fgetc从流中读取一个字符。 fgets从流中读取一个字符串。
现在,在您的代码中,您将遍历文件的末尾。因此,对流上的fgets的调用将只返回NULL并保持缓冲区内容不变。在您的情况下,您的缓冲区未初始化。这解释了您看到的随机值。
我没有使用fgetc读取完整的文件内容来获取字符数,而是建议使用fseek / ftell(请参阅此thread的答案)
答案 4 :(得分:0)
你的代码错了。如前所述:
如果您需要代码来阅读文件的内容,请尝试下一步(抱歉,但我没有编译它。无论如何它应该运行良好):
FILE* source = fopen("c.txt", "r+b");
if(!source){return;}
fseek(source, 0, SEEK_END);
size_t filesize = ftell(source);
fseek(source, 0, SEEK_SET);
char* buf = new char[filesize+1]; // +1 is for '/0'
fread(buf, sizeof(char), filesize, source);
fclose(source);
buf[filesize]=0;
printf("%s", buf);
delete buf;
答案 5 :(得分:0)
每次调用fgetc()时,都会使内部文件指针进一步前进一个字符。在while()循环结束时,文件指针将位于文件的末尾。意图读取文件句柄的后续调用将因EOF条件而失败。
fgets手册说:
如果在尝试读取字符时遇到文件结尾,则设置eof指示符(feof)。如果在读取任何字符之前发生这种情况,则返回的指针是空指针(并且str的内容保持不变)。
结果是tmp_str保持不变。调用printf时返回的垃圾实际上是conc()函数堆栈的一部分。
解决问题的方法是在调用fgets()之前用fseek()重写文件指针。
fseek(source, 0, SEEK_SET);
然后获得文件大小的更好方法是fseek到文件末尾,并使用ftell获取当前位置:
long size;
fseek(source, 0, SEEK_END);
size = ftell(source);
话虽如此,您的代码仍有问题。在堆栈上分配(函数本地的变量)时,必须在编译时告诉变量的大小。在这里,您的编译器会分配一个长度为0的char数组。如果您使用C ++进行编码,我建议您使用关键字 new 的 malloc 调查动态分配。
正确的分配如下:
char *tmp_str = malloc(size);
// Here you read the file
free(tmp_str);
更简单的解决方案可能是预分配足够大的字符串来保存文件。
char tmp_str[1024 * 100]; // 100Kb
然后使用我们之前获得的 size 变量来检查文件在读取之前是否适合tmp_str。