2013-06-27 123 views
1

为什么此代码的输出是内存中的一些随机字?从文件中获取字符串

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

你编译了你的应用程序吗? –

+0

是你的'while'循环吗? – Bill

回答

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); 
+0

哦!那些小(BIG)的东西......非常感谢你,先生! –

+2

@TelmoVaz不客气。顺便说一句,不要循环遍历文件两次,而是使用'ftell()'。 – 2013-06-27 12:39:11

+1

+1。 – 0decimal0

0

fgetc()后 - 环已达到EOF,如果你不fseek(source, 0l, SEEK_SET)回开始你将不会获得更多的数据。 无论如何,你应该避免两次阅读文件。改用fstat(fileno(source), ...)来确定文件大小。

1

使用rewind(source);fgets(tmp_str, i, source);

0

龟etc从流中读取一个字符。 fgets从流中读取一个字符串。

现在在您的代码中,您正在迭代文件的末尾。因此,对流上fgets的调用将简单地返回NULL并保持缓冲区内容不变。在你的情况下,你的缓冲区不会被初始化。这解释了你所看到的随机值。

而不是阅读与龟etc完整的文件内容,以获得字符数,我建议使用FSEEK/FTELL(查看从此thread答案)

0

你的代码是错误的。正如之前所说:

  1. 你不应该读文件两次
  2. 要分配阵列动态如果您需要您必须使用new操作符(在C++) 或函数malloc(C语言)

代码读取文件内容,尝试下(很抱歉,但我没有编译它无论如何它应该很好地工作。):

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; 
0

每次调用龟etc(时间)你提前内部文件指针再一个字符。在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的字符数组。我建议你调查动态分配malloc关键字如果你使用C++编码。

一个适当的分配是这样的:

char *tmp_str = malloc(size); 
// Here you read the file 
free(tmp_str); 

一个简单的解决方案可能是预先分配的字符串大到足以容纳你的文件。

char tmp_str[1024 * 100]; // 100Kb 

然后使用大小变量我们早点起床来检查文件将适合tmp_str读数。