目录
int fseek (FILE * stream, long offset,int location);
文件
磁盘上的文件是文件
一般来讲,分为:程序文件和数据文件
程序文件:包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行文件(windows环境后缀为.exe)
数据文件:文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取的文件,或者输出内容的文件
本文讨论的是数据文件。
在以前各章所处理数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上
文件名:一个文件需要唯一的文件标识,以便用户的识别和引用
文件名包含三部分:文件路径,文件名主干,文件后缀;
为了方便期间,文件标识常被称为文件名
文件的打开和关闭:
文件指针:
缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名称,文件的状态,以及文件当前的位置等)
这些信息是被保存在一个结构体变量中的。该结构体类型是由系统声明的,取名FILE。
每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节。
一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便
创建一个FILE指针
FILE *pf
pf指向某文件的文件信息区(是一个结构体变量)。
通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件
比如:
如何打开和关闭文件:
文件打开之后需要关闭
int main()
{
FILE* pf = fopen("test2.txt", "r");
w模式可以创建不存在的文件
r模式只会打开不存在的文件
if (pf == NULL)
{
perror("fioen");
return 1;
}
写文件:
关闭文件:
fclose(pf);
pf = NULL;
return 0;
}
文件输入输出函数:
硬盘上的文件数据 -->> 内存中的程序 :输入/读取
内存中的程序 -->> 硬盘上的文件数据 :输出/写入
字符输入函数:fgetc
字符输出函数:fputc
文本行输入函数:fgets
文本行输出函数:fputs
格式化输入函数:fscanf
格式化输出函数:fpintf
以上是适应于所有输入输出流,
以下适应于文件
二进制输入:fread
二进制输出:fwrite
int main()
{
FILE* pf = fopen("test1.txt", "a+");
w模式可以创建不存在的文件
r模式只会打开不存在的文件
if (pf == NULL)
{
perror("fioen");
return 1;
}
写文件:
fputc('\n', pf); //单个字符输入,
fputs("1bit", pf); //单行文本输入
关闭文件:
fclose(pf);
pf = NULL;
return 0;
}
输出到文件
流:高度抽象的概念
程序-->>屏幕,硬盘,U盘,光盘,网络,软盘。。。
但是这种方式输出数据,不可以重用
所以就在中间加了一个层级,称为流
程序-->>流-->>其他
C语言程序,只要运行起来,就默认打开了三个流
stdin -- 标准输入流 -- 键盘
stdout -- 标准输出流 -- 屏幕
stderr -- 标准错误流 -- 屏幕
stdout的使用
int main()
{
fputc('b', stdout);
fputc('i', stdout);
fputc('t', stdout);
return 0;
}
//输出
bit
fgetc()读文件示例:
int main()
{
FILE* pf = fopen("test1.txt", "r");
w模式可以创建不存在的文件
r模式只会打开不存在的文件
if (pf == NULL)
{
perror("fioen");
return 1;
}
读文件(单个字符)
printf("%c\n", fgetc(pf));
printf("%c\n", fgetc(pf));
printf("%c\n", fgetc(pf));
printf("%c\n", fgetc(pf));
printf("%c\n", fgetc(pf));
读取文件(单行字符)
char arr[20] = { 0 };
printf("%s\n", fgets(arr, 5, pf));
当读取五个的时候,只会读取4个,因为要给arr留一个‘\0’的位置
printf("%s\n", fgets(arr, 5, pf));
printf("%s\n", fgets(arr, 5, pf));
printf("%s\n", fgets(arr, 5, pf));
printf("%s\n", fgets(arr, 5, pf));
从标准输入流读取信息(键盘)
printf("%c\n", fgetc(stdin));
printf("%c\n", fgetc(stdin));
printf("%c\n", fgetc(stdin));
printf("%c\n", fgetc(stdin));
printf("%c\n", fgetc(stdin));
关闭文件:
fclose(pf);
pf = NULL;
return 0;
}
写文件
struct s {
char ch[10];
int i;
double d;
};
fprintf()函数:相比printf()多了一个参数---输入流
int main()
{
struct s s1 = { "abcdef",10,5.5f };
FILE* pf = fopen("test.txt", "w");
if (NULL == pf)
{
perror("fopen");
return 1;
}
写文件
fprintf(pf, "%s %d %f", s1.ch, s1.i, s1.d);
fclose(pf);
pf = NULL;
return 0;
}
读文件
scanf()函数
按照某一种格式输入输出数据
int main()
{
char ch[100] = { 0 };
int i = 0;
FILE* pf = fopen("test.txt", "r");
if (NULL == pf)
{
perror("fopen");
return 1;
}
fscanf(pf, "%s ", ch);//这里直接用结构体获取数据也可以
fscanf(pf, "%d ", &i);//这里输入的应该是一个地址
fscanf(pf, "%s ", ch);
printf(ch);
fclose(pf);
pf = NULL;
return 0;
}
二进制的读写:
写入
struct s {
char ch[10];
int i;
double d;
};
int main()
{
struct s s1 = { "abcdef",10,5.5f };
二进制的形式写
FILE* pf = fopen("test.txt", "w");
if (NULL == pf)
{
perror("fopen");
return 1;
}
写文件
fwrite(&s1, sizeof(struct s), 1,pf);
关闭文件
fclose(pf);
pf = NULL;
return 0;
}
读取
int main()
{
struct s s1 = { 0 };
二进制的形式写
FILE* pf = fopen("test.txt", "r");
if (NULL == pf)
{
perror("fopen");
return 1;
}
读文件
fread(&s1, sizeof(struct s), 1, pf);
printf("%s %d %f\n", s1.ch, s1.i, s1.d);
关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fwrite写入的虽然看不懂,但是可以通过fread读取到数据;
对比一组函数
scanf //fscanf // sscanf
scanf -- 针对标准输入格式化的输入语句 -- stdin
fscanf -- 针对所有输入流的格式化输入语句 -- stdin/文件
sscanf -- 从字符串中还原为一个结构体数据
printf // fprintf // sprintf
printf -- 针对标准输出的格式化输出语句 -- stdout
fprintf -- 针对所有输出流的格式化输出语句 -- stdout/文件
sprintf -- 把格式化数据转换成字符串
struct s {
char ch[10];
int i;
double d;
};
int main()
{
struct s s1 = { "hello", 20,5.5f };
struct s s2 = {0 };
char buff[100] = { 0 };
sprintf(buff, "%s %d %lf", s1.ch, s1.i, s1.d);
sprintf -- 把格式化数据转换成字符串
printf(buff);
从buff字符串中还原为一个结构体数据
sscanf(buff, "%s %d %lf", &(s2.ch), &(s2.i), &(s2.d));
printf("%s %d %lf", s2.ch, s2.i, s2.d);
return 0;
}
buff并不一定是结构体,其他类型也可以
文件的随机读写
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
读取文件
int ch = fgetc(pf);
printf("%c\n", ch);
fseek(pf, -1, SEEK_CUR);
ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
关闭文件
fclose(pf);
pf = NULL;
return 0;
}
int fseek (FILE * stream, long offset,int location);
三个参数:流,偏移量,起始位置:seek_cur--当前位置;seek_end-->文件末尾;seek_set-->文件开头
/*程序清单16.12predef.c程序
ll predef.c --预定义宏和预定义标识符*/
void why_me();
int main()
{
printf("The file is %s. \n", __FILE__);
printf("The date is %s. \n", __DATE__);
printf("The time is %s. \n", __TIME__);
printf("The version is %ld .\n", __STDC_VERSION__);
printf("This is line %d. \n", __LINE__);
printf("This function is %s .\n", __func__);
why_me();
return 0;
}
void why_me() {
printf("This function is %s \n", __func__);
printf("This is line %d. \n", __LINE__);
}