嵌入式学习之路(十八)——C语言学习(13)
今天我们来讲讲文件操作,如果我们要把数据存起来,现在我们就要用文件存储
一。文件打开
要想对文件进行操作,必须先打开它,文件怎么打开呢?我们可以找男人(man),聊一下
FILE*fopen(const char *path, const char *mode);
这是男人(man)告诉我的结果:
从男人的话中中我们得到什么呢?
首先,fopen的返回值是一个文件指针,
打开失败则返回NULL
参数psth:是文件名称带路径
参数mode:是打开文件的方式:有读、写权限的组合
文本文件
r可读,文件头开始
r+可读可写,文件头开始
w可写,文件不存在则创建,存在则覆盖
w+可写可读,文件不存在则创建,存在则覆盖
a以追加的方式写,不存在则创建,每次写都强行写在文件的末尾
a+以追加的方式可写可读,不存在则创建,每次写都强行写在文件的末尾
二进制文件:
rb可读,文件头开始
rb+可读可写,文件头开始
wb可写,文件不存在则创建,存在则覆盖
wb+可写可读,文件不存在则创建,存在则覆盖
ab以追加的方式写,不存在则创建,每次写都强行写在文件的末尾
ab+以追加的方式可写可读,不存在则创建,每次写都强行写在文件的末尾
二。文件关闭
文件打开操作完成直购,肯定要关闭它,做事情要有头有尾,我们也着男人聊一下
intfclose(FILE *fp);
fclose是不是简单很多呢,给他一个文件指针就行了,返回的是什么呢?我们来看看
返回的是一个整形,0代表关闭成功。
三。文件的写操作
打开文件,我们必须要对他进行操作,我们也来找男人聊一下
size_tfwrite(const void *ptr,size_tsize,size_tnmemb,FILE*stream);
男人这次告诉我什么呢?
ptr:是一个void的指针,可以代表任何变量的指针,所以他是写入文件数据变量的地址
size:是写入一次的大小
nmemb:写入多少次
stream:文件指针
返回值:是写入的个数
四。文件读操作
说完写操作,必须也要看看读操作,还是找男人聊一下
size_tfread(void *ptr, size_t size, size_t nmemb, FILE *stream);
男人这次告诉我什么呢?
ptr:是一个void的指针,可以代表任何变量的指针,所以他是从文件中读到数据变量的地址
size:是读取一次的大小
nmemb:读取多少次
stream:文件指针
返回值:是读取出来的个数
四。文件的位置指针
说完读写操作,我们接下来看看文件的位置指针,还是找男人聊一下
long ftell(FILE *stream);
void rewind(FILE *stream);
int fseek(FILE *stream, long offset, int whence);
男人这次告诉我什么呢?
ftell()是一个可以获得当前文件位置指针的函数,
参数:给它一个文件指针,就可以返回一个位置,
rewind()是一个函数,可以将文件指针移动文件的开头
参数:给它一个文件指针,就可以移动位置指针到文件的开头
fseek()函数可以把位置指针调整到文件中的任何位置
参数:stream是文件指针
offset是偏移量,可正可负
whence:参考的位置,这里有三个选项
SEEK_SET:文件的开头位置0
SEEK_CUR:当前位置1
SEEK_END:文件的末尾位置2
返回值:成功返回0
失败返回-1
这个函数比较给力了,那么就可以想写哪里写哪里,哈哈哈,妈妈再也不担心啥啥啥了。
好像讲了这么多,没有实践,根本不知道从男人那里得到的消息是对是错,我们来验证一下
五。文件编程
为了都用上这些函数,然后再将上本人之前的放过的错误,来和大家来分享。我们就凑合着来写一个小程序吧。
程序功能描述:1.用户信息输入,包括id,name,sal
2.用户信息的读取,包括id,name,sal
3.输入id,修改指定用户的信息
我们先来描述一下程序的思路吧。
这边顺便把我们的ubuntu下用vi编写程序的多文件编写方式,也来说一下
首先定义一个结构体,来存储我们的id,name和sal
编写一个信息的输入函数,用来输入我们的信息
编写一个信息的读出函数,用来打印我们的信息
编写一个信息的修改函数,用来修改我们的信息
编写一个主函数,用来测试我们的功能
好了,开始啦
本人花了一点时间写的,因为博客的容量有限,格式不太正常,所以很多注释没写,大神,轻拍
大家可以自己先写一下,然后看看会出现什么问题,这样才会有所收获,祝大家好运!
程序分为3个文件分别为file.hfile.c main.c
1 /***************************
2 ** **
3 ** 文件名称:main.c **
4 ** 作者:紫瞳标 **
5 ***************************/
6 #include <stdio.h>
7 #include "file.h"
8 FILE *p_file = NULL;/*定义一个全局的文件指针*/
9 staff message;/*定义一个结构体变量*/
10 int main()
11 {
12 /*这边不考虑文件不存在的问题,默认文件已经存在*/
13 /*当然这个bug很好解决,这边就先不解决了*/
14 p_file = fopen("data.bin","r+b");/*打开文件*/
15 if(p_file != NULL)/*文件打开成功*/
16 {
17 system("clear");/*清屏*/
18 int flag = 0;
19 do
20 {
21 int num = 0;
22 printf("[1]输入新信息\n");
23 printf("[2]打印全部已经存在的信息\n");
24 printf("[3]修改某个员工的信息\n");
25 printf("[4]退出!\n");
26 scanf("%d",&num);
27 switch(num)
28 {
29 case 1:
30 {
31 put_in();/*输入新信息*/
32 break;
33 }
34 case 2:
35 {
36 get_out();/*打印全部信息*/
37 break;
38 }
39 case 3:
40 {
41 change();/*修改员工信息*/
42 break;
43 }
44 default:
45 {
46 flag = 1;/*退出标志位*/
47 break;
48 }
49 }
50 }
51 while(!flag);
52 fclose(p_file);/*关闭文件*/
53 p_file = NULL;/*置NULL,防止变成野指针*/
54 }
55 return 0;
56 }
1 /*****************************
2 **
3 ** 文件名称: file.c
4 ** 作者:紫瞳标
5 *****************************/
6 #include <stdio.h>
7 #include "file.h"
8 void put_in()
9 {
10 printf("请输入你的id\n");
11 scanf("%d",&message.id);
12 printf("请输入你的姓名\n");
13 scanf("%s",message.name);
14 printf("请输入你的工资\n");
15 scanf("%lf",&message.sal);
16 /*得到信息后,写入文件中*/
17 fseek(p_file,0,SEEK_END);/*移动到文件的末尾,以追加方式写入*/
18 fwrite(&message.id,sizeof(int),1,p_file);
19 fwrite(message.name,sizeof(char),20,p_file);
20 fwrite(&message.sal,sizeof(double),1,p_file);
21 /*这边可以直接用结构体的,但是为了演示,先分开写入*/
22 }
23 void get_out()
24 {
25 rewind(p_file);/*移动位置指针到开头*/
26 int res = 0;
27 int num = 0;
28 while(res = fread(&message,sizeof(staff),1,p_file))
29 {
30 num++;
31 printf("----------我是分割线----------\n");
32 printf("第%d个员工的id是%d\n",num,message.id);
33 printf("第%d个员工的名字是%s\n",num,message.name);
34 printf("第%d个员工的工资是%g\n",num,message.sal);
35 printf("----------我是分割线----------\n");
36 }
37 }
38 void change()
39 {
40 int num = 0;
41 printf("你要修改第几个员工的信息\n");
42 scanf("%d",&num);
43 rewind(p_file);/*移动到开头*/
44 fseek(p_file,sizeof(staff) * (num-1),SEEK_SET);/*寻找到第n个员工*/
45 fread(&message,sizeof(staff),1,p_file);
46
47 printf("----------我是分割线----------\n");
48 printf("第%d个员工的id是%d\n",num,message.id);
49 printf("第%d个员工的名字是%s\n",num,message.name);
50 printf("第%d个员工的工资是%g\n",num,message.sal);
51 printf("----------我是分割线----------\n");
52
53 printf("请重新输入你的id\n");
54 scanf("%d",&message.id);
55 printf("请重新输入你的姓名\n");
56 scanf("%s",message.name);
57 printf("请重新输入你的工资\n");
58 scanf("%lf",&message.sal);
59 fseek(p_file, -(sizeof(staff)),SEEK_CUR);/*向前移动一个结构体位置*/
60 fwrite(&message,sizeof(staff),1,p_file);
61 printf("修改成功\n");
62 }
1 /*****************************
2 **
3 ** 文件名称: file.h
4 ** 作者:紫瞳标
5 *****************************/
6 #ifndef __FILE_H__
7 #define __FILE_H__
8
9 typedef struct {
10 int id;
11 char name[20];
12 double sal;
13 }staff;
14 extern FILE *p_file;
15 extern staff message;
16
17 void put_in(void);
18 void get_out(void);
19 void change(void);
20
21 #endif