从文件中获取字符串

时间:2013-06-27 12:33:26

标签: c string file get

为什么这段代码的输出是内存中的一些随机字?

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

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

6 个答案:

答案 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)

你的代码错了。如前所述:

  1. 你不应该两次阅读文件
  2. 要动态分配数组,必须使用operator new(在c ++中) 或函数malloc(在c中)
  3. 如果您需要代码来阅读文件的内容,请尝试下一步(抱歉,但我没有编译它。无论如何它应该运行良好):

    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。