每天进步一点点-->函数fseek() 用法

本文详细解释了fseek函数的功能、用法及其参数,并通过代码示例展示了如何使用fseek进行文件指针的移动。文章还介绍了如何在文件读写过程中灵活运用fseek来实现文件定位,包括从文件开头、当前位置或文件末尾进行偏移操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自于:http://blog.youkuaiyun.com/wl_soft50/article/details/7787521

在阅读代码时,遇到了很早之前用过的fseek(),很久没有用了,有点陌生,写出来以便下次查阅。

函数功能是把文件指针指向文件的开头,需要包含头文件stdio.h

fseek
  函数名: fseek
  功 能: 重定位流上的文件指针
  用 法: int fseek(FILE *stream, long offset, int fromwhere);
  描 述: 函数设置文件指针stream的位置。如果执行成功,stream将指向以fromwhere为基准,偏移offset个字     节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。
  返回值: 成功,返回0,否则返回其他值。
  fseek position the file position pointer for the file referenced by stream to the byte location calculated by offset.
  程序例:
  

[cpp]  view plain copy
  1. #include <stdio.h>  
  2.   long filesize(FILE *stream);  
  3.   int main(void)  
  4.   {  
  5.     FILE *stream;  
  6.     stream = fopen("MYFILE.TXT""w+");  
  7.     fprintf(stream, "This is a test");  
  8.     printf("Filesize of MYFILE.TXT is %ld bytes\n", filesize(stream));  
  9.     fclose(stream);  
  10.     return 0;  
  11.   }  
  12.   long filesize(FILE *stream)  
  13.   {  
  14.     long curpos, length;  
  15.     curpos = ftell(stream);  
  16.     fseek(stream, 0L, SEEK_END);  
  17.     length = ftell(stream);  
  18.     fseek(stream, curpos, SEEK_SET);  
  19.     return length;  
  20.   }  


  int fseek( FILE *stream, long offset, int origin );
  第一个参数stream为文件指针
  第二个参数offset为偏移量,整数表示正向偏移,负数表示负向偏移
  第三个参数origin设定从文件的哪里开始偏移,可能取值为:SEEK_CUR、 SEEK_END 或 SEEK_SET
  SEEK_SET: 文件开头
  SEEK_CUR: 当前位置
  SEEK_END: 文件结尾

  其中SEEK_SET,SEEK_CUR和SEEK_END和依次为0,1和2.
  简言之:
  fseek(fp,100L,0);把fp指针移动到离文件开头100字节处;
  fseek(fp,100L,1);把fp指针移动到离文件当前位置100字节处;
  fseek(fp,100L,2);把fp指针退回到离文件结尾100字节处。
  使用实例:

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #define N 5  
  3. typedef struct student {  
  4.  long sno;  
  5.  char name[10];  
  6.  float score[3];  
  7. } STU;  
  8. void fun(char *filename, STU n)  
  9. {  
  10.  FILE *fp;  
  11.  fp = fopen(filename, "rb+");  
  12.  fseek(fp, -1L*sizeof(STU),SEEK_END);  
  13. fwrite(&n, sizeof(STU), 1, fp);  
  14. fclose(fp);  
  15. }  
  16. void main()  
  17. {  
  18.   STU t[N]={ {10001,"MaChao", 91, 92, 77}, {10002,"CaoKai", 75, 60, 88},  
  19.   {10003,"LiSi", 85, 70, 78}, {10004,"FangFang", 90, 82, 87},  
  20.   {10005,"ZhangSan", 95, 80, 88}};  
  21.   STU n={10006,"ZhaoSi", 55, 70, 68}, ss[N];  
  22.   int i,j; FILE *fp;  
  23.   fp = fopen("student.dat""wb");  
  24.   fwrite(t, sizeof(STU), N, fp);  
  25.   fclose(fp);  
  26.   fp = fopen("student.dat""rb");  
  27.   fread(ss, sizeof(STU), N, fp);  
  28.   fclose(fp);  
  29.   printf("\nThe original data :\n\n");  
  30.   for (j=0; j<N; j++)  
  31.   {  
  32.    printf("\nNo: %ld Name: %-8s Scores: ",ss[j].sno, ss[j].name);  
  33.    for (i=0; i<3; i++)   
[cpp]  view plain copy
  1.  printf("%6.2f ", ss[j].score[i]);  
  2.  printf("\n");  
  3. }  
  4. fun("student.dat", n);  
  5. printf("\nThe data after modifing :\n\n");  
  6. fp = fopen("student.dat""rb");  
  7. fread(ss, sizeof(STU), N, fp);  
  8. fclose(fp);  
  9. for (j=0; j<N; j++)  
  10. {  
  11.  printf("\nNo: %ld Name: %-8s Scores: ",ss[j].sno, ss[j].name);  
  12.  for (i=0; i<3; i++)   
[cpp]  view plain copy
  1.  printf("%6.2f ", ss[j].score[i]);  
  2.  printf("\n");  
  3. }  


<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、付费专栏及课程。

余额充值