C语言文件操作(一)

阅读: 评论:0

C语言文件操作(一)

C语言文件操作(一)

目录

  • 为什么要使用文件
  • 什么是文件
    • 程序文件
    • 数据文件
    • 文件名
  • 文件指针
  • 文件的打开与关闭
    • 相似的事件
    • 文件的打开与关闭
  • 文件的顺序读写
    • fgetc()
    • fputc()
    • fgets()
    • fputs()
    • fwrite
    • fread
    • fscanf
    • fprintf
    • sscanf
    • sprintf
  • 思考题
  • 总结

为什么要使用文件

在我们写某种程序时,我们需要在程序运行时,进行操作,但是如果程序结束,数据将自动销毁,我们无法使用这些数据。此时我们就需要一个文件来保存这些数据以便程序下次的操作。
以前我们设计程序时,我们数据的输入,是从键盘上读取的;数据的输出,是直接输出到屏幕上的。
但是如果我们不需要在键盘上读取数据,且不需要在屏幕上输出,这时我们可以所需要的数据或者是程序所产生的数据让在文件中。


什么是文件

磁盘上的文件是文件。
但在程序设计中,文件又被分为:程序文件、数据文件。

程序文件

程序文件包括:源文件(后缀为***.c***)、目标文件(在 windows 环境后缀为 .obj ), 可执行程序( 在 windows 环境下后缀为 .exe )

数据文件

程序运行时,所需要读取数据的文件,或者时所需要输出数据的文件。

文件名

文件名是文件唯一的文件标识,供用户查找和使用。
文件名包含三部分文件路径文件名主干文件后缀
例如:d:Learning
文件标识就是我们我们常说的:文件名


文件指针

每个被使用的文件在内存中都会开辟一个相应的文件信息区,用于存放文件的相关信息(如文件的名字、文件的状态以及文件当前的位置等等)。这些信息保存在保存在一个结构体变量中,该结构体类型是有系统声明的,取名 FILE.
在不同的C语言编译器, FILE 结构体类型所包含的内容(文件名、状态、当前位置等)会有所差异 ,但是这种差异是很小的,同时不会影响使用
我们通常是通过 FILE 类型指针来维护变量。
下面我们创造一个文件指针。

FILE* pf;

pf 是指向某一文件的信息区(是一个结构体变量),通过文件信息区的内容我们能够轻松的访问此文件。


文件的打开与关闭

相似的事件

我们在日常的生活中,可能遇到过向瓶子中导入液体和到处液体的情况,这类似于文件的打开与关闭。

文件的打开与关闭

我们在使用文件前或文件后,我们都应打开关闭文件。
我们在打开文件时,文件会返回一个 FILE* 的指针变量来指向该文件,相当于建立了指针与文件之间的联系。
美国国家标准协会(ANSI)及国际标准化组织规定,我们使用 fopen 来打开文件,使用 fclose 来关闭文件。

//打开文件
FILE* fopen ( const char* filename , const char* mode );
//关闭文件
int fclose ( FILE* stream );

打开文件的方式有如下几种( mode ):

***文件的使用方式含义如果文件不存在完整英文
r"(只读)为了输入数据,打开一个已经存在的文本文件出错read
w"(只写)为了输出数据,打开一个文本文件(文本原始内容将被清空)在文件相同目录下创建一个新文件write
a"(追加)像文本尾添加一个新的数据在文件相同目录下创建一个新文件append
rb”(只读)为了输入数据,打开一个二进制文件出错read binary file
wb”(只写)为了输出数据,打开一个二进制文件建立一个新的文件write binary file
"ab“(追加)为二进制文件尾添加数据出错append binary file
r+”(读写)为了读和写打开一个文本文件出错read and write
w+”(读写)为了读和写创立一个新的文件创立一个新的文件read and write
a+”(读写)打开文件在文件尾部进行读写创立一个新的文件
"rb+(读写)为了读和写打开一个二进制文件出错|
"wb+(读写)为了读和写新建一个二进制文件创立一个新文件|
ab+”(读写)打开一个二进制文件在末尾进行读和写创立一个新的文件|

示例

