C语言中的随机存取函数问题
我正在尝试学习C,我正在使用的书(按“学习C”)中有一章关于随机访问函数的内容非常混乱。以下代码让我感到困惑:C语言中的随机存取函数问题,c,C,我正在尝试学习C,我正在使用的书(按“学习C”)中有一章关于随机访问函数的内容非常混乱。以下代码让我感到困惑: int GetNumberOfDinos( void ) { FILE *fp; long fileLength; if ( (fp = fopen( kDinoFileName, "r" )) == NULL ) DoError( "Couldn't open file...Goodbye!" ); if ( f
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的参数是文件、偏移量,然后是3个搜索中的一个。为什么这里的条件不是零?如果文件确实存在(kDinoFileName),并且他们希望指向该文件的结尾,为什么位置为零?该文件存在,并且有信息!然后我完全不明白ftell函数怎么会以-1L?结束??此代码是否比需要的更难?此代码只是检查错误
fseek()
成功时返回0,失败时返回非零ftell()
失败时返回-1
至于“为什么位置为零?”——fseek()
调用正在请求从文件末尾进行搜索(seek\u end
)。文件末尾的零字节为。。文件的结尾。所以
fseek( fp, 0L, SEEK_END )
是将文件指针移动到文件末尾的请求
代码正在执行以下步骤:
由于错误处理,代码有点复杂。正是由于这个原因,许多书籍和文章省略了错误处理。但是,这也有其自身的缺点,即教导人们忽略错误条件。-1如果出现未知错误,例如试图读取文件时出现I/O错误,则可能会发生。你会发现
C
使用了这个-1特殊值,因为它没有像现代语言那样的真正的异常机制,所以这只是说,“嘿,这里发生了一些不好的事情。”
有关ftell的更多信息,请参阅
“如果发生错误,则返回-1L,全局变量errno设置为正值。此值可由perror解释。”谷歌是您的朋友:
I/O函数有很好的潜在错误,因此检查返回值是一种很好的做法
是的,还有POSIX语法,它要求
fseek()
返回新的位置,而不是错误代码。这些条件只是在发生错误时的一种保护措施。例如,即使您知道文件存在并且所有参数都正确,磁盘也可能出现问题。始终检查错误情况是一种很好的做法,这样您就不会盲目地继续,直到很久以后才发现出现了问题。fseek
只返回成功或失败指示,而不会返回文件指针的最终位置。它在成功时返回0
,这是许多库函数的标准成功返回
在ftell
的情况下,如果没有错误,它将返回文件指针的当前文件位置,因此简单地在成功时返回0,在失败时返回非零不起作用。因此,当发生故障时,ftell
函数返回-1
。这是返回有意义数字的函数的标准错误返回
如果你看,当根据我刚才给你的信息出现错误情况时,代码会抱怨某种错误。标准C函数的返回值有时会很奇怪,因为许多函数返回一个有意义的int,因此它不能使用相同的int返回值来指示错误 对于ftell,它返回文件指针的当前偏移量。如果文件指针位于文件的开头,则它位于偏移量0处。因此,0是有效的偏移量,不能用于指示错误。所以他们用-1代替 fseek是一种指令。它可能会返回void,但他们决定返回更有意义的内容。通过使用0表示成功,使用非零表示失败,它们可以返回不同的非零值以指示不同的错误
顺便说一句,代码计算文件大小的方法是转到末尾,然后询问当前位置。如果要将文件加载到内存中,并且需要知道要分配多少字节,则有时会这样做。需要注意的是,如果fseek失败(例如,由于磁盘介质上的读取错误),则无法保证后续ftell()将返回什么。这可能是一个似是而非的数字。如果在fseek()上检测不到错误,可能会导致程序使用错误的文件大小值,而不知道这是假的。@supercat-但如果您查看OP发布的代码,他在调用ftell之前检查fseek的返回值,因此我不确定您的注释“需要注意”的原因。如果fseek失败,对ftell的调用将永远不会出现在他的代码中,因此这确实是一个没有意义的问题。我假设他的DoError函数正在执行某种system.exit调用,或者以其他方式终止程序。