🎄文件的随机读写
再说接下来的操作之前,先明确一个东西:
文件偏移量(刚打开的文件偏移量为0)
🎅fseek
描述
C 库函数 int fseek(FILE *stream, long int offset, int whence) 设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数。
声明
int fseek(FILE *stream, long int offset, int whence)
参数
stream
– 这是指向FILE
对象的指针,该FILE
对象标识了流。offset
– 这是相对whence
的偏移量,以 字节为单位。whence
– 这是表示开始添加偏移 offset 的位置。它一般指定为下列常量之一:
常量 | 描述 |
SEEK_SET | 文件的开头 |
SEEK_CUR | 文件指针的当前位置 |
SEEK_END | 文件的末尾 |
返回值
如果成功,则该函数返回零,否则返回非零值。
使用实例
🎅ftell
描述
C 库函数 long int ftell(FILE *stream) 返回给定流 stream 的当前文件位置。
声明
long int ftell(FILE *stream)
参数
stream
– 这是指向FILE
对象的指针,该FILE
对象标识了流。
返回值
该函数返回位置标识符的当前值。如果发生错误,则返回 -1L,全局变量 errno 被设置为一个正值。
使用实例
🎅rewind
描述
C 库函数 void rewind(FILE *stream) 设置文件位置为给定流 stream 的文件的开头。
声明
void rewind(FILE *stream)
参数
stream
– 这是指向FILE
对象的指针,该FILE
对象标识了流。返回值
该函数 不返回任何值。
使用实例
🎄文件结束的判定
❗❗❗❗❗被错误使用的 feof
牢记:在文件读取过程中,不能 用feof函数
的返回值直接用来判断文件的是否结束。
而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。
🐂1. 文本文件读取是否结束,判断返回值是否为EOF (fgetc),或NULL(fgets)
例如:
- fgetc判断是否为
EOF
. - fgets判断返回值是否为
NULL
.
🐂2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:
- fread判断返回值是否小于实际要读的个数。
正确的使用:
1.文本文件的例子:
#include <stdio.h> #include <stdlib.h> int main(void) { int c; // 注意:int,非char,要求处理EOF FILE* fp = fopen("test.txt", "r"); if(!fp) { perror("File opening failed"); return EXIT_FAILURE; } //fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环 { putchar(c); } //判断是什么原因结束的 if (ferror(fp)) puts("I/O error when reading"); else if (feof(fp)) puts("End of file reached successfully"); fclose(fp); }
2.二进制文件的例子:
#include <stdio.h> enum { SIZE = 5 }; int main(void) { double a[SIZE] = {1.0,2.0,3.0,4.0,5.0}; double b = 0.0; size_t ret_code = 0; FILE *fp = fopen("test.bin", "wb"); // 必须用二进制模式 fwrite(a, sizeof(*a), SIZE, fp); // 写 double 的数组 fclose(fp); fp = fopen("test.bin","rb"); // 读 double 的数组 while((ret_code = fread(&b, sizeof(double), 1, fp))>=1) { printf("%lf\n",b); } if (feof(fp)) printf("Error reading test.bin: unexpected end of file\n"); else if (ferror(fp)) { perror("Error reading test.bin"); } fclose(fp); fp = NULL; }
🐂🐸通讯录高阶版(动态内存+自定义类型+文件)
contact.c
#include "contact.h" //静态初始化 //void InitContact(struct Contact* pc) //{ // pc->sz = 0;//默认没有信息 // memset(pc->data, 0, MAX*sizeof(struct PeoInfo)); // memset(pc->data, 0, sizeof(pc->data)); //} void CheckCapacity(struct Contact* pc) { if (pc->sz == pc->capacity) { struct PeoInfo* ptr = (struct PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(struct PeoInfo)); if (ptr != NULL) { pc->data = ptr; pc->capacity += 2; printf("增容成功\n"); } else { printf("增容失败\n"); return; } } } //加载数据 void LoadContact(struct Contact* pc) { FILE*pf = fopen("contact.txt", "r"); if (NULL == pf) { perror("LoadContact::fopen"); return; } struct PeoInfo temp = { 0 }; while(EOF != fscanf(pf, "%s %d %s %s %s", temp.name, &temp.age, temp.sex, temp.tele, temp.addr)) { CheckCapacity(pc); pc->data[pc->sz] = temp; pc->sz++; } fclose(pf); pf = NULL; } //动态初始化 void InitContact(struct Contact* pc) { pc->sz = 0; pc->data = (struct PeoInfo*)malloc(DEFAULT_SZ * sizeof(struct PeoInfo)); pc->capacity = DEFAULT_SZ;//初始最大容量为3 //加载文件信息 LoadContact(pc); } //静态添加 //void AddContact(struct Contact* pc) //{ // if (pc->sz == MAX) // { // printf("通讯录满了\n"); // } // else // { // printf("请输入名字:>"); // scanf_s("%s", pc->data[pc->sz].name, 30); // printf("请输入年龄:>"); // scanf_s("%d", &(pc->data[pc->sz].age)); // printf("请输入性别:>"); // scanf_s("%s", pc->data[pc->sz].sex, 5); // printf("请输入电话:>"); // scanf_s("%s", pc->data[pc->sz].tele, 12); // printf("请输入地址:>"); // scanf_s("%s", pc->data[pc->sz].addr, 30); // // // printf("添加成功\n"); // pc->sz++; // ShowContact(pc); // } //} //动态添加 void AddContact(struct Contact* pc) { if (pc->sz == pc->capacity) { struct PeoInfo* ptr = (struct PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(struct PeoInfo)); if (ptr != NULL) { pc->data = ptr; pc->capacity += 2; printf("增容成功\n"); } else { printf("增容失败\n"); return; } } //录入新增人的信息 printf("请输入名字:>"); scanf_s("%s", pc->data[pc->sz].name, 30); printf("请输入年龄:>"); scanf_s("%d", &(pc->data[pc->sz].age)); printf("请输入性别:>"); scanf_s("%s", pc->data[pc->sz].sex, 5); printf("请输入电话:>"); scanf_s("%s", pc->data[pc->sz].tele, 12); printf("请输入地址:>"); scanf_s("%s", pc->data[pc->sz].addr, 30); printf("添加成功\n"); pc->sz++; ShowContact(pc); } void DeletContact(struct Contact* pc) { printf("请输入需要删除的联系人姓名\n"); char name[30] = "0"; scanf_s("%s", name, 30); for (int i = 0; i < pc->sz; i++) { if (strcmp(name, pc->data[i].name) == 0) { for (int j = i; j < pc->sz-1; j++) { strcpy_s(pc->data[j].name, 30, pc->data[j + 1].name); strcpy_s(pc->data[j].sex, 5, pc->data[j + 1].sex); strcpy_s(pc->data[j].tele, 12, pc->data[j + 1].tele); strcpy_s(pc->data[j].addr, 30, pc->data[j + 1].addr); pc->data[j].age = pc->data[j + 1].age; } printf("删除成功\n"); (pc->sz)--; ShowContact(pc); } } } void ModifyContact(struct Contact* pc) { printf("请输入需要修改的联系人姓名\n"); char name[30] = "0"; scanf_s("%s", name, 30); for (int i = 0; i < pc->sz; i++) { if (strcmp(name, pc->data[i].name) == 0) { printf("请输入名字:>"); scanf_s("%s", pc->data[i].name, 30); printf("请输入年龄:>"); scanf_s("%d", &(pc->data[i].age)); printf("请输入性别:>"); scanf_s("%s", pc->data[i].sex, 5); printf("请输入电话:>"); scanf_s("%s", pc->data[i].tele, 12); printf("请输入地址:>"); scanf_s("%s", pc->data[i].addr, 30); printf("修改成功!\n"); ShowContact(pc); } } } void ShowContact(struct Contact* pc) { int i = 0; printf("序号\t%10s\t%10s\t%8s\t%15s\t%30s\n", "name", "age", "sex", "tele", "addr"); for (i = 0; i < pc->sz ; i++) { //打印每一个数据 printf("%d\t%10s\t%10d\t%8s\t%15s\t%30s\n", i + 1, pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr); } } void SearchContact(struct Contact* pc) { printf("请输入需要搜索的联系人姓名\n"); char name[30] = "0"; scanf_s("%s", name, 30); for (int i = 0; i < pc->sz; i++) { if (strcmp(name, pc->data[i].name) == 0) { printf("序号\t%10s\t%10s\t%8s\t%15s\t%30s\n", "name", "age", "sex", "tele", "addr"); printf("%d\t%10s\t%10d\t%8s\t%15s\t%30s\n", i + 1, pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr); return; } } printf("找不到联系人信息\n"); } void SortContact(struct Contact* pc) { struct PeoInfo temp; for (int j = 0; j < pc->sz - 1; j++) for (int i = 0; i < pc->sz - 1 - j; i++) { if (strcmp(pc->data[i].name, pc->data[i + 1].name) > 0) { temp = pc->data[i + 1]; pc->data[i + 1] = pc->data[i]; pc->data[i] = temp; } } ShowContact(pc); } void DestroyContact(struct Contact* pc) { free(pc->data); pc->data = NULL; pc->capacity = 0; pc->sz = 0; } void SaveContact(struct Contact* pc) { FILE* pf = fopen("contact.txt", "w"); if (NULL == pf) { perror("SaveContact::fopen"); return; } int i = 0; for (i = 0; i < pc->sz; i++) { fprintf(pf, "%s %d %s %s %s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr); } fclose(pf); pf = NULL; }
contact.h
#pragma once #define _CRT_SECURE_NO_WARNINGS #define NAME_MAX 30 #define SEX_MAX 5 #define TELE_MAX 12 #define ADDR_MAX 30 #define MAX 1000 #define DEFAULT_SZ 3 //默认大小为3 #include <string.h> #include <stdio.h> #include <string.h> #include <stdlib.h> //创建枚举变量 enum Option { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, SORT }; //描述人的信息 struct PeoInfo { char name[NAME_MAX]; int age; char sex[SEX_MAX]; char tele[TELE_MAX]; char addr[ADDR_MAX]; }; //通讯录-静态版本 //struct Contact //{ // struct PeoInfo data[MAX];//1000个人的数据存放在data数组中 // int sz;//记录当前通讯录有效信息的个数 //}; //动态增长的版本 struct Contact { struct PeoInfo* data; int sz;//通讯录中当前有效元素的个数 int capacity;//通讯录的当前最大容量 }; //初始化通讯录 void InitContact(struct Contact* pc); //增加联系人 void AddContact(struct Contact* pc); //删除联系人 void DeletContact(struct Contact* pc); //修改联系人信息 void ModifyContact(struct Contact* pc); //搜索联系人信息 void SearchContact(struct Contact* pc); //显示所有的联系人 void ShowContact(struct Contact* pc); //按姓氏排序联系人信息 void SortContact(struct Contact* pc); //销毁通讯录 void DestroyContact(struct Contact* pc); //保存通讯录信息 void SaveContact(struct Contact* pc); //加载文件信息 void LoadContact(struct Contact* pc); //增容 void CheckCapacity(struct Contact* pc);
通讯录(动态内存版本).c
#include "contact.h" void menu() { printf("******************************\n"); printf("**** 1. 添加 2. 删除 **\n"); printf("**** 3. 搜索 4. 修改 **\n"); printf("**** 5. 展示全部 6. 排序 **\n"); printf("**** 0. 退出 **\n"); printf("******************************\n"); } int main() { int input = 0; //创建一个通讯录 struct Contact con; //初始化通讯录 InitContact(&con); do { menu(); printf("请选择:>"); scanf_s("%d", &input); switch (input) { case ADD: AddContact(&con); break; case DEL: DeletContact(&con); break; case SHOW: ShowContact(&con); break; case MODIFY: ModifyContact(&con); break; case SEARCH: SearchContact(&con); break; case SORT: SortContact(&con); break; case EXIT: //销毁通讯录 SaveContact(&con); DestroyContact(&con); printf("保存成功\n退出通讯录\n"); break; default: printf("选择错误\n"); break; } } while (input); return 0; }
❤原创不易,如有错误,欢迎评论区留言指出,感激不尽❤
❤如果觉得内容不错,给个三连不过分吧~ ❤
❤看到会回访~ ❤