许多系统中的标准输入/输出库都允许程序打开一个文件,同时进行写入和读出的操作:

  

 
  
  1. FILE *fp; 
  2. fp = fopen(file, "r+"); 

上面的例子代码打开了文件名由变量file指定的文件,对于存取权限的设定表明程序希望对这个文件进行输入和输出操作。

  编程者也许认为,程序一旦执行上述操作完毕,就可以自由地交错进行读出和写入操作。遗憾的是,事实总难随人所愿,为了保持与过去不能同时进行读写操作的程序的向下兼容性,一个输入操作不能随后直接跟一个输出操作,反之亦然。如果要同时进行输入和输出操作,必须在其中插入fseek函数的调用。

  下面的程序片段似乎更新了一个顺序文件中的记录:

 

 
  
  1. FILE *fp; 
  2. struct record rec; 
  3. ... 
  4.  
  5. while (fread((char *)&rec, sizeof(rec), 1, fp) == 1) { 
  6.     //对rec执行某些操作 
  7.     if (/* rec必须被重新写入*/ ) { 
  8.         fseek(fp, -(long)sizeof(rec), 1); 
  9.         fwrite( ( char *) rec, sizeof(rec), 1, fp); 
  10.     } 

  这段代码看上去毫无问题:&rec在传入fread和fwrite函数时被小心翼翼地转换为字符指针类型,sizeof(rec)被转换为长整型(fseek函数要求第二个参数是long类型,因为int类型的整数可能无法包含一个文件的大小;sizeof返回一个unsigned值,因此首先必须将其转换为有符号类型才有可能将其反号)。但是这段代码仍然可能运行失败,而且出错的方式非常难于察觉。

  问题出在:如果一个记录需要被重新写入文件,也就是说,fwrite函数得到执行,对这个文件执行的下一个操作将是循环开始的fread函数。因为在fwrite函数调用与fread函数调用之间缺少了一个fseek函数调用,所有无法进行上述操作。解决的办法是把这段代码改写为:

 
  
  1. while (fread( ( char *)&rec, sizeof(rec), 1, fp) == 1) { 
  2.     /* 对rec执行某些操作*/ 
  3.     if (/* rec 必须被重新写入 */) { 
  4.         fseek(fp, -(long)sizeof(rec), 1); 
  5.         fwrite((char *)&rec, sizeof(rec), 1, fp); 
  6.         fseek(fp, 0L, 1); 
  7.     } 

  第二个fseek函数虽然看上去什么也没做,但它改变了文件的状态,使得文件现在可以正常地进行读取了。