因为最近是小学期,临时学c的文件管理
首先写一个职工管理系统需要用到fopen,fclose , perror ,fread,fwrite 等(文件中主要写的都是结构体之类的,用到的都是二进制的读写)
先来介绍下函数的使用方法
fopen()
读写模式
"r":只读模式。文件必须存在,否则打开失败。"w":只写模式。如果文件存在,则文件长度被截断为零(即清空文件内容),然后从头开始写入;如果文件不存在,则创建新文件。"a":追加模式。如果文件存在,则新的写入数据将被添加到文件末尾;如果文件不存在,则创建新文件。"r+":读写模式。文件必须存在,否则打开失败。文件指针位于文件开头。"w+":读写模式。如果文件存在,则文件长度被截断为零,然后从头开始写入;如果文件不存在,则创建新文件。文件指针位于文件开头。"a+":读写模式。如果文件存在,则新的写入数据将被添加到文件末尾;如果文件不存在,则创建新文件。文件指针位于文件末尾。示例
- 打开一个文件以只读模式读取:
fopen("file.txt", "r"); - 创建一个新文件并写入内容:
fopen("file.txt", "w"); - 追加内容到已存在的文件末尾:
fopen("file.txt", "a"); - 以二进制模式打开一个文件以只读方式读取:
fopen("file.bin", "rb");
fclose()
~就是当你使用了open就要用close像是这样:(这里的编译平台是vs)
FILE* fp_write;
fopen_s(&fp_write, "D:\\data.txt", "wb");
if (fp_write == NULL) {
perror("Error opening file for writing");
exit(1);
}
fclose(fp_write);
也可以
FILE* fp_write=fopen(fp_write, "D:\\data.txt", "wb");
if (fp_write == NULL) {
perror("Error opening file for writing");
exit(1);
}
fclose(fp_write);
通常都是定义一个File* 名字 fopen 再fclose
要注意的是fopen_s调用的第一个参数是一个二级指针还要对FILE指针取地址
fopen就不用
perror()
就是打印一些提示信息没什么好说的
fread()
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数说明:
ptr:指向一个内存块的指针,该内存块用于存储从文件中读取的数据。size:要读取的每个数据项的大小(以字节为单位)。nmemb:要读取的数据项的最大数量。stream:指向 FILE 对象的指针,该对象标识了要从中读取数据的文件。
fread 返回成功读取的数据项数量,这可能会小于 nmemb 如果在读取时遇到文件结束符(EOF)或发生错误
附上代码:
void show_employees() {
FILE* file; fopen_s(&file,"D:\\data.txt", "rb");
if (file == NULL) {
perror("Error opening file");
return ;
}
//定义一个缓冲区
Employee employee;
size_t numRead;
// 读取文件直到 EOF
while ((numRead = fread(&employee, sizeof(Employee), 1, file)) == 1) {
printf(" from files ID: %d, Name: %s, Age: %d, Sex: %s, Address: %s, Phone: %s, Degree: %s, Salary: %s, Position: %s\n", employee.id, employee.name, employee.age, employee.sex, employee.address, employee.phone, employee.degree, employee.salary, employee.position);
}
fclose(file);
return;
}
fwrite()
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
ptr:一个指向要写入数据的内存块的指针。size:每个数据项的大小(以字节为单位)。count:要写入的数据项的数量。stream:指向要写入的文件的FILE对象。
和fread在语法上差不多 第一个都是写入文件的指针 第二个是数据块的大小 通常都是sizeof(类名),第三个是读入数据的数量通常是1 火车strlen(字符串),第四个是文件
fprintf()
int fprintf(FILE *stream, const char *format, ...);
FILE *stream:指向FILE对象的指针,该对象标识了要写入数据的输出流。使用如fopen函数打开的文件或标准流(如stdout、stderr)的指针。const char *format:格式字符串,用于指定后续参数如何被格式化和插入到输出流中。这与printf的格式字符串相同。...:可变数量的附加参数,它们的数量和类型由格式字符串决定,并且被插入到输出流
fprintf的写入文件更为灵活 可以写入不同的数据类型
int number = 10;
float pi = 3.14159;
// 使用 fprintf 向文件写入数据
fprintf(fp, "This is a test.\n");
fprintf(fp, "Number = %d\n", number);
fprintf(fp, "Pi = %.2f\n", pi);
fgets()
fget在作用上与fread()相似
参数一是缓冲区
参数二缓冲区大小
参数三是文件指针
可以用于对于文件的读取
一下代码实现了对文件的写入和读取字符串,通过while循环不断读入
需要注意的是在读入之前需要关闭文件,即写入文件后再关闭文件
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *fp;
char buffer[1024]; // 假设文件内容不会超过1023个字符加上一个终止符'\0'
// 写入文件
fp = fopen("example.txt", "w"); // 使用"w"模式打开文件,如果文件存在则覆盖,不存在则创建
if (fp == NULL) {
perror("Error opening file");
return -1;
}
fprintf(fp, "Hello, World!\nThis is a test file.\n");
fclose(fp); // 关闭文件
// 从文件中读取
fp = fopen("example.txt", "r"); // 使用"r"模式打开文件以进行读取
if (fp == NULL) {
perror("Error opening file");
return -1;
}
// 读取文件内容到buffer中
if (fgets(buffer, 1024, fp) != NULL) {
// fgets会在读取到文件末尾或读取到n-1个字符时停止,其中n是buffer的大小
// 因此,这里可能需要一个循环来读取文件的全部内容
printf("%s", buffer); // 打印读取到的第一行内容
// 如果文件有多行,可以添加循环来继续读取
while (fgets(buffer, 1024, fp) != NULL) {
printf("%s", buffer); // 打印后续行
}
} else {
perror("Error reading file");
}
fclose(fp); // 关闭文件
return 0;
}
文件管理系统完整代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_EMPLOYEES 100
//文件输入
typedef struct {
int id;
char name[100];
int age;
char sex[10];
char address[100];
char phone[100];
char degree[100];
char salary[100];
char position[100];
//首先先声明一个结构体其次生成一个新的变量去接收 然后
//简化数据输入重新输出
} Employee;
// 假设的职工列表(这里使用静态数组简化示例)
void writeprintfromstudent(Employee& w1) {//写入文件的指针 引用
printf("添加到文件成功\n");
FILE* fp_write; fopen_s(&fp_write,"D:\\data.txt", "ab");
if (fp_write == NULL) {
perror("Error opening file for writing");
exit(1);
}
fwrite(&w1, sizeof(Employee), 1, fp_write); //每个数据项的大小 写入数据项的数量 写入的文件
fclose(fp_write);
FILE* fp_read; fopen_s(&fp_read, "D:\\data.txt", "rb");
if (fp_read == NULL) {
perror("Error opening file for reading");
exit(1);
}
//查询的变成了最后一个
Employee buffer;
size_t bytes_read = fread(&buffer, sizeof(Employee), 1, fp_read); // 读取数据
if (bytes_read == 1) {
printf("from files ID: %d, Name: %s, Age: %d, Sex: %s, Address: %s, Phone: %s, Degree: %s, Salary: %s, Position: %s\n",
buffer.id, buffer.name, buffer.age, buffer.sex, buffer.address, buffer.phone, buffer.degree, buffer.salary, buffer.position);
}
else {
printf("Failed to read worker data from file.\n");
}
fclose(fp_read);
}
Employee employees[MAX_EMPLOYEES];
int employee_count = 0;
// 添加职工
void add_employee() {
if (employee_count >= MAX_EMPLOYEES) {
printf("员工列表已满!\n");
return;
}
Employee new_employee;
printf("请输入员工ID: ");
scanf_s("%d", &new_employee.id);
printf("请输入员工名字: ");
scanf_s("%s", new_employee.name,100);
printf("请输入员工年龄: ");
scanf_s("%d", &new_employee.age);
printf("请输入员工性别: ");
scanf_s("%s", new_employee.sex,100);
printf("请输入员工住址: ");
scanf_s("%s", &new_employee.address,100);
printf("请输入员工电话: ");
scanf_s("%s", new_employee.phone,13);
printf("请输入员工学位: ");
scanf_s("%s", new_employee.degree,100);
printf("请输入员工薪水: ");
scanf_s("%s", new_employee.salary,10);
printf("请输入员工职位: ");
scanf_s("%s", new_employee.position,100);
employees[employee_count++] = new_employee;
writeprintfromstudent(new_employee);
printf("员工添加成功!\n");
return;
}
// 显示所有职工
void show_employees() {
FILE* file; fopen_s(&file,"D:\\data.txt", "rb");
if (file == NULL) {
perror("Error opening file");
return ;
}
//定义一个缓冲区
Employee employee;
// 读取文件直到 EOF
while (fread(&employee, sizeof(Employee), 1, file) == 1) {
printf(" from files ID: %d, Name: %s, Age: %d, Sex: %s, Address: %s, Phone: %s, Degree: %s, Salary: %s, Position: %s\n", employee.id, employee.name, employee.age, employee.sex, employee.address, employee.phone, employee.degree, employee.salary, employee.position);
}
fclose(file);
return;
}
// 查询职工(简化示例,仅根据ID查询)
void search_employee() {
int id;
//不太能从文件里面查询所以用的是数组
printf("请输入要查询的员工ID: ");
scanf_s("%d", &id);
for (int i = 0; i < employee_count; i++) {
if (employees[i].id == id) {
printf("找到员工 ID: %d, Name: %s, Age: %d, Sex: %s, Address: %s, Phone: %s, Degree: %s, Salary: %s, Position: %s\n\n", employees[i].id, employees[i].name, employees[i].age, employees[i].sex, employees[i].address, employees[i].phone, employees[i].degree, employees[i].salary, employees[i].position);
return;
}
}
printf("未找到员工!\n");
return;
}
// 删除职工(简化示例,仅根据ID删除)
void delete_employee() {
int id, index;
//删除其实可以重写文件把不必要的去掉
printf("请输入要删除的员工ID: ");
scanf_s("%d", &id);
for (index = 0; index < employee_count; index++) {
if (employees[index].id == id) {
break;
}
}
if (index == employee_count) {
printf("未找到员工!\n");
return;
}
for (; index < employee_count - 1; index++) {
employees[index] = employees[index + 1];
}
employee_count--;
printf("员工删除成功!\n");
return;
}
//主函数
int main() {
int choice;
//第一次是wb比较特殊 相当于清除数据
FILE* fp_write;
fopen_s(&fp_write, "D:\\data.txt", "wb");
if (fp_write == NULL) {
perror("Error opening file for writing");
exit(1);
}
fclose(fp_write);
do {
printf("\n职工信息管理系统\n");
printf("1. 添加职工\n");
printf("2. 显示所有职工\n");
printf("3. 查询职工\n");
printf("4. 删除职工\n");
printf("5. 退出\n");
printf("请选择操作: ");
scanf_s("%d", &choice);
switch (choice) {
case 1:
add_employee();
break;
case 2:
show_employees();
break;
case 3:
search_employee();
break;
case 4:
delete_employee();
break;
case 5:
printf("退出系统...\n");
break;
default:
printf("无效的选择!\n");
}
} while (choice != 5);
return 0;
}
ps:
好了,这个就是全部了,感觉还行。原本以为是要在文件输入数据的data.txt中打开展示数据(不是二进制),想太多了,在想用链表申请空间 (如果是用C语言的话)把所有每一个节点连起来
每个节点上是数据val;顺便记录id (这个懒得写id重复的操作了),这样文件中打开不会有未分配的内存 (出现一堆烫烫烫烫烫)
后面发现好像不知道如何处理结构体成员的输入就pass了
附上问题解决后的代码 用链表串联 并且可以在文件中打开:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_EMPLOYEES 100
//文件输入
struct List_Employee {
unsigned int id;
char name[100];
unsigned int age;
char sex[100];
char address[100];
char phone[100];
char degree[100];
char salary[100];
char position[100];
List_Employee* next;
};
// 写入文件
void writeToFile(const char* filename, List_Employee &person) {
FILE* file; fopen_s(&file, filename, "w");
if (file == NULL) {
perror("Error opening file_write");
exit(EXIT_FAILURE);
}
fprintf(file, "%d %s %d %s %s %s %s %s %s", person.id, person.name, person.age, person.sex, person.address, person.phone, person.degree, person.salary, person.position);
fclose(file);
}
List_Employee readFromFile(const char* filename) {
List_Employee person;
FILE* file;
fopen_s(&file, filename, "rb");
if (file == NULL) {
perror("Error opening file_read");
exit(EXIT_FAILURE);
}
if(fscanf_s(file, "%d%d%s%s%s%s%s%s%s", &person.id, &person.age, person.name, 99, person.sex, 99, person.address, 99, person.phone, 99, person.degree, 99, person.salary, 99, person.position, 99)==9)
{
printf("from files ID: %d, Name: %s, Age: %d, Sex: %s, Address: %s, Phone: %s, Degree: %s, Salary: %s, Position: %s\n",
person.id, person.name, person.age, person.sex, person.address, person.phone, person.degree, person.salary, person.position);
}
else {
printf("error");
}
fclose(file);
return person;
}
// 创建新节点
List_Employee * createNode() {
List_Employee* new_employee = (List_Employee*)malloc(sizeof(List_Employee));
if (new_employee == NULL) {
printf("Memory allocation failed!\n");
exit(0);
}
printf("请输入员工ID: ");
scanf_s("%d", &new_employee->id);
printf("请输入员工名字: ");
scanf_s("%s", new_employee->name, 100);
printf("请输入员工年龄: ");
scanf_s("%d", &new_employee->age);
printf("请输入员工性别: ");
scanf_s("%s", new_employee->sex, 100);
printf("请输入员工住址: ");
scanf_s("%s", &new_employee->address, 100);
printf("请输入员工电话: ");
scanf_s("%s", new_employee->phone, 13);
printf("请输入员工学位: ");
scanf_s("%s", new_employee->degree, 100);
printf("请输入员工薪水: ");
scanf_s("%s", new_employee->salary, 10);
printf("请输入员工职位: ");
scanf_s("%s", new_employee->position, 100);
new_employee->next = nullptr;
writeToFile("D:\\data.txt",*new_employee);
readFromFile("D:\\data.txt");
printf("员工添加成功!\n");
return new_employee;
}
// 在链表末尾插入节点
void insertAtEnd(List_Employee** head_ref) {
// 1. 分配节点
List_Employee* newNode = createNode();
// 2. 如果链表为空,新节点即为头节点
if (*head_ref == NULL) {
*head_ref = newNode;
return;
}
// 3. 否则,遍历到链表的末尾,并将新节点连接到最后一个节点
List_Employee* last = *head_ref;
while (last->next != NULL) {
last = last->next;
}
last->next = newNode;
return;
}
// 打印链表
void printList(List_Employee* employee) {
while (employee!= NULL) {
printf("from files ID: %d, Name: %s, Age: %d, Sex: %s, Address: %s, Phone: %s, Degree: %s, Salary: %s, Position: %s\n",
employee->id, employee->name, employee->age, employee->sex, employee->address, employee->phone, employee->degree, employee->salary, employee->position);
employee = employee->next;
}
}
void printList_special(List_Employee* employee) {
int id;
printf("请输入需要查找程序员的id:\n");
scanf_s("%d", &id);
while (employee != NULL) {
if (employee->id == id) {
printf("from files ID: %d, Name: %s, Age: %d, Sex: %s, Address: %s, Phone: %s, Degree: %s, Salary: %s, Position: %s\n",
employee->id, employee->name, employee->age, employee->sex, employee->address, employee->phone, employee->degree, employee->salary, employee->position);
return;
}
employee = employee->next;
}
printf("未找到职员");
return;
}
void deleteList_special(List_Employee** employee) { // 使用二级指针来修改传入的指针
int id;
printf("请输入需要删除的程序员的id:\n");
scanf_s("%d", &id);
if (employee == nullptr || *employee == nullptr) {
printf("链表为空\n");
return;
}
// 处理头节点的情况
if ((*employee)->id == id) {
List_Employee* temp = *employee;
*employee = temp->next;
free(temp);
printf("头节点被删除\n");
return;
}
List_Employee* current = *employee;
while (current->next != NULL && current->next->id != id) {
current = current->next;
}
// 如果找到了要删除的节点
if (current->next != NULL) {
List_Employee* to_delete = current->next;
current->next = to_delete->next;
free(to_delete);
printf("职员被删除\n");
}
else {
printf("未找到职员\n");
}
}
int main() {
List_Employee *head = nullptr; // 初始化头节点为NULL
// 插入节点
int choice;
//第一次是wb比较特殊 相当于清除数据
FILE* fp_write;
fopen_s(&fp_write, "D:\\data.txt", "w");
if (fp_write == NULL) {
perror("Error opening file for writing");
exit(1);
}
fclose(fp_write);
do {
printf("\n职工信息管理系统\n");
printf("1. 添加职工\n");
printf("2. 显示所有职工\n");
printf("3. 查询职工\n");
printf("4. 删除职工\n");
printf("5. 退出\n");
printf("请选择操作: ");
scanf_s("%d", &choice);
switch (choice) {
case 1:
insertAtEnd(&head);
break;
case 2:
printList(head);
break;
case 3:
printList_special(head);
break;
case 4:
deleteList_special(&head);
break;
case 5:
printf("退出系统...\n");
break;
default:
printf("无效的选择!\n");
}
} while (choice != 5);
return 0;
}
1313

被折叠的 条评论
为什么被折叠?



