2.fseek函数的用法


C语言lseek()函数:移动文件的读写位置

头文件:

1
#include <sys/types.h>  #include <unistd.h>

定义函数:

1
off_t lseek( int  fildes, off_t offset,  int  whence);

函数说明:
每一个已打开的文件都有一个读写位置, 当打开文件时通常其读写位置是指向文件开头, 若是以附加的方式打开文件(如O_APPEND), 则读写位置会指向文件尾. 当read()或write()时, 读写位置会随之增加,lseek()便是用来控制该文件的读写位置. 参数fildes 为已打开的文件描述词, 参数offset 为根据参数whence来移动读写位置的位移数.

参数 whence 为下列其中一种:

  •     SEEK_SET 参数offset 即为新的读写位置.
  •     SEEK_CUR 以目前的读写位置往后增加offset 个位移量.
  •     SEEK_END 将读写位置指向文件尾后再增加offset 个位移量. 当whence 值为SEEK_CUR 或
  •     SEEK_END 时, 参数offet 允许负值的出现.

下列是教特别的使用方式:
1) 欲将读写位置移到文件开头时:lseek(int fildes, 0, SEEK_SET);
2) 欲将读写位置移到文件尾时:lseek(int fildes, 0, SEEK_END);
3) 想要取得目前文件位置时:lseek(int fildes, 0, SEEK_CUR);

返回值:当调用成功时则返回目前的读写位置, 也就是距离文件开头多少个字节. 若有错误则返回-1, errno 会存放错误代码.

附加说明:Linux 系统不允许lseek()对tty 装置作用, 此项动作会令lseek()返回ESPIPE.

C语言fseek()函数:移动文件流的读写位置
头文件:

1
#include <stdio.h>

定义函数:

1
int  fseek ( FILE  * stream,  long  offset,  int  whence);

函数说明:
fseek()用来移动文件流的读写位置.

1、参数stream 为已打开的文件指针,
2、参数offset 为根据参数whence 来移动读写位置的位移数。参数 whence 为下列其中一种:
    SEEK_SET 从距文件开头offset 位移量为新的读写位置. SEEK_CUR 以目前的读写位置往后增加offset 个位移量.
    SEEK_END 将读写位置指向文件尾后再增加offset 个位移量. 当whence 值为SEEK_CUR 或
    SEEK_END 时, 参数offset 允许负值的出现.

下列是较特别的使用方式:
1) 欲将读写位置移动到文件开头时:fseek(FILE *stream, 0, SEEK_SET);
2) 欲将读写位置移动到文件尾时:fseek(FILE *stream, 0, 0SEEK_END);

返回值:当调用成功时则返回0, 若有错误则返回-1, errno 会存放错误代码.

附加说明:fseek()不像lseek()会返回读写位置, 因此必须使用ftell()来取得目前读写的位置.

范例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
main()
{
   FILE  * stream;
   long  offset;
   fpos_t  pos;
   stream =  fopen ( "/etc/passwd" "r" );
   fseek (stream, 5, SEEK_SET);
   printf ( "offset = %d\n" ftell (stream));
   rewind (stream);
   fgetpos (stream, &pos);
   printf ( "offset = %d\n" , pos);
   pos = 10;
   fsetpos (stream, &pos);
   printf ( "offset = %d\n" ftell (stream));
   fclose (stream);
}

执行

?
1
2
3
offset = 5
offset = 0
offset = 10


