我正在努力学习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结束?这段代码比它需要的更难吗?
答案 0 :(得分:5)
代码只是检查错误。 fseek()
成功时返回0,失败时返回非零。失败时ftell()
返回-1。
至于“为什么位置为零?” - fseek()
调用请求从文件末尾(SEEK_END
)进行搜索。文件末尾的零字节是..文件的结尾。所以
fseek( fp, 0L, SEEK_END )
是将文件指针移动到文件末尾的请求。
代码执行以下步骤:
错误处理使代码有些复杂。正是出于这个原因,许多书籍和文章都忽略了错误处理。然而,这有教导人们忽略错误条件的缺点。
答案 1 :(得分:2)
-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表示成功而非零表示失败,它们可以返回不同的非零值以指示不同的错误。
顺便提一下,代码是通过到最后然后询问当前位置来计算文件的大小。如果要将文件加载到内存中并且需要知道要分配的字节数,有时会执行此操作。