C中的随机访问函数问题

时间:2010-10-11 17:42:38

标签: c

我正在努力学习C和我正在使用的书(Apress''Learn C')有一章在随机访问功能上非常混乱。以下代码令我困惑:

 int    GetNumberOfDinos( void ) {
    FILE    *fp;
    long    fileLength;

    if ( (fp = fopen( kDinoFileName, "r" )) == NULL )
        DoError( "Couldn't open file...Goodbye!" );

    if ( fseek( fp, 0L, SEEK_END ) != 0 )
        DoError( "Couldn't seek to end of file...Goodbye!" );

    if ( (fileLength = ftell( fp )) == -1L )
        DoError( "ftell() failed...Goodbye!" );

    fclose( fp );

    return( (int)(fileLength / kDinoRecordSize) );
}

我理解代码的目的,但不了解如何实现目的。 fopen系列很容易理解。 fseek和ftell是我的麻烦开始的地方。 fseek的参数是文件,偏移量,然后是3个SEEK中的一个。为什么它的条件不是零呢?如果文件确实存在(kDinoFileName),并且他们想要指向该文件的末尾,为什么该位置为零?文件存在,有信息!然后我完全不明白ftell函数将如何以-1L结束?这段代码比它需要的更难吗?

6 个答案:

答案 0 :(得分:5)

代码只是检查错误。 fseek()成功时返回0,失败时返回非零。失败时ftell()返回-1。

至于“为什么位置为零?” - fseek()调用请求从文件末尾(SEEK_END)进行搜索。文件末尾的零字节是..文件的结尾。所以

fseek( fp, 0L, SEEK_END )

是将文件指针移动到文件末尾的请求。

代码执行以下步骤:

  1. 打开文件
  2. 寻求结束
  3. 获取文件指针的位置(因为我们最后会告诉你文件中有多少字节 - 注意,严格来说,需要使用二进制访问打开文件,例如使用“rb” ,为了这是真的)
  4. 错误处理使代码有些复杂。正是出于这个原因,许多书籍和文章都忽略了错误处理。然而,这有教导人们忽略错误条件的缺点。

答案 1 :(得分:2)

如果存在一些未知错误,例如尝试读取文件的I / O错误,则会发生

-1。您会发现C使用此-1特殊值,因为它没有像更现代语言那样的真正异常机制,所以这只是一种说法,“嘿,这里发生了一些不好的事情。”

有关ftell的更多信息,请参阅here

“如果发生错误,则返回-1L,并将全局变量errno设置为正值。该值可由perror解释。”

答案 2 :(得分:1)

这些条件只是作为一种保护措施,以防发生不良事件。即使您知道该文件存在且所有参数都正确,例如,磁盘也可能出现问题。总是检查错误情况是一种好习惯,这样你就不会盲目地继续只知道出了什么问题。

答案 3 :(得分:0)

Google是你的朋友:

http://www.cplusplus.com/reference/clibrary/cstdio/fseek/

http://www.cplusplus.com/reference/clibrary/cstdio/ftell/

I / O函数具有良好的错误潜力,因此检查返回值是一种很好的做法。

是的,还有POSIX语法,要求fseek()返回新位置而不是错误代码。

答案 4 :(得分:0)

fseek仅返回成功或失败指示,它不返回文件指针结束的位置。成功时返回0,这是许多库函数的标准成功返回。

ftell的情况下,如果文件指针没有错误,它将返回文件指针的当前文件位置,因此在成功时返回0,在失败时返回非零不起作用。因此,ftell函数在发生故障时返回-1。这是返回具有含义的数字的函数的标准错误返回。

如果你看一下,根据我刚给你的信息,代码会在出现错误情况时抱怨某种错误。

答案 5 :(得分:0)

标准C函数的返回值有时可能很奇怪,因为许多函数返回一个具有重要性的int,因此它不能使用相同的int返回值来表示错误。

在ftell的情况下,它返回文件指针的当前偏移量。如果文件指针位于文件的开头,则它位于偏移0.因此0是有效的偏移量,不能用于指示错误。所以他们用-1代替。

fseek是一条指令。它可能会返回无效,但他们决定返回更有意义的东西。通过使用0表示成功而非零表示失败,它们可以返回不同的非零值以指示不同的错误。

顺便提一下,代码是通过到最后然后询问当前位置来计算文件的大小。如果要将文件加载到内存中并且需要知道要分配的字节数,有时会执行此操作。