fseek函数位移量在文件中的使用问题

hawk008 2009-09-14 08:11:57
有如下一段程序

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct studentstruct
{
int No;
char Name[20];
int Age;
}student[3];
void main()
{
int i=0;
int studentNo=3;
printf("请输入学生数据:\n");
for(i=0;i<3;i++)
scanf("%d%s%d",&student[i].No, student[i].Name, &student[i].Age);
//SaveFile();
printf("No\t\tName\t\tAge\n");

printf("请输入要显示学生数据的学生学号:\n");
scanf("%d",&studentNo);
GetFileData(studentNo);
}
void GetFileData(int no)
{
struct studentstruct *p;
FILE *fp;
if((fp=fopen("student.txt","r"))==NULL)
{
printf("不能打开文件读请按下任意键结束!\n");
getch();
exit(1);
}
p=&student[0];
fseek(fp,(no-1)*sizeof(struct studentstruct),0);
fread(p,sizeof(struct studentstruct),1,fp);
printf("%d\t\t%s\t\t%d\n",p->No, p->Name, p->Age);
fclose(fp);
}


其中SaveFile()自定义函数的功能是把输入的学生数据写到文件中去。在这里可以先不管他!
现在我不明白的是,在按照学生NO.查找学生信息时,如果学生的NO值是一个较大的数,比如100,那么Fseek函数中,位移量就会很大,等于要向后移动sizeof(struct studentstruct)*100这么大的字节数,可是为什么还是能找到这个学生的信息呢?
是否是当位移量大于文件大小时,就回又向文件头开始查找??
请明白的高手详细解答一下吧!
...全文
246 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
hawk008 2009-09-14
  • 打赏
  • 举报
回复
靠,我明白了~~~~
我一直在试第一个,所以总能显示……太粗心了!!
我明白了,谢谢mstlq,送分结贴!
mstlq 2009-09-14
  • 打赏
  • 举报
回复

int flag=fseek(fp,(no-1)*sizeof(struct studentstruct),0);
if(flag!=0)
{
puts("fseek失败,文件指针实际上根本没有移动!\n");
}
hawk008 2009-09-14
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 mstlq 的回复:]
请看1楼……


当你把aveFile()源码看清楚之后,就明白了……
[/Quote]
我把saveFile()源码贴出来

void SaveFile(void)
{
FILE *fp;
int i=0;

if( (fp=fopen("student.txt","w"))==NULL )
{
printf("不能打开文件读请按下任意键结束!\n");
getch();
exit(1);
}

for( i=0; i<3; i++ )
if(fwrite(&student[i],sizeof(struct studentstruct),1,fp)!=1)
printf("不能写文件\n");
fclose(fp);
}

我的理解,程序向文件里写入的时候,是将结构体数组的元素依次写入的,既先写入student[0]……
数组中一个元素是28个字节,一个84个,我就是这不明白,如果我的学号是4,则要从文件起始位置往后找84个字节,但这时已经超出整个结构体数组的大小了啊,为什么还能找出来?
mstlq 2009-09-14
  • 打赏
  • 举报
回复
楼上的把谜底给揭开了……
kakashi0309 2009-09-14
  • 打赏
  • 举报
回复
fseek 如果偏移量超过文件大小 应该返回非零值 文件指针指向不变
mstlq 2009-09-14
  • 打赏
  • 举报
回复
请看1楼……


当你把aveFile()源码看清楚之后,就明白了……
hawk008 2009-09-14
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 mstlq 的回复:]
楼主问的是“为什么行?”
根据楼上的回答,实际上这个玩意是不行……

那么楼主的问题没有问下去的意义了^_^
[/Quote]
先不要去纠结程序的严谨性问题了吧~
我是只想知道,为什么向后移动很多字节找也可以找到!LS的XD知道就告诉我一下吧,谢谢了!
mstlq 2009-09-14
  • 打赏
  • 举报
