输入文件路径和文件名还是打不开文件
遇到的现象和发生背景:
使用C语言编写学生管理系统(多文件),将文件中的数据保存到链表中实现一系列功能,上传文件时显示文件无法打开。
用代码块功能插入代码:
//work_list.h
#include <stdio.h>
#include <string.h>
typedef struct student {
int id; // 学号
int grade; // 年级
char class[10]; // 班级
char name[20]; // 姓名
int age; // 年龄
char sex[10]; // 性别
float score; // 成绩
} Data;
typedef struct node {
Data data;
struct node* next;
} Node;
// 创建头节点
int create_head(Node** head, Data data);
// 头插法插入节点
int insert_head(Node** head, Data data);
// 查找节点
Node* find(Node* head, Data finddata);
// 更新节点
int update(Node* head, Data olddata, Data newdata);
// 删除节点
int del(Node** head, Data deldata);
// 按年级对成绩排序
Node* stor_grade(Node* head);
// 按班级对成绩排序
Node* stor_score(Node* head);
//根据班级名过滤链表
Node* filter_by_class(Node* head, const char* class_name);
void free_list(Node* head);
#endif
//work_list.c
#include "work_list.h"
// 创建头节点
int create_head(Node** head, Data data) {
Node* p = (Node*)malloc(sizeof(Node));
if (p == NULL) {
puts("内存分配失败");
return -1;
}
p->data = data;
p->next = NULL;
*head = p;
return 0;
}
// 头插法插入节点
int insert_head(Node** head, Data data) {
Node* p = (Node*)malloc(sizeof(Node));
if (p == NULL) {
puts("内存分配失败");
return -1;
}
p->data = data;
p->next = *head;
*head = p;
return 0;
}
// 查找节点
Node* find(Node* head, Data finddata) {
Node* current = head;
while (current != NULL) {
if (memcmp(&(current->data), &finddata, sizeof(Data)) == 0) {
return current;
}
current = current->next;
}
return NULL;
}
// 修改节点
int update(Node* head, Data olddata, Data newdata) {
Node* current = head;
while (current != NULL) {
if (memcmp(&(current->data), &olddata, sizeof(Data)) == 0) {
current->data = newdata;
return 0;
}
current = current->next;
}
puts("找不到数据");
return -1;
}
// 删除节点
int del(Node** head, Data deldata) {
if (*head == NULL) {
puts("链表为空");
return -1;
}
Node* current = *head;
Node* follow = NULL;
while (current != NULL) {
if (memcmp(&(current->data), &deldata, sizeof(Data)) == 0) {
if (follow == NULL) { // 删除头节点
*head = current->next;
} else {
follow->next = current->next;
}
free(current);
return 0;
}
follow = current;
current = current->next;
}
puts("要删除的数据不存在");
return -1;
}
/*
// 辅助函数:获取链表的中间节点
Node* get_middle(Node* head) {
if (head == NULL || head->next == NULL) {
puts("链表为空或只有一个节点");
return head;
}
Node* fast = head->next; // 快指针
Node* slow = head; // 慢指针
while (fast != NULL && fast->next != NULL) {
fast = fast->next->next; // 快指针一次移动两个位置
slow = slow->next; // 慢指针一次移动一个位置
}
return slow; // 返回中间节点
}
// 辅助函数:合并两个已排序的链表(按年级排序)
Node* stor_by_grade(Node* left, Node* right) {
Node dummy; // 哑节点,不存储实际数据,作为占位符,简化算法逻辑
Node* tail = &dummy;// 尾指针
dummy.next = NULL;
while (left != NULL && right != NULL) {
if (strcmp(left->data.grade, right->data.grade) < 0 ||
(strcmp(left->data.grade, right->data.grade) == 0 && left->data.score <= right->data.score)) {
tail->next = left;
left = left->next;
} else {
tail->next = right;
right = right->next;
}
tail = tail->next;
}
if (left != NULL) {
tail->next = left;
}
if (right != NULL) {
tail->next = right;
}
return dummy.next;
}
// 按年级对成绩排序
Node* stor_grade(Node* head) {
if (head == NULL || head->next == NULL) {
return head;
}
Node* mid = get_middle(head);
Node* left = head;
Node* right = mid->next;
mid->next = NULL; // 将链表从中间断开
left = stor_grade(left);
right = stor_grade(right);
return stor_by_grade(left, right);
}
// 辅助函数:合并两个已排序的链表(按成绩排序)
Node* stor_by_score(Node* left, Node* right) {
Node dummy; // 哑节点,不存储实际数据,作为占位符,简化算法逻辑
Node* tail = &dummy;// 尾指针
dummy.next = NULL;
while (left != NULL && right != NULL) {
if (left->data.score <= right->data.score) {
tail->next = left;
left = left->next;
} else {
tail->next = right;
right = right->next;
}
tail = tail->next;
}
if (left != NULL) {
tail->next = left;
}
if (right != NULL) {
tail->next = right;
}
return dummy.next;
}
// 按班级对成绩排序
Node* stor_score(Node* head) {
if (head == NULL || head->next == NULL) {
return head;
}
Node* mid = get_middle(head);
Node* left = head;
Node* right = mid->next;
mid->next = NULL; // 将链表从中间断开
left = stor_score(left);
right = stor_score(right);
return stor_by_score(left, right);
}
// 辅助函数:根据班级名过滤链表
Node* filter_by_class(Node* head, const char* class_name) {
Node* filtered_head = NULL;
Node* filtered_tail = NULL;
while (head != NULL) {
if (strcmp(head->data.class, class_name) == 0) {
Node* new_node = (Node*)malloc(sizeof(Node));
if (new_node == NULL) {
perror("分配内存失败");
exit(EXIT_FAILURE);
}
new_node->data = head->data;
new_node->next = NULL;
if (filtered_head == NULL) {
filtered_head = new_node;
filtered_tail = new_node;
} else {
filtered_tail->next = new_node;
filtered_tail = new_node;
}
}
head = head->next;
}
return filtered_head;
}*/
void free_list(Node* head) {
Node* current = head;
Node* next;
while (current != NULL) {
next = current->next;
free(current);
current = next;
}
}
//work_file.h
#ifndef WORK_FILE_H
#define WORK_FILE_H
#include"work_list.h"
//读取文件
int read_file(Node** head,const char* file_name);
#endif
work_file.c
#include "work_file.h"
#include "work_list.h"
#include <stdio.h>
// 从文件读取数据并插入到链表中
int read_file(Node** head, const char* file_name) {
FILE *fp = fopen(file_name, "r");
if (fp == NULL) {
perror("无法打开文件"); // 打开文件失败时输出错误信息
return -1;
}
Data student;
// 修正 fscan 的格式字符串以匹配数据结构
while (fscanf(fp, "%d,%d,%[^,],%[^,],%d,%[^,],%f\n",
&student.id,
&student.grade,
student.class,
student.name,
&student.age,
student.sex,
&student.score) == 7) {
// 将数据插入链表
if (insert_head(head, student) != 0) {
puts("插入链表失败"); // 插入链表失败时输出提示
fclose(fp); // 确保在返回前关闭文件
return -1;
}
}
if (ferror(fp)) {
perror("读取文件时出错"); // 读取文件过程中出错时输出错误信息
fclose(fp);
return -1;
}
fclose(fp);
return 0;
}
```c
//work_page.h
#ifndef WORK_PAGE_H
#define WORK_PAGE_H
#include "work_list.h"
// 打印菜单
void print_menu(void);
// 增加学生信息
void increase(Node** head);
// 删除学生信息
void delstu(Node** head);
// 查询学生信息
void search(Node* head);
// 修改学生信息
void updatestu(Node* head);
// 显示所有学生信息
void display_all(Node* head);
/*
// 排序学生信息
void sort(Node** head);
// 按班级过滤学生信息
void filter(Node* head);*/
#endif
//work_page.c
#include <stdio.h>
#include "work_page.h"
#include "work_list.h"
// 打印菜单
void print_menu() {
printf("\n\n");
printf("*****************************************************\n");
printf("*----------------------duoduo------------------------\n");
printf("* 学生信息管理系统 *\n");
printf("*****************************************************\n");
printf("********************系统功能菜单*********************\n");
printf("---------------------- --------------------------\n");
printf("*****************************************************\n");
printf("** 1、增加学生信息 * 2、删除学生信息 **\n");
printf("*****************************************************\n");
printf("** 3、查询学生信息 * 4、修改学生信息 **\n");
printf("*****************************************************\n");
printf("** 5、学生成绩排名 * 6、查看所有学生 **\n");
printf("*****************************************************\n");
printf("** 7、退出系统 * **\n");
printf("*****************************************************\n");
printf("---------------------- --------------------------\n");
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "work_list.h" // 包含 Node 结构体定义和 insert_head 函数
#include "work_file.h" // 包含文件操作函数
// 辅助函数:查找学号是否存在
int is_id_exist(Node* head, int id) {
Node* current = head;
while (current != NULL) {
if (current->data.id == id) {
return 1; // 学号已存在
}
current = current->next;
}
return 0; // 学号不存在
}
// 增加学生信息
void increase(Node** head) {
Data Student;
printf("输入学生信息(学号 年级 班级 姓名 年龄 性别 成绩)用空格隔开:\n");
if (scanf("%d %d %s %s %d %s %f", &Student.id, &Student.grade, Student.class, Student.name, &Student.age, Student.sex, &Student.score) == 7) {
// 检查学号是否已存在
if (is_id_exist(*head, Student.id)) {
printf("学号 %d 已存在,不能重复添加。\n", Student.id);
return;
}
if (insert_head(head, Student) == 0) {
printf("学生信息添加成功!\n");
// 将新学生信息追加到文件中
FILE *fp = fopen("student.txt", "a");
if (fp == NULL) {
perror("无法打开文件");
return;
}
fprintf(fp, "%d,%d,%s,%s,%d,%s,%.2f\n", Student.id, Student.grade, Student.class, Student.name, Student.age, Student.sex, Student.score);
fclose(fp);
} else {
printf("学生信息添加失败。\n");
}
} else {
printf("输入格式错误。\n");
}
}
// 删除学生信息
void delstu(Node** head) {
Data Student;
printf("输入删除学生信息(学号 年级 班级 姓名)用空格隔开:\n");
if (scanf("%d %d %s %s", &Student.id, &Student.grade, Student.class, Student.name) == 4) {
if (del(head, Student) == 0) {
printf("学生信息删除成功!\n");
// 从文件中删除学生信息
FILE *fp = fopen("student.txt", "r");
FILE *temp = fopen("temp.txt", "w");
if (fp == NULL || temp == NULL) {
perror("无法打开文件");
return;
}
Data current;
while (fscanf(fp, "%d,%d,%[^,],%[^,],%d,%[^,],%f\n",
¤t.id, ¤t.grade, current.class, current.name, ¤t.age, current.sex, ¤t.score) == 7) {
if (current.id != Student.id) {
fprintf(temp, "%d,%d,%s,%s,%d,%s,%f\n", current.id, current.grade, current.class, current.name, current.age, current.sex, current.score);
}
}
fclose(fp);
fclose(temp);
remove("student.txt");
rename("temp.txt", "student.txt");
} else {
printf("学生信息删除失败。\n");
}
} else {
printf("输入格式错误。\n");
}
}
// 查询学生信息
void search(Node* head) {
Data student;
printf("输入要查询的学生学号:\n");
if (scanf("%d", &student.id) == 1) {
Node* result = find(head, student);
if (result != NULL) {
printf("学号=%d, 年级=%d, 班级=%s, 姓名=%s, 年龄=%d, 性别=%s, 成绩=%.2f\n",
result->data.id, result->data.grade, result->data.class, result->data.name,
result->data.age, result->data.sex, result->data.score);
} else {
printf("未找到学号为 %d 的学生信息。\n", student.id);
}
} else {
printf("输入格式错误。\n");
}
}
// 修改学生信息
void updatestu(Node* head) {
Data olddata, newdata;
printf("请输入要修改的学生学号:\n");
if (scanf("%d", &olddata.id) == 1) {
Node* result = find(head, olddata);
if (result != NULL) {
printf("当前学生信息:\n");
printf("学号=%d, 年级=%d, 班级=%s, 姓名=%s, 年龄=%d, 性别=%s, 成绩=%.2f\n",
result->data.id, result->data.grade, result->data.class, result->data.name,
result->data.age, result->data.sex, result->data.score);
printf("请输入新的学生信息(学号 年级 班级 姓名 年龄 性别 成绩)用空格隔开:\n");
if (scanf("%d %d %s %s %d %s %f", &newdata.id, &newdata.grade, newdata.class, newdata.name, &newdata.age, newdata.sex, &newdata.score) == 7) {
result->data = newdata;
printf("学生信息更新成功!\n");
// 更新文件中的信息
FILE *fp = fopen("student.txt", "r");
FILE *temp = fopen("temp.txt", "w");
if (fp == NULL || temp == NULL) {
perror("无法打开文件");
return;
}
Data current;
while (fscanf(fp, "%d,%d,%[^,],%[^,],%d,%[^,],%f\n",
¤t.id, ¤t.grade, current.class, current.name, ¤t.age, current.sex, ¤t.score) == 7) {
if (current.id == olddata.id) {
fprintf(temp, "%d,%d,%s,%s,%d,%s,%f\n", newdata.id, newdata.grade, newdata.class, newdata.name, newdata.age, newdata.sex, newdata.score);
} else {
fprintf(temp, "%d,%d,%s,%s,%d,%s,%f\n", current.id, current.grade, current.class, current.name, current.age, current.sex, current.score);
}
}
fclose(fp);
fclose(temp);
remove("student.txt");
rename("temp.txt", "student.txt");
} else {
printf("输入格式错误。\n");
}
} else {
printf("未找到学号为 %d 的学生信息。\n", olddata.id);
}
} else {
printf("输入格式错误。\n");
}
}
// 显示所有学生信息
void display_all(Node* head) {
Node* current = head;
printf("所有学生信息:\n");
while (current != NULL) {
printf("学号=%d, 年级=%d, 班级=%s, 姓名=%s, 年龄=%d, 性别=%s, 成绩=%.2f\n",
current->data.id, current->data.grade, current->data.class, current->data.name,
current->data.age, current->data.sex, current->data.score);
current = current->next;
}
}
/*
//成绩排名
void stor_stu_score(Node* head)
{
printf("\n\n");
printf("*****************************************************\n");
printf("*----------------------duoduo------------------------\n");
printf("* 学生成绩排名 *\n");
printf("*****************************************************\n");
printf("********************系统功能菜单*********************\n");
printf("---------------------- --------------------------\n");
printf("*****************************************************\n");
printf("** 1、按班级排名 * 2、按年级排名 **\n");
printf("*****************************************************\n");
printf("** 3、退出系统 * **\n");
printf("*****************************************************\n");
printf("---------------------- --------------------------\n");
int num;
printf("选择操作:");
scanf("%d",&num);
printf("\n");
if(num == 1)
{}
else if (num == 2)
{
}
else if (num == 3)
{
}
else
{
puts("无效选择");
}
}
*/
//work_mian.c
#include <stdio.h>
#include <stdlib.h>
#include "work_page.h"
#include "work_list.h"
#include "work_file.h"
// 主函数
int main() {
Node* head = NULL;
int choice;
// 从文件读取数据到链表
if (read_file(&head, "D:\\vscodePro\\work\\student.txt") != 0) {
printf("读取文件失败,程序退出。\n");
return -1;
}
while (1) {
print_menu(); // 打印菜单
printf("请选择操作(1-7):");
if (scanf("%d", &choice) != 1) {
printf("输入格式错误。\n");
// 清空输入缓冲区
while (getchar() != '\n');
continue;
}
switch (choice) {
case 1:
increase(&head);
break;
case 2:
delstu(&head);
break;
case 3:
search(head);
break;
case 4:
updatestu(head);
break;
case 5:
// 这里可以调用成绩排名功能,当前功能未实现
printf("成绩排名功能尚未实现。\n");
break;
case 6:
display_all(head);
break;
case 7:
// 退出系统前释放链表内存并退出
free_list(head);
printf("退出系统。\n");
return 0;
default:
printf("无效选择,请重新输入。\n");
}
}
return 0; // 这行在 while 循环后,用于结束 main 函数
}
运行结果及详细报错内容
编译运行时显示无法打开文件
我的解答思路和尝试过的方法,不写自己思路的,回答率下降 60%
尝试使用测试代码输出文件内容
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义数据结构
typedef struct {
int id;
int grade;
char class[10];
char name[50];
int age;
char sex[10];
float score;
} Data;
// 定义节点结构
typedef struct Node {
Data data;
struct Node* next;
} Node;
// 在链表头部插入节点的函数
int insert_head(Node** head, Data student) {
Node* new_node = (Node*)malloc(sizeof(Node));
if (new_node == NULL) {
return -1; // 内存分配失败
}
new_node->data = student;
new_node->next = *head;
*head = new_node;
return 0;
}
// 从文件中读取数据并插入到链表中的函数
int read_file(Node** head, const char* file_name) {
FILE *fp = fopen(file_name, "r");
if (fp == NULL) {
perror("无法打开文件");
return -1;
}
Data student;
while (fscanf(fp, "%d,%d,%[^,],%[^,],%d,%[^,],%f\n",
&student.id,
&student.grade,
student.class,
student.name,
&student.age,
student.sex,
&student.score) == 7) {
if (insert_head(head, student) != 0) {
puts("插入链表失败");
fclose(fp);
return -1;
}
}
if (ferror(fp)) {
perror("读取文件时出错");
fclose(fp);
return -1;
}
fclose(fp);
return 0;
}
// 打印链表的函数
void list_print(Node* head) {
Node* current = head;
while (current != NULL) {
printf("学号=%d, 年级=%d, 班级=%s, 姓名=%s, 年龄=%d, 性别=%s, 成绩=%.2f\n",
current->data.id,
current->data.grade,
current->data.class,
current->data.name,
current->data.age,
current->data.sex,
current->data.score);
current = current->next;
}
}
// 释放链表的函数
void free_list(Node* head) {
Node* current = head;
Node* next;
while (current != NULL) {
next = current->next;
free(current);
current = next;
}
}
int main() {
Node* head = NULL;
// 从文件中读取数据到链表中
if (read_file(&head, "D:\\vscodePro\\work\\student.txt") == 0) {
printf("数据成功读取到链表中\n");
// 打印链表以验证数据
list_print(head);
} else {
printf("读取文件失败\n");
}
// 释放链表
free_list(head);
return 0;
}
可以输出内容
尝试在函数中使用失败
我想要达到的结果:
文件可以读取并插入到链表中,可以正常实现功能。