有时候程序运行后会有我们要操作的数据,或是存储的数据,例如我们前面所写的 通讯录程序,我们就需要存储联系人的信息,然而在程序运行完了之后,我们的信息就都会消失,因为我们的数据都在内存上。如果我们要永久性的存储需要存在外存上。这时候就到了C语言的文件操作登场了。
目录
文件的分类
文件是信息存储的基本单位。所以根据存储的方式不同可分为:
- 文本文件:看的懂的
- 二进制文件:看不懂的
文件指针
用一个指针变量指向一个文件,这个指针便是文件指针。我们通过指针对文件进行操作。
定义的方式为:
FILE* + 指针变量名
//C语言
FILE* fp;
文件基本操作
文件只有打开了才能进行操作,当然操作完之后你必须关闭文件。 因为程序打开文件个数是有限的!如果频繁打开文件,没有关闭便会是文件描述符泄露。
-
操作函数
- 打开:fopen(const char* path, const char* made)
path: 文件名称 made: 打开方式
- 读取:fread(const void* buffer, size_t size, size_t count, FILE* fp)
buffer:存放输入数据首地址 size * count:整个数组大小 fp:文件指针
- 写入:fwrite(const void* buffer, size_t size, size_t count, FILE* fp)
buffer:存放输出数据首地址 size * count:整个数组大小 fp:文件指针
- 关闭:fclose(FILE* fp)
-
文件名称
文件名=文件目录 + 文件名
文件的打开实在源代码的路径下。
如果在源代码的路径下创建了 test.txt
./test.txt 表示当前文件夹内
../test.txt 表示上一级的文件夹内
-
文件打开方式
"r"(只读) | 为输入打开一个文本文件 |
"w"(只写) | 为输出打开一个文本文件 |
"a"(追加) | 向文件文件尾添加数据 |
"r+"(读写) | 为读写打开一个文本文件 |
"w+"(读写) | 为读写建立一个新的文本文件 |
"a+"(读写) | 为读写打开一个文本文件 |
- "rb"(只读) 为输入打开一个二进制文件
- "wb"(只写) 为输出打开一个二进制文件
- "rb+"(读写) 为读写打开一个二进制文件
- "wb+"(读写) 为读写建立一个新的二进制文件
- "ab+"(读写) 为读写打开一个二进制文件
打开操作
//C语言
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
void main() {
FILE* fp;
fp = fopen("./test.txt","r");
if (fp==NULL) {
printf("文件不存在,打开失败!\n");
}
else {
printf("文件已打开!\n");
}
fclose(fp);
system("pause");
}
若文档不存在:
文件存在:
读操作
//C语言
void main() {
FILE* fp;
fp = fopen("./test.txt","r");
if (fp==NULL) {
printf("文件不存在,打开失败!\n");
}
else {
printf("文件已打开!\n");
}
char arr[1024] = { 0 };
fread(arr, 1, 9, fp);
printf("%s\n", arr);
fclose(fp);
system("pause");
}
写操作
//C语言
void main() {
FILE* fp;
fp = fopen("./test.txt","w");
if (fp==NULL) {
printf("文件不存在,打开失败!\n");
}
else {
printf("文件已打开!\n");
}
char arr[1024] = "wenjancaozuo";
fwrite(arr, 1, strlen(arr), fp);
printf("%s\n", arr);
fclose(fp);
system("pause");
}
掌握以上操作就基本完成文件操作的内容。上面是数据块的读写函数。
附加
1、字符读写
先介绍两个句柄。
-
stdin(键盘输入)
-
stdout (标准输出)
fgetc(文件指针) 输入
fputc(字符常量 ,文件指针) 输出
//C语言
void main() {
FILE* fp;
fp = fopen("./test.txt","w");
if (fp==NULL) {
printf("文件不存在,打开失败!\n");
}
else {
printf("文件已打开!\n");
}
int c;
while ((c=fgetc(stdin))!=EOF){
fputc(c, stdout);
fputc(c, fp);
}
fclose(fp);
system("pause");
}
2、字符串读写
fgets( 字符数组 , 字符长度 , 文件指针 ) 输入
fputs( 字符串 ,文件指针 ) 输出
//C语言
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main() {
FILE* fp;
fp = fopen("./test.txt","w");
if (fp==NULL) {
printf("文件不存在,打开失败!\n");
}
else {
printf("文件已打开!\n");
}
char buf[1024] = "0";
while (fgets(buf,sizeof(buf),stdin)!=NULL) {
fputs(buf, stdout);
fputs(buf, fp);
}
fclose(fp);
system("pause");
}
文件的运用
文件到这里就学习完了。所以就要动手实践。现在将前面的动态内存通讯录进阶为文件通讯录。
//C语言
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define peoplemax 1000
//实现一个通讯录;
//通讯录可以用来存储1000个人的信息,每个人的信息包括:
//姓名、性别、年龄、电话、住址
//
//提供方法:
//1. 添加联系人信息
//2. 删除指定联系人信息
//3. 查找指定联系人信息
//4. 修改指定联系人信息
//5. 显示所有联系人信息
//6. 清空所有联系人
//7. 以名字排序所有联系人
//8. 保存联系人到文件
//9. 加载联系人
//先创建一个结构体数组。结构体里面包含个人信息。再加上一个人数
typedef struct FUNCTION {//定义1000长度的结构体数组
char name[20];
char sex[2];
int age;
char telnumber[11];
char adress[20];
}ADbook;
struct BOOK {
ADbook* address_book;
int size;
int personcount;
}as_book;
void Check_malloc() {
if (as_book.size < as_book.personcount) {
return;
}
as_book.personcount *= 2;
ADbook* temp = (ADbook*)malloc
(sizeof(ADbook)*as_book.personcount);
for (int i = 0; i < as_book.size; i++) {
temp[i] = as_book.address_book[i];
}
free(as_book.address_book);
as_book.address_book = temp;
printf("通讯录已经扩容!\n");
}
int book_menu() {
int choice = 0;
printf("=========<简易通讯录>=========\n");
printf("=========<1、添加联系人>=========\n");
printf("=========<2、删除联系人>=========\n");
printf("=========<3、查找联系人>=========\n");
printf("=========<4、修改联系人>=========\n");
printf("=========<5、显示全部>==========\n");
printf("=========<6、清空联系人>=========\n");
printf("=========<7、排序联系人>=========\n");
printf("=========<8、退出通讯录>=========\n");
printf("请输入您的选择:");
scanf("%d", &choice);
return choice;
}
void empty_person() {//清空和初始化的相同作用。所以这里可以写成初始化
as_book.size = 0;
as_book.personcount = 5;
as_book.address_book = (ADbook*)malloc
(sizeof(ADbook)*as_book.personcount);
//printf("通讯录已经初始化!\n");
}
void add_person() {
Check_malloc();
printf("请输入姓名:");
scanf("%s", as_book.address_book[as_book.size].name);
printf("请输入性别:");
scanf("%s", as_book.address_book[as_book.size].sex);
printf("请输入年龄:");
scanf("%d", &as_book.address_book[as_book.size].age);
printf("请输入电话:");
scanf("%s", as_book.address_book[as_book.size].telnumber);
printf("请输入地址:");
scanf("%s", as_book.address_book[as_book.size].adress);
printf("成功增加!\n");
++as_book.size;
printf("目前%d位联系人!\n", as_book.size);
}
int find_person() {
char name[1024] = "0";
printf("请输入查找人的姓名:");
scanf("%s", name);
int temp = 0;
while (temp < as_book.size) {
if (temp == 0) {
printf("编号\t姓名\t性别\t年龄\t电话\t住址\n");
printf("=================================================\n");
}
if (strcmp(name, as_book.address_book[temp].name) == 0) {
printf("%d\t%s\t%s\t%d\t%s\t%s\t", as_book.size, as_book.address_book[temp].name, as_book.address_book[temp].sex
, as_book.address_book[temp].age, as_book.address_book[temp].telnumber, as_book.address_book[temp].adress);
printf("\n");
return temp;
}
++temp;
}
printf("通讯录里没有该联系人!\n");
return -1;
}
void del_person() {
int temp = 0;
temp = find_person();
if (temp == 0) {
;
}
else {
while (temp < as_book.personcount) {
as_book.address_book[temp] = as_book.address_book[temp + 1];
++temp;
}
--as_book.personcount;
printf("成功删除该联系人!\n");
}
}
void alt_person() {
int temp = 0;
temp = find_person();
if (temp == -1) {
;
}
else {
int choice = 0;
int max = 5;
while (max--) {//有五次修改机会,没选择一次就会减少一次。
printf(" ======1、姓名 === 2、性别=======\n");
printf(" ======3、年龄 === 4、电话=======\n");
printf(" ======5、地址 === 6、跳过=======\n");
printf("请选择要修改的项:");
scanf("%d", &choice);
switch (choice)
{
case 1:
printf("姓名修改为:");
scanf("%s", as_book.address_book[temp].name);
break;
case 2:
printf("性别修改为:");
scanf("%s", as_book.address_book[temp].sex);
break;
case 3:
printf("年龄修改为:");
scanf("%d", &as_book.address_book[temp].age);
break;
case 4:
printf("电话修改为:");
scanf("%s", as_book.address_book[temp].telnumber);
break;
case 5:
printf("地址修改为:");
scanf("%s", as_book.address_book[temp].adress);
break;
case 6:
printf("请继续选择。\n");
break;
default:
++max;//输入错误,加一次修改机会。
break;
}
}
}
}
void print_person() {
if (as_book.size == 0) {
printf("通讯录为空,请先添加联系人!\n");
}
else {
int temp = 0;
printf("编号\t姓名\t性别\t年龄\t电话\t住址\n");
printf("=================================================\n");
while (temp < as_book.size)
{
printf("%d\t%s\t%s\t%d\t%s\t%s\t", as_book.size, as_book.address_book[temp].name, as_book.address_book[temp].sex
, as_book.address_book[temp].age, as_book.address_book[temp].telnumber, as_book.address_book[temp].adress);
printf("\n");
++temp;
}
}
}
//保存联系人
void save() {
printf("正在保存……\n");
FILE* fp = fopen("../ test.txt","w");
if (fp==NULL) {
printf("文件不存在,打开失败!\n");
return;//结束程序
}
for (int temp = 0; temp < as_book.size; ++temp) {
fwrite(&as_book.address_book[temp],sizeof(ADbook), 1 ,fp);
}
fclose(fp);
printf("保存成功!\n");
printf("已经保存 %d 条数据\n",as_book.size);
}
//加载联系人
void load() {
printf("LOADING……\n");
FILE* fp = fopen("../ test.txt", "r");
if (fp == NULL) {
printf("文件打开失败,加载失败\n");
return;//结束程序
}
ADbook temp = { 0 };
while (fread(&temp,sizeof(temp),1,fp)){
Check_malloc();
as_book.address_book[as_book.size] = temp;
++as_book.size;
}
fclose(fp);
printf("加载成功\n");
printf("加载 %d 条联系人!\n",as_book.size);
}
void sort_person() {
if (as_book.size == 0)
{
printf("通讯录为空,不需要排序!\n");
}
else
{
int row = 0;
while (row < as_book.size - 1)
{
int col = 0;
while (col < as_book.size - 1 - row)
{
if (strcmp(as_book.address_book[col].name, as_book.address_book[col + 1].name) > 0)
{
char temp[1024];
strcpy(temp, as_book.address_book[col].name);
strcpy(as_book.address_book[col].name, as_book.address_book[col + 1].name);
strcpy(as_book.address_book[col + 1].name, temp);
}
++col;
}
++row;
}
}
}
int main() {
int choice = 0;
empty_person();
load();
//以循环打印菜单提示用户输入选择
while (1) {
//开关语句卡是实现函数,增删查改,排序,清空。
choice = book_menu();
switch (choice) {
case 1://添加联系人
add_person();
save();
break;
case 2://删除联系人
del_person();
save();
break;
case 3://查找联系人
find_person();
break;
case 4://修改联系人
alt_person();
save();
break;
case 5://显示所有联系人
print_person();
break;
case 6://清空联系人
empty_person();
save();
break;
case 7://排序联系人
sort_person();
save();
break;
case 8:
save();
printf("欢迎下次使用!\n");
system("pause");
return 0;
break;
default:
break;
}
}
return 0;
system("pause");
}