C语言文件操作&&文件管理系统的c语言代码

因为最近是小学期,临时学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 函数打开的文件或标准流(如 stdoutstderr)的指针。
  • 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值