磁盘上的文件是文件。 但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)。
包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境 后缀为.exe)。
文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件, 或者输出内容的文件。
缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名 字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统 声明的,取名FILE.
一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。
下面我们可以创建一个FILE*的指针变量:
FILE* pf;//文件指针变量
文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。
在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指 针和文件的关系。
ANSIC 规定使用fopen函数来打开文件,fclose来关闭文件
//打开文件
FILE * fopen ( const char * filename, const char * mode );
//关闭文件
int fclose ( FILE * stream ); 比特
- #include
- #include
-
- int main()
- {
- //打开文件test.txt
- //相对路径
- //.. 表示上一级路径
- //. 表示当前路径
- //fopen("../../test.txt", "r")
- //fopen("test.txt", "r");
-
- //绝对路径的写法【添加转义字符】
- //fopen("C:\\2020_code\\84班\\test_5_6\\test_5_6\\test.txt", "r");
-
- FILE* pf = fopen("test.txt", "w");
- if(pf == NULL)
- {
- printf("%s\n", strerror(errno));
- return 0;
- }
- //打开成功
- //读文件
-
- //关闭文件
- fclose(pf);
- pf = NULL;
-
- return 0;
- }
操作一行
- int main()
- {
- FILE* pfWrite = fopen("TEST.txt", "w");
- if(pfWrite == NULL)
- {
- printf("%s\n", strerror(errno));
- return 0;
- }
- //写文件
- fputc('b', pfWrite);
- fputc('i', pfWrite);
- fputc('t', pfWrite);
-
- //关闭文件
- fclose(pfWrite);
- pfWrite = NULL;
-
- return 0;
- }
操作一行
- int main()
- {
- FILE* pfRead = fopen("test.txt", "r");
- if(pfRead == NULL)
- {
- printf("%s\n", strerror(errno));
- return 0;
- }
- //读文件
- printf("%c", fgetc(pfRead));//b
- printf("%c", fgetc(pfRead));//i
- printf("%c", fgetc(pfRead));//t
-
- //关闭文件
- fclose(pfRead);
- pfRead = NULL;
-
- return 0;
- }
从键盘输入
输出到屏幕.
键盘&屏幕都是外部设备【默认打开的】键盘-标准输入设备- stdin
屏幕-标准输出设备- stdout
是一个程序默认打开的两个流设备stdin FILE*
stdout FILE*
stderr FILE*
- int main()
- {
- int ch = fgetc(stdin);
- fputc(ch, stdout);
-
- return 0;
- }
操作多行
- int main()
- {
- char buf[1024] = { 0 };
-
- FILE* pf = fopen("test.txt", "r");
- if (pf == NULL)
- {
- return 0;
- }
- //读文件
- //表示从pf输入流中读取1024个字节到buf中
- fgets(buf, 1024, pf);
- printf("%s", buf);//bit
-
- return 0;
- }
要手动换行
- int main()
- {
- char buf[1024] = { 0 };
-
- FILE* pf = fopen("test.txt", "w");
- if (pf == NULL)
- {
- return 0;
- }
- //写文件
- fputs("hello\n", pf);
- fputs("world\n", pf);
-
-
- fclose(pf);
- pf = NULL;
-
- return 0;
- }
- int main()
- {
- //从键盘读取一行文本信息
- //char buf[1024] = {0};
- fgets(buf, 1024, stdin);//从标准输入流读取
- fputs(buf, stdout);//输出到标准输出流
-
- //gets(buf);
- //puts(buf);
-
- return 0;
- }
会自动换行
- struct S
- {
- int n;
- float score;
- char arr[10];
- };
-
- int main()
- {
- struct S s = { 100, 3.14f, "bit" };
- FILE* pf = fopen("test.txt", "w");
- if (pf == NULL)
- {
- return 0;
- }
- //格式化的形式写文件
- fprintf(pf, "%d %f %s", s.n, s.score, s.arr);
-
- fclose(pf);
- pf = NULL;
- return 0;
- }
- struct S
- {
- int n;
- float score;
- char arr[10];
- };
-
- int main()
- {
- struct S s = {0};
-
- FILE* pf = fopen("test.txt", "r");
- if (pf == NULL)
- {
- return 0;
- }
- //格式化的输入数据
- fscanf(pf, "%d %f %s", &(s.n), &(s.score), s.arr);
- printf("%d %f %s\n", s.n, s.score, s.arr);
-
- fclose(pf);
- pf = NULL;
- return 0;
- }
- struct S
- {
- int n;
- float score;
- char arr[10];
- };
-
- int main()
- {
- struct S s = { 0 };
-
- fscanf(stdin, "%d %f %s", &(s.n), &(s.score), s.arr);
- fprintf(stdout, "%d %.2f %s", s.n, s.score, s.arr);
-
- return 0;
- }
- int main()
- {
- struct S s = { 100, 3.14f, "abcdef" };
- struct S tmp = {0};
- char buf[1024] = { 0 };
- //把格式化的数据转换成字符串存储到buf
- sprintf(buf, "%d %f %s", s.n, s.score, s.arr);
- //printf("%s\n", buf);
- //从buf中读取格式化的数据到tmp中
- sscanf(buf, "%d %f %s", &(tmp.n), &(tmp.score), tmp.arr);
-
- printf("%d %f %s\n", tmp.n, tmp.score, tmp.arr);
-
- return 0;
- }
- //fwrite:将数据以二进制的形式写入
- int main()
- {
- struct S s = { "张三", 20, 55.6 };
-
- FILE* pf = fopen("test.txt", "rb");
- if (pf == NULL)
- {
- return 0;
- }
- //二进制的形式都文件
- //表示将s中的数据写入到pf中
- fwrite(&s, sizeof(struct S), 1, pf);
- printf("%s %d %lf\n", &s.name, &s.age, &s.score);
-
- fclose(pf);
- pf = NULL;
- return 0;
- }
- //fread:通过二进制的方式输出数据
- int main()
- {
- struct S tmp = { 0 };
-
- FILE* pf = fopen("test.txt", "rb");
- if (pf == NULL)
- {
- return 0;
- }
- //二进制的形式都文件
- //表示将pf中的数据写到tmp中
- fread(&tmp, sizeof(struct S), 1, pf);
- printf("%s %d %lf\n", tmp.name, tmp.age, tmp.score);
-
- fclose(pf);
- pf = NULL;
- return 0;
- }
根据文件指针的位置和偏移量来定位文件指针
int fseek ( FILE * stream, long int offset, int origin );
- int main()
- {
- FILE* pf = fopen("test.txt", "r");
- if (pf == NULL)
- {
- return 0;
- }
- //1.定位文件指针
- //fseek(要读取的文件,移动的字节数,起始位置)
- //SEEK_END:表示向前移动2个位置
- fseek(pf, -2, SEEK_END);
- //2.读取文件
- int ch = fgetc(pf);
- printf("%c\n", ch);
-
- fclose(pf);
- pf = NULL;
-
- return 0;
- }
返回文件指针相对于起始位置的偏移量
long int ftell ( FILE * stream );
- //ftell:返回文件指针相对于起始位置的偏移量
- int main()
- {
- FILE* pf = fopen("test.txt", "r");
- if (pf == NULL)
- {
- return 0;
- }
- //2.读取文件
- int post = ftell(pf);
- printf("%d\n", post);//打开默认地址为0
-
- fclose(pf);
- pf = NULL;
-
- return 0;
- }
- int main()
- {
- FILE* pf = fopen("test.txt", "r");
- if (pf == NULL)
- {
- return 0;
- }
- //此时读取一个字符,则表示跳过第一个字符
- fgetc(pf);
- //2.读取文件
- int post = ftell(pf);
- printf("%d\n", post);//故此时输出为1
-
- fclose(pf);
- pf = NULL;
-
- return 0;
- }
让文件指针的位置回到文件的起始位置
void rewind ( FILE * stream );
- //rewind:回到文件的起始位置
- int main()
- {
- FILE* pf = fopen("test.txt", "r");
- if (pf == NULL)
- {
- return 0;
- }
- int ch = fgetc(pf);
- printf("%c\n", ch);//读取出a
- rewind(pf);//返回原来的位置
- ch = fgetc(pf);
- printf("%c\n", ch);//读取出a
-
- fclose(pf);
- pf = NULL;
-
- return 0;
- }
feof:是用于判断文件读取结束的原因
- /*
- 文本文件读取结束:fgetc:pf==EOF
- fgets:pf=null
- 二进制文件读取结束:fread判断返回值是否小于实际要读的个数
- */
- int main()
- {
- //EOF
- //feof();//EOF - end of file - 文件结束标志
- FILE* pf = fopen("test.txt", "r");
- if (pf == NULL)
- return 0;
- int ch = fgetc(pf);
- printf("%d\n", ch);//-1
-
- fclose(pf);
- pf = NULL;
-
- return 0;
- }
-
- /*
- strerror:把错误码对应的错误信息的字符串地址返回
- peerror(s):参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。
- */
- int main()
- {
- //strerror - 把错误码对应的错误信息的字符串地址返回
- //printf("%s\n", strerror(errno));
-
- //perror
- FILE* pf = fopen("test2.txt", "r");
- if (pf == NULL)
- {
- perror("open file test2.txt");//open file test2.txt:No such file or directory
- return 0;
- }
- //读文件
-
- fclose(pf);
- pf = NULL;
-
- return 0;
- }
C语言 | perror函数使用详解_c语言线程perror_嵌入式大杂烩的博客-CSDN博客
- struct {
- int a;//0-3 4字节
- char b;//4 1字节
- short c;//6-7 2字节【因为是2字节,所以要使用2的倍数】
- short d;//8-9 2字节【因为是2字节,所以要使用2的倍数】
- };//10字节
- //所以我们应该直接+到12字节【地址为12-->(1,2,4)的最大倍数】
- struct A
- {
- int a;//0-3
- short b;//4-5
- //6-7
- int c;//8-11
- char d;//12
- //13 14 15
- };//13 -- > 16【(1,2,4)的最大倍数】
-
- struct B
- {
- int a;//0-3
- short b;//4-5
- char c;//6
- //7
- int d;//8-11
- };//12【(1,2,4)的最大倍数】
-
- int main()
- {
- printf("%d\n", sizeof(struct A));//16
- printf("%d\n", sizeof(struct B));//12
-
- return 0;
- }
- #pragma pack(4)/*编译选项,表示4字节对齐 平台:VS2013。语言:C语言*/
- int main(int argc, char* argv[])
- {
- struct tagTest1
- {
- short a;//0-1
- char d;//2
- 3
- long b;//4-7
- long c;//8-11
- };//12
- struct tagTest2
- {
- long b;//0-3
- short c;//4-5
- char d;//6
- 7
- long a;//8-11
- };//12
-
- struct tagTest3
- {
- short c;//0-1
- 2 3
- long b;//4-7
- char d;//8
- 9-11
- long a;//12-15
- };//16
- struct tagTest1 stT1;
- struct tagTest2 stT2;
- struct tagTest3 stT3;
-
- printf("%d %d %d", sizeof(stT1), sizeof(stT2), sizeof(stT3));
- return 0;
- }
- #pragma pack()