Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的随机存取函数问题_C - Fatal编程技术网

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

我正在尝试学习C,我正在使用的书(按“学习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的参数是文件、偏移量,然后是3个搜索中的一个。为什么这里的条件不是零?如果文件确实存在(kDinoFileName),并且他们希望指向该文件的结尾,为什么位置为零?该文件存在,并且有信息!然后我完全不明白ftell函数怎么会以-1L?结束??此代码是否比需要的更难?

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

至于“为什么位置为零?”——
fseek()
调用正在请求从文件末尾进行搜索(
seek\u end
)。文件末尾的零字节为。。文件的结尾。所以

fseek( fp, 0L, SEEK_END )
是将文件指针移动到文件末尾的请求

代码正在执行以下步骤:

  • 打开文件
  • 穷尽
  • 获取文件指针的位置(由于我们在末尾,它会告诉您文件中有多少字节-注意,严格来说,文件需要使用二进制访问打开,例如使用“rb”,才能实现此目的)

  • 由于错误处理,代码有点复杂。正是由于这个原因,许多书籍和文章省略了错误处理。但是,这也有其自身的缺点,即教导人们忽略错误条件。

    -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调用,或者以其他方式终止程序。