#include<stdio.h>//文件的打开与关闭int main()
{FILE* pf;pf = fopen(&#", "r");if (pf == NULL){perror("fopen");return 1;}//对文件进行操作(省略)//关闭文件fclose(pf);pf = NULL;return 0;
}

这里我们对文件进行了只读操作,前提是我们必须有这个文件。


文件的顺序读写

fgetc()

读取一个字符。

int fgetc ( FILE * stream );

  • stream 表示指向文件的指针。
  • 函数返回的是所获取字符的 ASCⅡ码;如果直接指向文件的末尾或者获取失败,将返回 EOF.
//文件的顺序读写//fgetc()
int main()
{//打开文件FILE* pf;pf = fopen(&#", "r");if(pf == NULL){perror("fopen");return 1;}//获取字符char a;a = fgetc(pf);printf("%c", a);//关闭文件fclose(pf);pf = NULL;return 0;
}

结果展示

我们使用的是相对地址打开的文件,所以在与源文件相同目录的文件夹下, < 文件必须存在

fputc()

写一个字符到 stream 。

int fputc ( int character, FILE * stream );

  • character 可以填字符的 ASCⅡ码或’字符’
  • stream 是文件的指针。
  • 返回值:如果成功,将返回 character 的 ASCⅡ值;如果失败,将会返回 EOF,同时错误码会被设置,可以用 perror 查看错误信息。
//fputc
int main()
{//打开文件FILE* pf;pf = fopen(&#", "w");if(pf == NULL){perror("fopen");return 1;}//输出字符fputc('h', pf);//关闭文件fclose(pf);pf = NULL;return 0;
}

结果展示


这里我们使用的仍然是相对地址,在源文件相同目录下,必须有 文件,如果没有系统将会自动创建空白文件。如果文件存在,文件原有内容将会被清空( “w" 是只写)。

fgets()

读取多个字符从 stream 。

char * fgets ( char * str, int num, FILE * stream );

  • str 是将获取字符所要放的位置
  • num 是获取字符的个数
  • 返回值:如果读取成功,将会返回 str 的地址;如果文件内字符不足 num ,将会设置 EOF 指示符;如果在读取任何字符之前遇到EOF,将会返回 NULL;如果读取错误,将会设置错误码,并返回 NULL
//fgets
int main()
{//打开文件FILE* pf;pf = fopen(&#", "r");if(pf == NULL){perror("fopen");return 1;}//获取字符char arr1[20];char arr2[20];fgets(arr1, 20, pf);fgets(arr2, 20, pf);printf("%s", arr1);printf("%s", arr2);//关闭文件fclose(pf);pf = NULL;return 0;
}

结果展示

fputs()

写多个字符到 stream 。

int fputs ( const char * str, FILE * stream );

  • str 为要输出的字符串的地址
  • 返回值:如果输出成功,将返回非负值;如果输出失败,将返回 EOF 并设置错误码。
//fputs
int main()
{//打开文件FILE* pf;pf = fopen(&#", "w");if (pf == NULL){perror("fopen");return 1;}//输出字符fputs("hello world!n", pf);fputs("ni hao!n", pf);//关闭文件fclose(pf);pf = NULL;return 0;
}

结果展示

当在本目录下没有 此文件时,系统将自动创建;在我们以 “w”(只写) 的方式打开文件时,如果原文件存在内容将会被清空,来存放新的内容。

fwrite

以二进制的形式写数据到 stream .

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

  • ptr 为所要写的数据的首地址
  • size 为每个元素的大小
  • count 为元素的个数
  • 返回值:如果成功,将返回被写的元素的个数;如果 size 或 count 为0,将会返回0,不会设置错误码;如果返回的值和 count 不相等,将会阻止函数完成,并且设置错误码。
//fwrite
struct s
{char name[20];char id[15];int age;
};int main()
{//打开文件FILE* pf;pf = fopen(&#", "wb");if (pf == NULL){perror("fopen");return 1;}//写入文件//struct s s1 = { "xiaoming", "102030", 11 };//struct s s2 = { "xiaohong", "102031", 12 };//fwrite(&s1, sizeof(s1), 1, pf);//fwrite(&s2, sizeof(s2), 1, pf);struct s s1[2] = { {"xiaoming", "102030", 11}, {"xiaohong", "102031", 12} };fwrite(s1, sizeof(struct s), 2, pf);//关闭文件fclose(pf);pf = NULL;return 0;
}

结果展示

它以二进制的形式写入,我们以记事本的形式打开时,有些数据是不能被解读的。

fread

以二进制的形式,对文件的内容进行读取

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

  • ptr 数据要存放空间的首地址,空间的大小至少为 size*count ;
  • size 为每个元素的大小
  • count 为元素的个数
  • 返回值:如果成功,将返回被读取的元素的个数;如果 size 或 count 为0,将会返回0,不会设置错误码;如果返回的值和 count 不相等,表示读取错误或到文件的末尾,会设置错误码。
//fread
struct s
{char name[20];char id[15];int age;
};int main()
{//打开文件FILE* pf;pf = fopen(&#", "rb");if (pf == NULL){perror("fopen");return 1;}//读取文件struct s s1[2];fread(s1, sizeof(struct s), 2, pf);printf("%-20s  %-15s  %2dn", s1[0].name, s1[0].id, s1[0].age);printf("%-20s  %-15s  %2dn", s1[1].name, s1[1].id, s1[1].age);//关闭文件fclose(pf);pf = NULL;return 0;
}

结果展示

在这里,记事本无法解读的数据,在 fread() 函数的配合下能够轻松解读。

fscanf

从流中读取格式化信息。

int fscanf ( FILE * stream, const char * format, … );

  • format 表示读取字符的格式
  • 后面的 … 表示地址,将读取到的内容放入其中;
  • 返回值:请参考cplusplus;
//fscanf
int main()
{char name[20];char id[15];//打开文件FILE *pf = fopen(&#", "r");if (pf == NULL){perror("fopen");return 1;}//操作fscanf(pf, "%s", name);fscanf(pf, "%s", id);printf("%s  %s", name, id);//关闭文件fclose(pf);pf = NULL;return 0;}
* 

结果展示

此函数的使用方式请参考 scanf() 两者用法基本相同。
如:scanf(“%s %s”, name, id);
fscanf(pf, “%s %s”, name, id);
两者的参数只是 fscanf 多了一个文件指针。

fprintf

写入格式化的信息到流中。

int fprintf ( FILE * stream, const char * format, … );

  • format 表示要写的字符的格式
  • 后面的 … 表示要输出的内容;
  • 返回值:请参考cplusplus;
//fprintf
int main()
{char name[20] = "xiaoming";char id[15] = "102030";//打开文件FILE* pf = fopen(&#", "w");if (pf == NULL){perror("fopen");return 1;}//操作fprintf(pf, "%st", name);fprintf(pf, "%st", id);//关闭文件fclose(pf);pf = NULL;return 0;
}

结果展示

此函数的用法同样可以参考 printf();如:
printf(“%s %s”, name, id);
fprintf(pf, “%s %s”, name, id);
第二个函数的参数只是相对于第一个多了一个文件指针。

sscanf

读格式化的信息从字符串中。

int sscanf ( const char * s, const char * format, …);

  • s 表示字符串
  • format 表示参数的格式
  • 返回值:返回参数列表中成功填充的项,如果成功,返回值应与预期的项数相等,失败则少于预期的项数;如果在成功解释任何参数之前就失败,则返回 EOF
//sscanf
int main()
{char arr[] = "xiaoming 20";char name[20];int age = 0;sscanf(arr, "%s %d", name, &age);printf("%s %d", name, age);return 0;
}

结果展示
此函数的用法与 scanf() 用法基本相同。但是只是多了一个需要被读的 arr 字符串。

sprintf

写格式化的数据到字符串中。

int sprintf ( char * str, const char * format, … );

  • str 存放字符串的指针,所指的空间要足够大;
  • 返回值:成功后,将返回写入的字符总数。此计数不包括自动追加到字符串末尾的其他空字符。
    失败时,将返回负数。
//sprintf
int main()
{char arr[30];char name[10] = "xiaoming";int age = 20;char id[10] = "102030";sprintf(arr, "%s %d %s", name, age, id);printf("%s", arr);return 0;
}

结果展示

此函数的用法和 printf() 的用法基本相同,只不过多了一个字符串 arr .

思考题

scanf/sscanf/fscanf
printf/sprintf/fprintf 的区别在哪里?

答案
scanf 是从键盘上直接读取数据;
sscanf 是从字符串中读取数据;
fscanf 是从文件中读取数据。
printf 是直接在屏幕上打印内容;
sprintf 是将内容写入字符串中;
fprintf 是将内容写入文件中。


总结

看到这里希望大家多多支持与关注。你的点赞是我创作的动力。

本文发布于:2024-02-01 18:06:49,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170678226238497.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:语言   操作   文件
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23