回复
楼主问的是“为什么行?”
根据楼上的回答,实际上这个玩意是不行……

那么楼主的问题没有问下去的意义了^_^
hawk008 2009-09-14
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 mstlq 的回复:]
能输出
99999999  **** ****
??
[/Quote]
你说的是输入学号9999999啊,呵呵,我还以为移动了99999999个字节!
输入8个9,肯定不行啊,再乘结构体的大小,已经超出了取值范围了啊!
mstlq 2009-09-14
  • 打赏
  • 举报
回复
能输出
99999999 **** ****
??
hawk008 2009-09-14
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 hawk008 的回复:]
引用 5 楼 mstlq 的回复:
引用 4 楼 hawk008 的回复:
超出LONG的取值范围肯定不行啊~~~
我现在就是不明白为什么往后移动了,还能找到!


99999999 < 2的27次方 < int可以表示的范围……

哦,刚才没仔细数几个9,8个9没问题啊,可以找到啊
[/Quote]
不对,我的错,输入8个9始终找到的都是第一个学生的信息!
那这是因为什么呢 ?
mstlq 2009-09-14
  • 打赏
  • 举报
回复
printf("%d\t\t%s\t\t%d\n",p->No, p->Name, p->Age);

这一行输出正常?
hawk008 2009-09-14
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 mstlq 的回复:]
引用 4 楼 hawk008 的回复:
超出LONG的取值范围肯定不行啊~~~
我现在就是不明白为什么往后移动了,还能找到!


99999999 < 2的27次方 < int可以表示的范围……
[/Quote]
哦,刚才没仔细数几个9,8个9没问题啊,可以找到啊
mstlq 2009-09-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 hawk008 的回复:]
超出LONG的取值范围肯定不行啊~~~
我现在就是不明白为什么往后移动了,还能找到!
[/Quote]

99999999 < 2的27次方 < int可以表示的范围……
hawk008 2009-09-14
  • 打赏
  • 举报
回复
超出LONG的取值范围肯定不行啊~~~
我现在就是不明白为什么往后移动了,还能找到!
mstlq 2009-09-14
  • 打赏
  • 举报
回复
输入99999999也可以吗^_^?
hawk008 2009-09-14
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 mstlq 的回复:]
fseek() returns zero upon success, non-zero on failure. You can use fseek() to move beyond a file, but not before the beginning. Using fseek() clears the EOF flag associated with that stream.


写代码的人啊……
估计是将学生信息按学号顺序存放在文件里面的,而且学号紧紧相连一个不差……
这个设计,唉……
[/Quote]
楼上的XD速度真快!!
现在我在输入的时候,学号就是乱输的,但是也能够找到对应的学员信息!
我英文不好,您发的那个我大概理解就是fseek()可以越过EOF重新返回查找是吗?
mstlq 2009-09-14
  • 打赏
  • 举报
回复
fseek() returns zero upon success, non-zero on failure. You can use fseek() to move beyond a file, but not before the beginning. Using fseek() clears the EOF flag associated with that stream.


