C语言 ftell()函数是如何工作的?

euoag5mw  于 2023-04-11  发布在  其他
关注(0)|答案(2)|浏览(138)

我有这个代码,我不明白它是如何工作的:

void print(char * fileName)
{
    FILE * fp;
    int ch;
    fp = fopen(fileName, "r");
    while (ftell(fp) < 20)
    {
        ch = fgetc(fp);
        putchar(ch);
    }
    fclose(fp);
}

ftell(fp)在循环中是如何工作的?因为循环中没有任何东西可以启动它。它是如何渐进的?

llycmphe

llycmphe1#

ftell()获取流的位置指示符的当前值(在您的示例中,它基本上返回当前指向的字符位置)。
fgetc()从指定的流中获取下一个字符(无符号字符),并前进流的位置指示符。此函数在文件结束或错误时将读取的字符作为无符号字符转换为int或EOF

您的程序流程

简单来说就是-

  • fgetc()从文件中阅读一个字符后,将指针推进到下一个字符。
  • ftell()返回当前位置,以字节为单位,从文件的开头开始。这意味着它告诉了它现在所指向的字符的位置(因为1个字符占用1个字节)。
  • 因此,您的程序从文件中读取,直到ftell()返回小于20的位置。这意味着它将继续循环,直到从文件中读取了20个字符

希望这能消除你的疑虑!

ohtdti5x

ohtdti5x2#

ftell返回文件位置指示符的当前值,并且fgetc在循环内推进文件位置指示符。
但是这个程序是错误的。对于以文本模式打开的流("r"),ftell的返回值不能用于除查找到前一个位置之外的任何其他操作。来自C11草案n1570 7.21.9.4p2
[...]对于文本流,其文件位置指示符包含未指定的信息,fseek函数可使用该信息将流的文件位置指示符返回到ftell调用时的位置;两个这样的返回值之间的差不一定是写入或读取的字符数的有意义的度量。
实际上,在这个程序中使用ftell没有任何意义。要么以二进制模式打开文件,"rb",然后保证
[...]该值是从文件开始的字符数。
或者为了计算从 text file 读取的 characters,使用一个counter变量:

int c_read = 0;
while (c_read < 20)
{
    ch = fgetc(fp);
    putchar(ch);
    c_read ++;
}

最后,如果文件的字符数 * 小于20个 *,那么无论是你的原始版本还是我的版本都不能正常工作。在这种情况下,fgetc返回EOFputchar将把(unsigned char)EOF写入流(很可能是一个值为255的字节!)
因此正确的代码应该是

int c_read = 0;
while (c_read < 20)
{
    ch = fgetc(fp);
    if (ch == EOF) {
        // report the error
        perror("Failed to read 20 characters");
        break;
    }
    putchar(ch);
    c_read ++;
}

相关问题