目录
一.为什么使用文件
二.什么是文件
三.文件的打开和关闭
四.文件的顺序读写
五.文件的随机读写
六.文本文件的二进制文件
七.文件读取结束的判定
八.文件缓存冲区
九.通讯录
一.为什么使用文件
简单来说:让数据持久化
二.什么是文件
磁盘上的文件是文件--程序设计中,我们一般谈的文件有两种:~程序文件~数据文件(从文件功能的角度来分类的)
1.程序文件:
包括源文件(后缀.c) , 目标文件(windows环境后缀.obj) ,可执行程序(windows环境后缀.exe)
2.数据文件:
文件的内容不一定是程序,而是程序运行时读写的数据
3.文件名:
包含三部分:文件路径+文件名主干+文件后缀
ex:C:\code\text.txt
三.文件的打开和关闭
1.文件指针:
缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。 这些信息是保存在一个结构体变量中的。 该结构体类型是有系统 声明的,取名FILE
不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异。
一般都是通过一个FILE的指针来维护这个 FILE 结构的变量,这样使用起来更加方便。
下面我们可以创建一个 FILE* 的指针变量 :
FILE* pf
文件指针变量
通过文件指针变量能够找到与它关联 文件 。
四.文件的顺序读写
接下来,让我来 带你们康康到底怎么用这几个函数
咱们浅浅举一个例子: fputs
之后其实 大同小异!
这样 代码给你 你自行探索!冲
#include
//文件流
//标准输入流 stdin 键盘
//标准输出流 stdout 屏幕
//标准错误流 stderr 屏幕
struct S
{
char name[20];
int age;
double d;
};
int main()
{
fread
//struct S s = { 0 };
//FILE* pf = fopen("text.txt", "rb");
//if (pf == NULL)
//{
// perror("fopen");
//}
//fread(&s, sizeof(struct S), 1, pf);
//printf("%s %d %lf", s.name, s.age, s.d);
//fclose(pf);
//pf = NULL;
fwrite
//struct S s = { "张三",20,95.5 };
//FILE* pf = fopen("text.txt", "wb");
//if (pf == NULL)
//{
// perror("fopen");
//}
//fwrite(&s, sizeof(struct S), 1, pf);
//fclose(pf);
//pf = NULL;
sprintf sscanf
//char buf[256] = { 0 };
//struct S s = { "zhang",20,98.8 };
//struct S tmp = { 0 };
//sprintf(buf,"%s %d %lf", s.name, s.age, s.d);
//printf("%s\n",buf);//字符串
//sscanf(buf, "%s %d %lf", tmp.name, &(tmp.age), &(tmp.d));
//printf("%s %d %lf", tmp.name, tmp.age, tmp.d);//格式化形式打印
fscanf
//struct S s = { 0 };
//FILE* pf = fopen("text.txt", "r");
//if (pf == NULL)
//{
// perror("fopen");
//}
//fscanf(pf, "%s %d %lf", s.name, &(s.age), &(s.d));
printf("%s %d %lf", s.name, s.age, s.d);
//fprintf(stdout,"%s %d %lf", s.name, s.age, s.d);
//fclose(pf);
//pf = NULL;
fprintf
//struct S s = { "张三",20,95.5 };
//FILE* pf = fopen("text.txt", "w");
//if (pf == NULL)
//{
// perror("fopen");
//}
//fprintf(pf, "%s %d %lf", s.name, s.age, s.d);
//fclose(pf);
//pf = NULL;
fgets
//char arr[256] = { 0 };
//FILE* pf = fopen("text.txt", "r");
//if (pf == NULL)
//{
// perror("fopen");
//}
///*fgets(arr,256,pf);
//printf("%s", arr);*/
//while (fgets(arr, 256, pf) != NULL)
//{
// printf("%s", arr);
//}
//fclose(pf);
//pf = NULL;
fputs
//FILE* pf = fopen("text.txt", "w");
//if (pf == NULL)
//{
// perror("fopen");
//}
//fputs("aancannfiqnf", pf);
//fclose(pf);
//pf = NULL;
从键盘上读 fgetc
//int ch = fgetc(stdin);
//printf("%c\n", ch);
//fputc(ch, stdout);
//fgetc
//FILE* pf = fopen("text.txt", "r");
//if (pf == NULL)
//{
// perror("fopen");
// return 1;
//}
读文件 - 输入 *** 作
//int ch = 0;
//while ((ch = fgetc(pf)) != EOF)
//{
// printf("%c ", ch);
//}
//fclose(pf);
//pf = NULL;
fputc
打开文件
//FILE* pf = fopen("text.txt", "w");
FILE* pf = fopen("C:\\A\\text.txt", "w");
//if (pf == NULL)
//{
// perror("fopen");
// return 1;
//}
读文件 输出 *** 作
fputc('a', pf);
//char ch = 'a';
//for (ch = 'a'; ch <= 'z'; ch++)
//{
// fputc(ch, pf);
//}
关文件
//fclose(pf);
//pf = NULL;
return 0;
}
最后 让我们对比几个函数
五.文件的随机读写
介绍三个函数 ~fseek~ftell~rewind
//fseek ftell rewind
FILE* pf = fopen("text.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件 -
fputc('a', pf);
fputc('b', pf);
fputc('c', pf);
fputc('d', pf);
fseek(pf, -3, SEEK_CUR);
fputc('w', pf);
long pos = ftell(pf);
printf("%ld\n", pos);
rewind(pf);
pos = ftell(pf);
printf("%ld\n", pos);
fclose(pf);
pf = NULL;
//FILE* pf = fopen("text.txt", "r");
//if (pf == NULL)
//{
// perror("fopen");
// return 1;
//}
读文件 -
//fseek(pf, 2, SEEK_CUR);
//int ch = fgetc(pf);
//printf("%c\n", ch);
//
//fclose(pf);
//pf = NULL;
//
六.文本文件的二进制文件
根据数据的组织形式,数据文件被称为文本文件 或者 二进制文件 。数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件 。
如果要求在外存上以ASCII 码的形式存储,则需要在存储前转换。
以
ASCII 字符的形式存储的文件就是 文 本文件 。一个数据在内存中是怎么存储的呢? 字符一律以ASCII形式存储,数值型数据既可以用 ASCII形式存储,也可以使用二进制形式存储
七.文件读取结束的判定
牢记:在文件 读取过程 中,不能用feof 函数的返回值直接用来判断文件的是否结束。1. 文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets ) 2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
八.文件缓存冲区
因为有缓冲区的存在,C 语言在 *** 作文件的时候,需要做刷新缓冲区或者在文件 *** 作结束的时候关闭文 件。如果不做,可能导致读写文件的问题
九.通讯录
contact.h
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
//类型的声明
#define MAX 1000
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
//通讯录初始状态的容量大小
#define DEFAULT_SZ 3
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SORT,
PRINT
};
typedef struct PeoInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tele[TELE_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//动态的版本
typedef struct Contact
{
PeoInfo* data;//可以存放1000个人的信息
int sz;//记录通讯中已经保存的信息个数
int capacity;//记录通讯录当前的最大容量
}Contact;
//函数的声明
//初始化通讯录
void InitContact(Contact* pc);
//销毁通讯录
void DestroyContact(Contact* pc);
//增加联系人的信息
void AddContact(Contact* pc);
//打印通讯录中的信息
void PrintContact(const Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//查找指定联系人
void SearchContact(const Contact* pc);
//修改
void ModifyContact(Contact* pc);
//排序
void SortContact(Contact* pc);
//3. 文件版本
//保存通讯录的信息到文件
void SaveContact(const Contact* pc);
contact.c
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
void CheckCapacity(Contact* pc)
{
//增容的代码
if (pc->sz == pc->capacity)
{
PeoInfo* tmp = (PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInfo));
if (tmp != NULL)
{
pc->data = tmp;
}
else
{
perror("CheckCapacity::realloc");
return;
}
pc->capacity += 2;
printf("增容成功\n");
}
}
void LoadContact(Contact* pc)
{
//打开文件
FILE* pf = fopen("contact.dat", "rb");
if (pf == NULL)
{
perror("LoadContact::fopen");
return;
}
//读文件
PeoInfo tmp = { 0 };
while (fread(&tmp, sizeof(PeoInfo), 1, pf))
{
CheckCapacity(pc);
pc->data[pc->sz] = tmp;
pc->sz++;
}
//关闭文件
fclose(pf);
pf = NULL;
}
//初始化通讯录 - 文件版本
void InitContact(Contact* pc)
{
assert(pc);
pc->sz = 0;
pc->capacity = DEFAULT_SZ;
pc->data = (PeoInfo*)malloc(pc->capacity * sizeof(PeoInfo));
if (pc->data == NULL)
{
perror("InitContact::malloc");
return;
}
memset(pc->data, 0, pc->capacity * sizeof(PeoInfo));
//加载文件信息到通讯录中
LoadContact(pc);
}
void DestroyContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
printf("销毁成功\n");
}
void AddContact(Contact* pc)
{
assert(pc);
//动态的版本
CheckCapacity(pc);
//录入信息
printf("请输入名字:>");
scanf("%s", pc->data[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("添加成功\n");
}
void PrintContact(const Contact* pc)
{
assert(pc);
int i = 0;
printf("%-20s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
for (i = 0; i < pc->sz; i++)
{
printf("%-20s %-5d %-5s %-12s %-30s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
}
}
//找到了返回下标
//找不到返回-1
int FindByName(const Contact* pc, char name[])
{
assert(pc);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (0 == strcmp(pc->data[i].name, name))
{
return i;
}
}
return -1;
}
void DelContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录已空,无法删除\n");
return;
}
//删除
//1. 找到
char name[NAME_MAX] = { 0 };
printf("请输入要删除人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要删除的人不存在\n");
return;
}
//2. 删除
int j = 0;
for (j = pos; j < pc->sz - 1; j++)
{
pc->data[j] = pc->data[j + 1];
}
pc->sz--;
printf("删除成功\n");
}
void SearchContact(const Contact* pc)
{
char name[NAME_MAX] = { 0 };
printf("请输入要查找人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
printf("%-20s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
printf("%-20s %-5d %-5s %-12s %-30s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex,
pc->data[pos].tele, pc->data[pos].addr);
}
void ModifyContact(Contact* pc)
{
assert(pc);
//1.找到
char name[NAME_MAX] = { 0 };
printf("请输入要修改人的姓名;>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
//2、修改
printf("请输入修改后名字;>");
scanf("%s", pc->data[pos].name);
printf("请输入修改后年龄;>");
scanf("%d", &(pc->data[pos].age));
printf("请输入修改后性别;>");
scanf("%s", pc->data[pos].sex);
printf("请输入修改后电话;>");
scanf("%s", pc->data[pos].tele);
printf("请输入修改后地址;>");
scanf("%s", pc->data[pos].addr);
printf("修改成功\n");
}
void SortContact(Contact* pc)
{
assert(pc);
//按名字字母顺序排序
int i = 0;
for (i = 0; i < pc->sz; i++)
{
int j = 0;
for(j = 0; j < pc->sz - 1 - i; j++)
{
int pos = strcmp(pc->data[j].name, pc->data[j + 1].name);
if (pos > 0);
{
PeoInfo tmp = pc->data[j];
pc->data[j ] = pc->data[j + 1];
pc->data[j + 1] = tmp;
}
}
}
printf("排序成功\n");
}
void SaveContact(const Contact* pc)
{
FILE* pf = fopen("contact.dat", "wb");
if (pf == NULL)
{
perror("SaveContact::fopen");
return;
}
//写文件
int i = 0;
for (i = 0; i < pc->sz; i++)
{
fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
}
text.c
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
void menu()
{
printf("***************************\n");
printf("**** 1.add 2.del ****\n");
printf("**** 3.search 4.modify ****\n");
printf("**** 5.sort 6.print ****\n");
printf("**** 0.exit ****\n");
printf("***************************\n");
}
void test()
{
int input = 0;
Contact con;
InitContact(&con);
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case ADD:
AddContact(&con);
break;
case DEL:
DelContact(&con);
break;
case SEARCH:
SearchContact(&con);
break;
case MODIFY:
break;
case SORT:
break;
case PRINT:
PrintContact(&con);
break;
case EXIT:
SaveContact(&con);
DestroyContact(&con);
printf("退出\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)