非常抱歉给您带来了困扰。让我们仔细检查并修正代码中的潜在问题,确保所有功能都能正常工作。我将特别注意以下几个方面:
1. **文件操作的正确性**:确保文件的打开、读取和写入操作都正确无误。
2. **内存管理**:确保所有动态分配的内存都被正确释放,避免内存泄漏。
3. **用户输入处理**:确保用户输入处理逻辑正确,避免程序因意外输入而崩溃。
4. **链表操作的健壮性**:确保链表插入、删除等操作正确无误。
### 改进后的代码
```c
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
// 定义链表节点结构
struct Node {
int data; // 数据域
struct Node* next; // 指针域
};
// 全局链表头指针
struct Node* head = NULL;
// 文件路径
const char* filename = "data.txt";
// 在链表尾部插入新节点
void append(struct Node** head_ref, int new_data) {
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
if (new_node == NULL) {
printf("Memory allocation failed!\n");
exit(EXIT_FAILURE);
}
new_node->data = new_data;
new_node->next = NULL;
if (*head_ref == NULL) {
*head_ref = new_node;
return;
}
struct Node* last = *head_ref;
while (last->next != NULL) {
last = last->next;
}
last->next = new_node;
}
// 打印链表中的所有节点
void printList(struct Node* head) {
struct Node* temp = head;
if (temp == NULL) {
printf("The list is empty.\n");
return;
}
printf("Current List: ");
while (temp != NULL) {
printf(" %d ", temp->data);
temp = temp->next;
}
printf("\n");
}
// 释放链表占用的内存
void freeList(struct Node** head_ref) {
struct Node* current = *head_ref;
struct Node* next;
while (current != NULL) {
next = current->next;
free(current);
current = next;
}
*head_ref = NULL;
}
// 冒泡排序链表
void bubbleSort(struct Node* head) {
int swapped;
struct Node* ptr1;
struct Node* lptr = NULL;
if (head == NULL) return;
do {
swapped = 0;
ptr1 = head;
while (ptr1->next != lptr) {
if (ptr1->data > ptr1->next->data) {
// 交换数据
int temp = ptr1->data;
ptr1->data = ptr1->next->data;
ptr1->next->data = temp;
swapped = 1;
}
ptr1 = ptr1->next;
}
lptr = ptr1;
} while (swapped);
}
// 从文件读取数据并加载到链表
void loadFromFile(struct Node** head_ref) {
FILE* file = fopen(filename, "r");
if (file == NULL) {
printf("File not found or unable to open.\n");
return;
}
int data;
while (fscanf(file, "%d", &data) == 1) { // 确保只读取成功的情况
append(head_ref, data);
}
fclose(file);
printf("Data loaded from file.\n");
}
// 将链表数据保存到文件
void saveToFile(struct Node* head) {
FILE* file = fopen(filename, "w");
if (file == NULL) {
printf("Unable to open file for writing.\n");
return;
}
struct Node* temp = head;
while (temp != NULL) {
fprintf(file, "%d\n", temp->data);
temp = temp->next;
}
fclose(file);
printf("Data saved to file.\n");
}
// 移动光标到指定位置
void _gotoxy(unsigned char x, unsigned char y) {
COORD coord = { x, y };
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hConsole, coord);
}
int main() {
char ch;
// 加载已有数据
loadFromFile(&head);
do {
system("cls");
_gotoxy(48, 3); printf("---主菜单---");
_gotoxy(50, 5); printf("1-录入数据");
_gotoxy(50, 7); printf("2-查看数据");
_gotoxy(50, 9); printf("3-数据排序");
_gotoxy(50, 11); printf("4-输出数据");
_gotoxy(50, 13); printf("5-保存数据");
_gotoxy(50, 15); printf("6-加载数据");
_gotoxy(50, 17); printf("7-Exit");
_gotoxy(48, 19); printf("Please Choose: ");
_gotoxy(50, 21);
ch = _getch();
_gotoxy(0, 23);
switch(ch) {
case '1':
system("cls");
printf("录入数据\n");
int num;
while (1) {
printf("Enter a number to add to the list (or type 'q' to quit): ");
if (scanf("%d", &num) != 1) {
// 清除输入缓冲区
while (getchar() != '\n');
break;
}
append(&head, num); // 将数字添加到链表中
printf("Data added successfully!\n");
}
printf("Press any key to return to menu.");
_getch();
break;
case '2':
system("cls");
printf("查看数据\n");
printList(head); // 打印链表中的所有元素
printf("Press any key to return to menu.");
_getch();
break;
case '3':
system("cls");
printf("数据排序\n");
if (head == NULL) {
printf("The list is empty.\n");
} else {
bubbleSort(head);
printf("Data sorted successfully!\n");
printList(head);
}
printf("Press any key to return to menu.");
_getch();
break;
case '4':
system("cls");
printf("输出数据\n");
if (head == NULL) {
printf("The list is empty.\n");
} else {
printList(head); // 打印链表中的所有元素
}
printf("Press any key to return to menu.");
_getch();
break;
case '5':
system("cls");
printf("保存数据\n");
saveToFile(head); // 将链表数据保存到文件
printf("Press any key to return to menu.");
_getch();
break;
case '6':
system("cls");
printf("加载数据\n");
loadFromFile(&head); // 从文件加载数据到链表
printf("Press any key to return to menu.");
_getch();
break;
case '7':
system("cls");
printf("Exiting...\n");
Sleep(1500);
break;
default:
system("cls");
printf("Invalid input! Please try again.\nPress any key to continue.");
_getch();
break;
}
} while(ch != '7');
// 释放链表占用的内存
freeList(&head);
return 0;
}
```
### 关键修正点
1. **文件读取**:在 `loadFromFile` 函数中,使用 `fscanf(file, "%d", &data) == 1` 来确保只处理成功读取的情况,避免潜在的无限循环。
2. **输入处理**:在录入数据时,确保用户输入 `q` 或其他非数字字符时能正确退出输入循环,并清除输入缓冲区。
3. **链表初始化**:确保链表在加载数据前后都能正确初始化和释放内存,避免内存泄漏。
4. **光标移动函数**:修正了 `_gotoxy` 函数的参数传递方式,确保坐标正确设置。
### 测试建议
1. **测试数据录入**:确保可以成功录入多个数据,并且可以正确查看、排序和输出。
2. **测试数据保存和加载**:确保数据可以正确保存到文件,并在下次启动程序时加载。
3. **测试错误处理**:尝试输入非数字字符或删除文件,确保程序能够正确处理这些情况而不崩溃。
如果您还有任何问题或需要进一步的帮助,请随时告知!