<think>好的,用户想了解fseek函数用法和示例代码。首先,我需要回顾一下自己之前关于fseek函数的知识,并结合用户提供的引用内容来组织回答。用户提供的引用中有四个关于fseek的说明,这些内容需要整合到回答中,同时还要参考之前的对话历史。 首先,用户的问题是关于fseek的具体用法和示例代码。根据引用内容,fseek函数的原型是int fseek(FILE *stream, long offset, int fromwhere);,功能是重新设置文件内部指针的位置。引用中还提到了不同参数的使用方法,比如SEEK_SET、SEEK_CUR、SEEK_END,以及偏移量的正负处理。此外,用户之前的对话中涉及到了C语言文件操作的相关问题,比如指针类型不匹配的解决方法,但当前的问题主要集中在fseek上,所以需要专注于这部分。 接下来,我需要确定回答的结构。按照用户之前的示例,回答应该分步骤,结构清晰,包含基本语法、参数说明、使用步骤、示例代码、注意事项和相关问题。同时,需要遵循系统级指令,如使用中文、正确LaTeX格式、生成相关问题等。 首先,基本语法部分需要明确函数原型,参数含义,以及返回值。引用2和引用3中提到了函数原型和参数说明,这里可以直接引用。例如,offset是偏移量,origin是起始位置,可能的取值有SEEK_SET、SEEK_CUR、SEEK_END。 然后,使用步骤部分需要分点说明,如打开文件、计算偏移量、调用fseek、错误处理。引用4中的示例代码展示了如何打开文件并使用fseek,可以借鉴这些例子。同时,引用1提到错误处理的重要性,比如检查返回值,处理文件打开模式的问题。 示例代码部分需要覆盖不同的使用场景,比如定位到开头、当前位置、结尾,以及修改文件中的特定记录。引用1中的高级应用实例提到了修改学生记录的例子,可以改编成一个示例。另外,引用4中的代码展示了写入数据后如何使用fseek,可能需要调整以确保代码正确性,比如在写入后重新定位指针。 注意事项部分需要包括文件打开模式、偏移量计算、可移植性、错误处理等。引用1提到不同系统对SEEK_END的处理可能不同,建议使用负偏移量以确保可移植性,这一点很重要,应该包含在内。同时,引用1还提到与rewind和ftell的对比,可以简要提及,但重点还是在fseek上。 相关问题部分需要生成三个相关问题,比如与ftell的结合使用、二进制和文本模式的区别、常见错误及解决方法。这些问题应该与fseek的使用相关,帮助用户进一步学习。 在整合引用内容时,需要正确标注引用标识,如[^1]、[^2]等。例如,在讨论可移植性时引用[^1],在函数原型部分引用[^2],在示例代码中引用[^4]等。 最后,要确保示例代码的正确性。例如,在引用4的代码中,用户可能没有正确使用fseek导致覆盖问题,需要指出正确的做法,比如在写入后使用fseek调整指针位置,或者以读写模式打开文件。同时,检查代码中的错误,如fwrite后是否需要重新定位指针,避免数据覆盖的问题。 总结来说,回答需要结构清晰,涵盖函数用法、参数、示例、注意事项,并正确引用提供的资料。同时,生成的示例代码要准确,注释详细,帮助用户理解每一步操作。最后的问题部分要引导用户深入学习相关主题。</think>### **fseek函数详解与示例代码** --- #### **一、函数功能** `fseek` 是C语言标准库中用于 **移动文件指针** 的核心函数,支持在文件中实现 **随机访问**。常用于二进制文件操作、数据记录修改等场景[^2]。 --- #### **二、基本语法** ```c #include <stdio.h> int fseek(FILE *stream, long offset, int origin); ``` - **参数说明**: - `stream`:文件指针(需已通过 `fopen` 打开) - `offset`:偏移量(字节数,可为正/负) - `origin`:起始位置,取以下值: - `SEEK_SET`:文件开头 - `SEEK_CUR`:当前位置 - `SEEK_END`:文件末尾(需注意不同系统对末尾指针的处理差异)[^1] - **返回值**: - 成功返回 `0`,失败返回非零值(可通过 `perror` 获取错误信息) --- #### **三、使用步骤** 1. **打开文件**:使用 `fopen` 以支持定位的模式(如 `"rb+"` 或 `"wb+"`) 2. **计算偏移量**:根据需求确定偏移方向和字节数 3. **调用fseek**:定位文件指针 4. **错误处理**:检查返回值并处理异常[^1] --- #### **四、示例代码** ##### **场景1:定位到文件开头后写入** ```c #include <stdio.h> #include <stdlib.h> int main() { FILE *fp = fopen("test.txt", "w+"); if (!fp) { perror("文件打开失败"); return -1; } // 写入初始数据 fputs("Hello World!", fp); // 定位到第6字节(从0开始计数) if (fseek(fp, 6, SEEK_SET) != 0) { perror("fseek失败"); fclose(fp); return -1; } // 覆盖写入新数据 fputs("Linux", fp); // 结果变为 "Hello Linux!" fclose(fp); return 0; } ``` **输出文件内容**:`Hello Linux!` [^4] --- ##### **场景2:修改二进制文件中的记录** ```c typedef struct { int id; char name[20]; float score; } Student; void update_score(int target_id, float new_score) { FILE *fp = fopen("students.dat", "rb+"); if (!fp) { perror("文件打开失败"); return; } Student stu; while (fread(&stu, sizeof(Student), 1, fp) == 1) { if (stu.id == target_id) { stu.score = new_score; fseek(fp, -sizeof(Student), SEEK_CUR); // 回退指针以覆盖原记录 fwrite(&stu, sizeof(Student), 1, fp); break; } } fclose(fp); } ``` --- #### **五、关键注意事项** 1. **文件模式**:确保使用支持定位的模式(如 `"r+"`、`"rb+"`)[^1] 2. **偏移量计算**: - 文本文件:某些系统可能不支持 `SEEK_END` 或非零偏移[^3] - 二进制文件:可自由使用所有定位方式 3. **可移植性**:使用 `SEEK_END` 时建议用负偏移(如 `fseek(fp, -5, SEEK_END)`)[^1] 4. **错误处理**:始终检查返回值,避免越界访问 --- #### **六、与其他函数对比** | 函数 | 功能 | 特点 | |----------|--------------------------|-------------------------------| | `rewind` | 重置指针到文件开头 | 无返回值,等效于 `fseek(fp, 0, SEEK_SET)` [^1] | | `ftell` | 获取当前指针位置 | 与 `fseek` 组合可实现动态定位[^1] | --- ### **相关问题** 1. 如何结合 `ftell` 和 `fseek` 动态计算文件大小? 2. 二进制模式与文本模式在文件定位时的区别? 3. `fseek` 在文件末尾追加数据时需要注意什么?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值