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);
}

我认为这应该给我文件的内容。

4

6 回答 6

7

因为在您使用 浏览文件fgetc()后,位置指示器位于文件末尾。fgets()没有什么可读的。您需要重置它,使其指向使用rewind(source);.

顺便说一句,不要使用 遍历文件fgetc(),这是一个非常丑陋的解决方案。使用fseek()andftell()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);
于 2013-06-27T12:35:34.000 回答
1

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

于 2013-06-27T12:38:18.033 回答
0

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

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

我建议不要使用 fgetc 读取完整的文件内容来获取字符数,而是使用 fseek / ftell (请参阅此线程的答案)

于 2013-06-27T12:46:11.643 回答
0

Your code is wrong. As was said before:

  1. You should not read file twice
  2. To allocate array dynamically you must use operator new (in c++) or function malloc (in c)

If you need code to read content of the file, try next (sorry, but I didn't compile it. anyway it should work well):

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;
于 2013-06-27T12:56:05.987 回答
0

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

于 2013-06-27T12:37:35.853 回答
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

然后使用我们之前得到的大小变量在读取之前检查文件是否适合 tmp_str。

于 2013-06-27T13:02:43.183 回答