文件的打开和关闭
fopen / fclose函数
-
fopen第一个参数接收打开的文件的名称的字符串,第二个参数接收的是打开文件的方式
- 打开文件的方式:
-
r 只读文件 文件不存在时报错
-
w 只写文件 文件不存在时新建 文件存在时覆盖
-
a 追加文件(只写) 文件不存在时新建 文件存在时在原有文件后追加
-
r+ 读写文件 文件不存在时报错 存在时打开
-
w+ 读写文件 文件不存在时新建 文件存在时覆盖
-
a+ 追加文件(读写) 文件不存在时新建 文件存在时在原有文件后追加
-
- 返回值:指向文件缓冲区的指针,该指针操作文件的句柄
- 打开文件的方式:
-
fclose接收一个参数
-
参数是指向文件缓冲的指针
-
返回值:int 成功返回 0 ,失败返回 EOF(-1)。
-
文件的读写(文本文件操作)
一次性写一个字符(fputc)
-
int fputc (int ch, FILE * stream );//函数声明
-
接收两个参数
1.第一个参数是写入的字符
2.第二个参数是指向文件缓冲的指针
-
返回值:int 写入成功,返回写入成功字符,如果失败,返回 EOF。
-
注意点:
1.不会在写入数据的后面添加\n
2.写入的时候遇到\0就会自动停止写入
代码如下:
// 1.打开一个文件
FILE *fp = fopen("test.txt", "w+");
// 2.往文件中写入内容
for(char ch = 'a'; ch <= 'z'; ch++){
// 一次写入一个字符
char res = fputc(ch, fp);
printf("res = %c\n", res);
}
// 3.关闭打开的文件
fclose(fp);
一次性读一个字符(fgetc)
-
int fgetc ( FILE * stream );//声明
-
参数:文件缓冲的指针
-
注意点:返回文件缓冲指针指向地址的那个字节,写入文件后文件缓冲的指针需要归位
-
返回值:int 正常,返回读取的字符;读到文件尾或出错时,为 EOF。
// 1.打开一个文件
FILE *fp = fopen("test.txt", "r+");
// 2.从文件中读取内容
char res = EOF;
while((res = fgetc(fp)) != EOF){
printf("res = %c\n", res);
}
// 3.关闭打开的文件
fclose(fp);
一次性写一行字符(fputs)
-
int fputs(char *str,FILE *fp)
-
第一个参数: 表示指向的字符串的指针。
-
第二个参数: 表示指向文件流结构的指针
-
返回值:int 正常,返 0;出错返 EOF。
{
FILE *fw = fopen("test.txt", "w+");
// 注意: fputs不会自动添加\n
fputs("lnj\n", fw);
fputs("it666\n", fw);
fclose(fw);
return 0;
}
-
一次性读一行字符(fgets)
-
char *fgets(char *str,int length,FILE *fp)
-
第一个参数: 指向需要读入数据的缓冲区。
-
第二个参数: 每一次读数字符的字数。
-
第三个参数: 指向文件流结构的指针
-
返回值:char * 正常,返 str 指针;出错或遇到文件结尾 返空指针 NULL。
-
-
注意点:
1.最多只能读取N-1个字符,最后自己添加\02.读取到\n或者EOF自动结束
文件的读写(二进制文件操作)
一次性写入一块数据(fwrite)
-
int fwrite(void *buffer, int num_bytes, int count, FILE *fp)
-
第一个参数:指向要写入数据存储区的首地址的指针
-
第二个参数:一次读取的字节数
-
第三个参数:读取的次数
-
第四个参数:文件流结构的指针
-
返回值:int 成功,返回写的字段数;出错或文件结束,返回 0
FILE *fp = fopen("test.txt", "wb+");
// 注意: fwrite不会关心写入数据的格式
char *str = "lnj\0it666";
/*
* 第一个参数: 被写入数据指针
* 第二个参数: 每次写入多少个字节
* 第三个参数: 需要写入多少次
* 第四个参数: 已打开文件结构体指针
*/
fwrite((void *)str, 9, 1, fp);
fclose(fp);
一次读取一块数据
-
int fread(void *buffer, int num_bytes, int count, FILE *fp)
-
第一个参数:读取后存放的地址
-
第二个参数:一次读取的字节数
-
第三个参数:读取的次数
-
第四个参数:已打开文件结构体指针
-
返回值: int 成功,返回读的字段数;出错或文件结束,返回 0。
-
注意点:
1.读取时num_bytes应该填写读取数据类型的最小单位, 而count可以随意写
2.如果读取时num_bytes不是读取数据类型最小单位, 会引发读取失败
读写结构体
- 读写结构体数组
#include <stdio.h>
typedef struct{
char name[5];
int age;
double height;
} Person;
int main()
{
Person ps[] = {
{"zs", 18, 1.65},
{"ls", 21, 1.88},
{"ww", 33, 1.9}
};
FILE *fp = fopen("person.stu", "wb+");
fwrite(&ps, sizeof(ps), 1, fp);
rewind(fp);
Person p;
while(fread(&p, sizeof(p), 1, fp) > 0){
printf("name = %s\n", p.name);
printf("age = %i\n", p.age);
printf("height = %lf\n", p.height);
}
return 0;
}
- 读写结构体链表
#include <stdio.h>
#include <stdlib.h>
typedef struct person{
char name[5];
int age;
double height;
struct person* next;
} Person;
Person *createEmpty();
void insertNode(Person *head, char *name, int age, double height);
void printfList(Person *head);
int saveList(Person *head, char *name);
Person *loadList(char *name);
int main()
{
// Person *head = createEmpty();
// insertNode(head, "zs", 18, 1.9);
// insertNode(head, "ls", 22, 1.65);
// insertNode(head, "ws", 31, 1.78);
// printfList(head);
// saveList(head, "person.list");
Person *head = loadList("person.list");
printfList(head);
return 0;
}
/**
* @brief loadList 从文件加载链表
* @param name 文件名称
* @return 加载好的链表头指针
*/
Person *loadList(char *name){
// 1.打开文件
FILE *fp = fopen(name, "rb+");
if(fp == NULL){
return NULL;
}
// 2.创建一个空链表
Person *head = createEmpty();
// 3.创建一个节点
Person *node = (Person *)malloc(sizeof(Person));
while(fread(node, sizeof(Person), 1, fp) > 0){
// 3.进行插入
// 3.1让新节点的下一个节点 等于 头节点的下一个节点
node->next = head->next;
// 3.2让头结点的下一个节点 等于 新节点
head->next = node;
// 给下一个节点申请空间
node = (Person *)malloc(sizeof(Person));
}
// 释放多余的节点空间
free(node);
fclose(fp);
return head;
}
/**
* @brief saveList 存储链表到文件
* @param head 链表头指针
* @param name 存储的文件名称
* @return 是否存储成功 -1失败 0成功
*/
int saveList(Person *head, char *name){
// 1.打开文件
FILE *fp = fopen(name, "wb+");
if(fp == NULL){
return -1;
}
// 2.取出头节点的下一个节点
Person *cur = head->next;
// 3.将所有有效节点保存到文件中
while(cur != NULL){
fwrite(cur, sizeof(Person), 1, fp);
cur = cur->next;
}
fclose(fp);
return 0;
}
/**
* @brief printfList 遍历链表
* @param head 链表的头指针
*/
void printfList(Person *head){
// 1.取出头节点的下一个节点
Person *cur = head->next;
// 2.判断是否为NULL, 如果不为NULL就开始遍历
while(cur != NULL){
// 2.1取出当前节点的数据, 打印
printf("name = %s\n", cur->name);
printf("age = %i\n", cur->age);
printf("height = %lf\n", cur->height);
printf("next = %x\n", cur->next);
printf("-----------\n");
// 2.2让当前节点往后移动
cur = cur->next;
}
}
/**
* @brief insertNode 插入新的节点
* @param head 链表的头指针
* @param p 需要插入的结构体
*/
void insertNode(Person *head, char *name, int age, double height){
// 1.创建一个新的节点
Person *node = (Person *)malloc(sizeof(Person));
// 2.将数据保存到新节点中
node->name = name;
node->age = age;
node->height = height;
// 3.进行插入
// 3.1让新节点的下一个节点 等于 头节点的下一个节点
node->next = head->next;
// 3.2让头结点的下一个节点 等于 新节点
head->next = node;
}
/**
* @brief createEmpty 创建一个空链表
* @return 链表头指针, 创建失败返回NULL
*/
Person *createEmpty(){
// 1.定义头指针
Person *head = NULL;
// 2.创建一个空节点, 并且赋值给头指针
head = (Person *)malloc(sizeof(Person));
if(head == NULL){
return head;
}
head->next = NULL;
// 3.返回头指针
return head;
}
作者:极客江南
链接:https://www.jianshu.com/p/eb12558ae490
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
网友评论