学习笔记8-C语言文件
2015-11-20 13:46
525 查看
文件
文件:存储在外部介质上的数据集合。集合的名称叫文件名。
作用:文件可以保存程序运行结果。
编码分类: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(数组首地址,块大小,块数,文件指针);
文件与结构体
写结构体
读结构体
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 文件出错检测函数。
文件操作实例
简易通讯录
文件:存储在外部介质上的数据集合。集合的名称叫文件名。
作用:文件可以保存程序运行结果。
编码分类: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); }
相关文章推荐
- 打印结果和调试结果不一样(C语言)
- 虚函数表与虚函数指针
- 关于指针的引用的讲解
- C++泛型算法中的accumulate
- VC++ CopyFile、MoveFile函数用法
- c语言之同余定理的应用求2001的2003次方除以13的余数
- C++内存泄漏
- 24.c/c++程序员面试宝典-多态
- C++类的常量对象与常量成员函数
- sscanf的使用
- c++通用模板类(template class)定义实现详细介绍
- 值得学习的C语言开源项目
- 2048游戏C语言代码
- c++STL 中的copy函数
- C++虚函数实现原理与代价
- 高效率、灵活打印结构体串(C语言版)
- 23.c/c++程序员面试宝典-类成员
- C++中int和string类型的相互转换
- C++88个注意点子之6~10
- C++ 学习(类的继承,派生)