1、C语言支持文本形式二进制形式的文件操作,无论那种形式,都把文件看作一个字节的序列,对文件的存取是以字节为单位进行的。

C语言编程注意点7_预定义


文本文件便于显示,二进制文件节省存储空间,处理速度快,一般用于保存大量数据。2、以二进制流打开文件的方式包括

C语言编程注意点7_预定义_02

3、二进制流文件结束判断
在二进制文件中不设EOF标志(因为-1为合法数据)

为了判断文件是否结束,提供了文件结束测试函数:
feof ( fp );
若最近一次读取fp所指向的文件时,读取了文件尾部,则返回非0值,否则返回0

feof()函数读取到尾部最后一个字节后,如下图:

C语言编程注意点7_预定义_03


(feof对于文本文件也适用)

4、行输入、行输出

char  *fgets(char  *s,  int  n,  FILE  *fp)

//常见使用方式
while ( fgets( s, 81, fp ) != NULL )
{
}

从fp上最多读入n-1个字符,放入s 字符数组中。返回s或NULL。

int  fputs( char  *s,  FILE  *fp)

把字符串s(不一定含\n)写入文件fp中。返回非负数或EOF。

  1. fgets正常读入换行字符(与gets不同);
  2. fputs不在输出后自动加换行字符(与puts不同);
  3. fgets能设置字符的最大个数,因此,当无法确定所读入的数据行有多长时,最好使用fgets,而不用gets。如:fgets(buf, 81, stdin);
  4. getc, putc和fgetc,fputc的另外一个区别是fgetc和fputc是函数,而getc和putc是宏定义

5、文件格式化输入/输出

fscanf(fp, format, )    //返回成功读入的数据个数,若到达文件末尾或转换出错,则返回EOF
fprintf(fp, format, )

比scanf、printf函数分别多了一个文件指针参数。

6、块输入/输出

size_t  fwrite(const void *ptr,  size_t size,  size_t  nobj,  FLE *fp)

从指针ptr所指的对象中,向文件fp中写入大小为size的nobj个对象。其返回值为实际写入的对象数。

size_t  fread(void *ptr,  size_t size,  size_t nobj,  FILE *fp)

从文件fp中读入大小为size的nobj个对象,放入指针ptr所指的对象中。其返回值为实际读入的对象数。

通常它们被用来输入或输出象结构这样的成块数据。如:

fwrite(buf, sizeof(struct student), n, fp); 
fread(buf, sizeof(struct student), n, fp);

注意:

  1. 块输入/输出又称直接输入/输出,不进行数据格式的转换 ,因此属于二进制流形式的输入/输出操作。
  2. 用fwrite函数写入数据的文件,其内容一般无法用普通的编辑器查看或修改。
  3. 一般用于保存数据,为了以后重新读取使用。
  4. fwrite和fread函数一般配对使用: 用fwrite写入的数据一般通过fread函数读取;用fread读取的数据也一般是用fwrite函数写入的。

7、文件读写位置与随机输入/输出

long ln = ftell(fp);

返回fp所指文件的读写指针当前位置,即相对于文件开始处的位移量,单位是字节。若调用失败,返回-1

可用下面函数来改变文件读写位置:

( fp, offset, origin );

将fp所指向文件的读写指针相对于origin移动offset个字节若成功,返回0,否则返回非0值

C语言编程注意点7_枚举_04


文件复位函数:

void rewind ( FILE * fp );

将fp所指向文件的读写指针重新定位到文件的开始。

8、常用库函数
【1】

sscanf(char * s, char *format [, pointer…])

从字符串s中读取数据并转换成相应数据格式的变量;
格式转换方式同scanf。
sscanf适合用来将字符数据转换成整数、浮点数或较短的字符串,它通常用以将事先读入的一行数据,依其不同的字段分开。使用如下:

char  *buf = "123.456 + 595.36";
float val1, val2;
char oper;
sscanf(buf, "%f %c %f", &val1, &oper, &val2);

【2】

sprintf(char * s, char *format [, arg…])

把变量转换成相应格式后,保存到字符串s中;
格式转换方式同printf。
当需要把某种类型的数据转换成字符串时,sprintf就特别有用。使用方式如下:

char buf[100], *cmd= "test";
int width = 80;
double x = 5.67;
sprintf(buf, "%s %d %f", cmd, width, x);
printf("%s\n", buf);

【3】

C语言编程注意点7_枚举_05


【4】

C语言编程注意点7_static_06


【5】

C语言编程注意点7_二进制文件_07

9、#include

C语言编程注意点7_预定义_08


使用#include的优点:

可以把所有公共的、需要给程序各个函数共享的外部变量说明、函数原型和宏定义、类型定义等都放在某一文件上(通常以.h为文件后缀)。其它文件的开头只须用一条#include “该.h”文件的语句,就可以省去重写这些说明、定义的麻烦,而且程序结构更为清晰10、#if (条件编译)

C语言编程注意点7_预定义_09


我们经常可在一些头文件中见到下面语句:

#ifndef
#define

#endif

可用它们来避免该头文件被重复包含。

11、变量作用域

  1. 变量作用域:变量的使用范围;
  2. 在同一个作用域内,不允许定义同名变量;
  3. 在不同作用域内,允许定义同名变量。如果同名变量作用域重叠,则内层变量将屏蔽外层变量;

12、静态变量(static)
① 内部静态变量
在局部变量前加上“static”关键字就成为内部静态变量。
内部静态变量仍是局部变量,其作用域仍在定义它的函数内。但该变量采用静态存贮分配(由编译程序在编译时分配,而一般的自动变量和函数形参均采用动态存贮分配,即在运行时分配空间),当函数执行完,返回调用点时,该变量并不撤消,其值将继续保留,若下次再进入该函数时,其值仍存在。
②外部静态变量
在函数外部定义的变量前加上“static”关键字便成了外部静态变量。
外部静态变量的作用域为定义它的文件,即成为该文件的的“私有”(private)变量,其它文件上的函数一律不得直接进行访问,除非通过它所在文件上的各种函数来对它进行操作,这可实现数据隐藏。(在C++中提供进一步的数据隐藏。)

13、变量初始化

  1. 外部和静态变量由编译程序给予隐含的初值0。
  2. 程序员可在变量定义时对它进行初始化(不是赋值表达式)。
  3. 自动变量的初始化每进入该函数时便初始化一次。 外部或静态变量的初始化仅(在编译时)进行一次。
  4. 自动变量或寄存器变量只能显式初始化,否则,自动变量和寄存器变量有不确定的值。
  5. *外部数据的说明,如果带有初始化项,即当成一个定义。

14、枚举类型(enum)
枚举值是标识符

对枚举变量的赋值并不是将标识符字符串传给它,而是把该标识符所对应的各值表中常数值赋于变量。C语言编译程序把值表中的标识符视为从0开始的连续整数;

枚举类型变量的作用范围与一般变量的定义相同;

枚举类型用途:枚举类型通常用来说明变量取值为有限的一组值之一;用来定义常量;