文件
文件:存储在外部介质上的数据集合。集合的名称叫文件名。
作用:文件可以保存程序运行结果。
编码分类:ascii文件(文本文件)和二进制文件。
文件操作原理:
1) 文件缓冲区:系统为文件自动的在内存区中为使用的文件开辟的缓冲区。
2) 输入输出流:数据的输入输出。
1 文件操作步骤:
1) 引入头文件 stdio.h
2) 定义文件指针
3) 打开文件
4) 文件读写
5) 关闭文件
2 文件相关函数
字符读写函数:fgetc和fputc
字符串读写函数:fgets和fputs
数据块读写函数:fread 和fwrite
格式化读写函数:fscanf和fprintf
3 文件指针
FILE *指针变量标识符;
文件指针指向文件在内存的首地址。
1) 文件打开(fopen)
打开文件是建立文件的各种信息,并使文件指针指向该文件,以便进行其他操作。
FILE *fp=NULL; //定义文件指针并赋值为NULL
fp=fopen(文件名,文件使用方式);
成功返回文件首地址,否则为NULL。
2) 文件关闭(fclose)
断开指针与文件的联系。
fclose(fp);
4文件使用方式
r 只读
w 只写 创建或者先删后建文件。
a 只写 文件存在追加,不存在创建。换行追加
r+ 读写
w+读写 创建文件或者覆盖文件
a+ 读写 等价a但是可以读。
t 打开文件文件 默认打开文本文件。
b 打开二进制文件
注意
凡是以 r 打开的文件,文件必须存在。
打开文件失败是 返回NULL。
文本文件读入内存时需要将ascii转换为二进制。写入时相反。对二进制读写不需要转换。
5 文件函数使用
1) 字符读写函数
单位:字节
fputc(字符,文件指针);//把字符写入文件。
使用循环写入字符串。
读取一个字符
fgetc(fp);
char s=fgetc(fp);
while(s!=EOF){ //EOF 文件结束标志
s=fgetc(fp); //文件指针会自动向后移动
putchar(s);
}
rewind(fp)将文件指针重新指向文件首地址。
2) 字符串读写
fputs(字符串,文件指针);
返回值为写入的字节数。
char str[100];
fgets(数组名称;sizeof(str),fp); //一次读取数组的长度个字节
1)文件读取完成后会给字符串数组加 \0 。
2)遇到\n或者EOF读取结束。 每次读取一行。
一个汉字 3个字节
一个字符1个字节
3) 数据块读写函数
fwrite(写入数据的首地址,块大小,块数,文件指针);
fread(数组首地址,块大小,块数,文件指针);
文件与结构体
写结构体
struct Student{
char name[20];
int age;
}stu[10];
fwrite(结构体变量地址,结构体大小,1,fp);
for(int i=0;i<10;i++){
fwrite(&stu[i],sizeof(structStudent),1,fp);
}
读结构体
struct Stuent stu2[10];
for(int i=0;i<10;i++){
fread(&stu2[i],sizeof(structStudent),1,fp);
}
4) 格式化读写函数
fscanf(文件指针,格式字符串,输入列表);
fscanf(fp,“%d%d”,&i,&j);
fprintf(文件指针,格式字符串,输入列表);
fprintf(fp,“%d%d”,i,j);
5)文件随机读写函数
fseek 移动文件内部的位置指针
fseek(文件指针,位移量,起始点);
位移量:移动的字节 long型数据数字后加L
起始点:从哪开始移动
文件首部 SEEK_SET 0
文件当前位置SEEK_CUR 1
文件末尾 SEEK_END 2
6)文件检测函数
feof(文件指针)
判断指针是否指向文件结束位置。 返回值 :结束是1 没结束为0。
ferror 文件出错检测函数。
文件操作实例
简易通讯录
//
// main.c
// 通讯录
//
// Created by ywxkdz on 15/11/19.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#include <stdio.h>
#include <string.h>
#define LEN 100 //通讯录容量
#define NAMELEN 21 //姓名长度
#define TELNUMLEN 12 //电话长度
//联系人结构体
typedef struct person {
char name[NAMELEN];
char telNum[TELNUMLEN];
}Person;
//定义通讯录数组
Person contacts[LEN];
//定义联系人总记录数
int totalCount=0;
//接收用户输入的编号
//联系保存的文件名
char *filePath="telbook.data";
int no=-1; //全局变量接收用户选择的功能
int flag; //全局变量 接收用户对操作的确认
//函数声明
void printFirstPage();
int validateInputNo();
void addContacts();
void delContacts();
void updateContacts();
void listContacts();
void searchContacts();
void initContcats();
void writeFile();
int main(int argc, const char * argv[]) {
flag=0;
while(1){
initContcats();
printFirstPage();
int no=validateInputNo();
switch (no) {
case 1:
addContacts();
break;
case 2:
delContacts();
break;
case 3:
updateContacts();
break;
case 4:
listContacts();
break;
case 5:
searchContacts();
break;
case 0:
return 0;
break;
default:
break;
}
}
return 0;
}
void printFirstPage(){
printf("****************************\n");
printf("*********欢迎使用通讯录********\n");
printf("**********1 添加联系人********\n");
printf("**********2 删除联系人********\n");
printf("**********3 修改联系人********\n");
printf("**********4 查看联系人********\n");
printf("**********5 搜索联系人********\n");
printf("**********0 退出系统**********\n");
printf("****************************\n");
}
/**
* 提示用户输入功能选项编号 并检验是否合法
*
* @return 合法的选项返回选项编号 不合法的返回-1
*/
int validateInputNo(){
printf("请输入0-5之间的编号\n");
scanf("%d",&no);
if (no>5||no<0) {
printf("输入不合法请重新输入\n");
return -1;
}
return no;
}
/**添加联系人
*
*/
void addContacts(){
//提示用户输入联系人姓名并接收
printf("请输入联系人姓名\n");
scanf("%s",contacts[totalCount].name);
//提示用户输入联系人电话号码并接收
printf("请输入联系人电话号码\n");
scanf("%s",contacts[totalCount].telNum);
//输出用户输入的信息,提示用户是否添加
printf("你添加的联系人是:%s,电话号码是:%s\n",contacts[totalCount].name,contacts[totalCount].telNum );
printf("是否添加?1:是 0:否\n");
scanf("%d",&flag);
if (flag) {
//电话记录条数+1 用户信息写入文件
totalCount++;
writeFile();
}else{
printf("你已经取消添加\n");
}
}
/**
* 根据用户选择,删除联系人
*/
void delContacts(){
//列出所有联系人,提示用户选择删除的联系人编号 并接收
listContacts();
printf("请选择将要删除的联系人id\n");
scanf("%d",&no);
if (no<0||no>totalCount) {
//非法输入提示
printf("你输入的编号有误请重新操作\n");
}else if (no==totalCount){
//如果用户输入的编号是最后一个,直接将记录数-1 最后一个不保存即可完成删除操作。
printf("你选择的\n id:%d \t name:%s \t telNum:%s\n",no,contacts[no-1].name,contacts[no-1].telNum);
printf("是否删除?1 是 0 否\n");
scanf("%d",&flag);
if (flag) {
totalCount--;
writeFile();
}
}else{
//如果用户输入的编号不是最后一个,需将这个id之后的数据向前挪一个位置。
printf("你选择的\n id:%d \t name:%s \t telNum:%s\n",no,contacts[no-1].name,contacts[no-1].telNum);
printf("是否删除?1 是 0 否\n");
scanf("%d",&flag);
if (flag) {
for (int i=no; i<totalCount; i++) {
contacts[i-1]=contacts[i];
}
totalCount--;
writeFile();
}
}
}
/**
* 根据用户输入信息修改联系人电话号码
*/
void updateContacts(){
listContacts();
printf("请选择你要修改联系人的id\n");
scanf("%d",&no);
if (0<no &&no<totalCount) {
//打印用户修改之前的联系人信息和用户将要修改的联系人信息,提示用户选择是否修改并接收
printf("你选择的\n id:%d \t name:%s \t telNum:%s\n",no,contacts[no-1].name,contacts[no-1].telNum);
printf("请输入你修改之后的电话号码\n");
char str[TELNUMLEN];
scanf("%s",str);
printf("修改之后的信息为\nname:%s \t telNum:%s\n",contacts[no-1].name,str);
printf("是否修改?1 是 0 否\n");
scanf("%d",&flag);
if (flag) {
//对联系人电话号码重新赋值
strcpy(contacts[no-1].telNum, str);
writeFile() ;
}
}else{
printf("你输入的id有误,请重新操作");
}
}
/**
* 根据姓名查找联系人
*/
void searchContacts(){
printf("请输入你要查找的联系人姓名\n");
char name[NAMELEN];
scanf("%s",name);
flag =0;
//联系人姓名匹配 匹配一个 flag +1
for (int i=0; i<totalCount; i++) {
if (strcmp(contacts[i].name, name)==0) {
printf("你查找的\n id:%d \t name:%s \t telNum:%s\n",i+1,contacts[i].name,contacts[i].telNum);
flag++;
}
}
if (flag==0) {
//未查找到联系人
printf("你查找的联系人不存在\n");
}
}
/**
* 打印联系人列表
*/
void listContacts(){
if (totalCount==0) {
printf("通讯录为空,请添加联系人\n");
}else{
for (int i=0; i<totalCount; i++) {
printf("id:%d\t name:%s\t telNum:%s\n",i+1,contacts[i].name,contacts[i].telNum);
}
}
}
/**
*初始化联系人文件和联系人数组
*如果联系人文件不存在 创建该文件
*如果联系人文件存在,先读取联系人总记录数赋值给 totalCount
再循环读取所有的联系人信息初始化数组
*/
void initContcats(){
//文件指针定义和打开文件
FILE *fp=fopen(filePath, "r");
if (fp!=NULL) {
//读取联系人总记录数
fread(&totalCount, sizeof(totalCount), 1, fp);
//循环读取所有的联系人信息初始化数组
for (int i=0; i<totalCount; i++) {
fread(&contacts[i], sizeof(Person), 1, fp);
}
}else {
//创建文件写入记录数 当前记录数为 0
fp=fopen(filePath, "wb");
fwrite(&totalCount, sizeof(totalCount), 1, fp);
printf("创建通讯录成功\n");
}
//关闭文件指针
fclose(fp);
}
/**
* 将总记录数和联系人信息写入文件
*/
void writeFile(){
FILE *fp=fopen(filePath, "wb");
if (fp!=NULL) {
//写总记录数
fwrite(&totalCount, sizeof(totalCount), 1, fp);
//循环 写联系人信息
for (int i=0; i<totalCount; i++) {
fwrite(&contacts[i], sizeof(Person), 1, fp);
}
}
fclose(fp);
}