写代码的人啊……
估计是将学生信息按学号顺序存放在文件里面的,而且学号紧紧相连一个不差……
这个设计,唉……
适用于初学第十章:文件 文件 文件的基本概念   所谓“文件”是指一组相关数据的有序集合。 这个数据集有一个名称,叫做文件名。 实际上在前面的各章我们已经多次使用文件,例如源程序文件、目标文件、可执行文件、库文件 (头文件)等。文件通常是驻留在外部介质(如磁盘等)上的, 在使用时才调入内存来。从不同的角度可对文件作不同的分类。从用户的角度看,文件可分为普通文件和设备文件两种。   普通文件是指驻留在磁盘或其它外部介质上的一个有序数据集,可以是源文件、目标文件、可执行程序; 也可以是一组待输入处理的原始数据,或者是一组输出的结果。对于源文件、目标文件、 可执行程序可以称作程序文件,对输入输出数据可称作数据文件。   设备文件是指与主机相联的各种外部设备,如显示器、打印机、键盘等。在操作系统,把外部设备也看作是一个文件来进行管理,把它们的输入、输出等同于对磁盘文件的读和写。 通常把显示器定义为标准输出文件, 一般情况下在屏幕上显示有关信息就是向标准输出文件输出。如前面经常使用的printf,putchar 函数就是这类输出。键盘通常被指定标准的输入文件, 从键盘上输入就意味着从标准输入文件上输入数据。scanf,getchar函数就属于这类输入。   从文件编码的方式来看,文件可分为ASCII码文件和二进制码文件两种。   ASCII文件也称为文本文件,这种文件在磁盘存放时每个字符对应一个字节,用于存放对应的ASCII码。例如,数5678的存储形式为: ASC码:  00110101 00110110 00110111 00111000      ↓     ↓    ↓    ↓ 十进制码: 5     6    7    8 共占用4个字节。ASCII码文件可在屏幕上按字符显示, 例如源程序文件就是ASCII文件,用DOS命令TYPE可显示文件的内容。 由于是按字符显示,因此能读懂文件内容。   二进制文件是按二进制的编码方式来存放文件的。 例如, 数5678的存储形式为: 00010110 00101110只占二个字节。二进制文件虽然也可在屏幕上显示, 但其内容无法读懂。C系统在处理这些文件时,并不区分类型,都看成是字符流,按字节进行处理。 输入输出字符流的开始和结束只由程序控制而不受物理符号(如回车符)的控制。 因此也把这种文件称作“流式文件”。   本章讨论流式文件的打开、关闭、读、写、 定位等各种操作。文件指针在C语言用一个指针变指向一个文件, 这个指针称为文件指针。通过文件指针就可对它所指的文件进行各种操作。 定义说明文件指针的一般形式为: FILE* 指针变标识符; 其FILE应为大写,它实际上是由系统定义的一个结构, 该结构含有文件名、文件状态和文件当前位置等信息。 在编写源程序时不必关心FILE结构的细节。例如:FILE *fp; 表示fp是指向FILE结构的指针变,通过fp 即可找存放某个文件信息的结构变,然后按结构变提供的信息找到该文件, 实施对文件的操作。习惯上也笼统地把fp称为指向一个文件的指针。文件的打开与关闭文件在进行读写操作之前要先打开,使用完毕要关闭。 所谓打开文件,实际上是建立文件的各种有关信息, 并使文件指针指向该文件,以便进行其它操作。关闭文件则断开指针与文件之间的联系,也就禁止再对该文件进行操作。   在C语言文件操作都是由库函数来完成的。 在本章内将介绍主要的文件操作函数文件打开函数fopen   fopen函数用来打开一个文件,其调用的一般形式为: 文件指针名=fopen(文件名,使用文件方式) 其,“文件指针名”必须是被说明为FILE 类型的指针变,“文件名”是被打开文件文件名。 “使用文件方式”是指文件的类型和操作要求。“文件名”是字符串常或字符串数组。例如: FILE *fp; fp=("file a","r"); 其意义是在当前目录下打开文件file a, 只允许进行“读”操作,并使fp指向该文件。 又如: FILE *fphzk fphzk=("c:\\hzk16',"rb") 其意义是打开C驱动器磁盘的根目录下的文件hzk16, 这是一个二进制文件,只允许按二进制方式进行读操作。两个反斜线“\\ ”的第一个表示转义字符,第二个表示根目录。使用文件的方式共有12种,下面给出了它们的符号和意义。 文件使用方式        意 义 “rt”      只读打开一个文本文件,只允许读数据 “wt”      只写打开或建立一个文本文件,只允许写数据 “at”      追加打开一个文本文件,并在文件末尾写数据 “rb”      只读打开一个二进制文件,只允许读数据 “wb”       只写打开或建立一个

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