这道题目需要我们编写一个调车信号机管理系统,可以通过菜单方式展现生成、修改、查询和保存信号机信息。
首先根据题目给出的结构体定义,我们可以定义一个结构体类型Signal,并使用malloc函数动态分配内存,以解决不确定信号机数量的问题。结构体中包含信号机名称、是否开放、位置、信号机性质以及前一架和后一架信号机的指针。
根据题目中给出的平面布置图,我们需要记录每个信号机的名称、是否开放、位置和锁闭继电器状态等信息。可以使用一个链表来存储所有的信号机信息,链表中的每个节点对应一个信号机,节点包含了该信号机的各种信息。
接下来需要实现菜单功能,包括信号机生成登记、信号机信息修改、信号机信息查询、信号机信息保存退出四项。对于每个功能,可以使用不同的函数来实现,具体的实现过程可以根据题目要求来编写。
在退出程序时,需要将所有信号机信息保存到文件中,可以使用文件操作函数来实现。可以将信号机信息保存到一个以Signal开头的文件中,文件名可以根据实际情况来确定,例如Signal.txt。
下面是一个简单的程序框架,包含了菜单功能的实现以及信号机信息的保存和读取过程:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义信号机结构体类型
struct Signal {
char Name[10]; // 信号机名称
int KB; // 是否开放,0表示关闭,1表示开放
float Pos; // 信号机位置
int Type; // 信号机性质,0表示调车信号机,1表示列车信号机
struct Signal *next, *prev; // 前一架信号机指针,后一架信号机指针
};
// 定义全局变量,保存链表头指针和信号机数量
struct Signal *head = NULL;
int count = 0;
// 声明函数
void displayMenu();
void saveToFile();
void loadFromFile();
void addSignal();
void modifySignal();
void searchSignal();
// 主函数
int main() {
// 从文件中读取信号机信息
loadFromFile();
// 显示菜单,根据用户选择执行相应的操作
int choice;
do {
displayMenu();
scanf("%d", &choice);
switch (choice) {
case 1:
addSignal();
break;
case 2:
modifySignal();
break;
case 3:
searchSignal();
break;
case 4:
saveToFile();
break;
case 5:
printf("程序已退出\n");
break;
default:
printf("无效选择,请重新输入\n");
break;
}
} while (choice != 5);
// 释放链表内存
struct Signal *p = head;
while (p) {
struct Signal *temp = p;
p = p->next;
free(temp);
}
return 0;
}
// 显示菜单
void displayMenu() {
printf("请选择操作:\n");
printf("1. 信号机生成登记\n");
printf("2. 信号机信息修改\n");
printf("3. 信号机信息查询\n");
printf("4. 信号机信息保存退出\n");
printf("5. 退出\n");
}
// 将所有信号机信息保存到文件中
void saveToFile() {
// 打开文件,如果文件不存在则创建
FILE *fp = fopen("Signal.txt", "w");
if (fp == NULL) {
printf("文件打开失败\n");
return;
}
// 写入信号机数量
fprintf(fp, "%d\n", count);
// 遍历链表,将每个节点的信息写入文件中
struct Signal *p = head;
while (p) {
fprintf(fp, "%s %d %.2f %d\n", p->Name, p->KB, p->Pos, p->Type);
p = p->next;
}
// 关闭文件
fclose(fp);
}
// 从文件中读取信号机信息
void loadFromFile() {
// 打开文件,如果文件不存在则直接返回
FILE *fp = fopen("Signal.txt", "r");
if (fp == NULL) {
return;
}
// 读取信号机数量
fscanf(fp, "%d", &count);
// 遍历文件中的每一行,解析出信号机的各项信息,并创建对应的节点插入链表中
for (int i = 0; i < count;续写程序:
```c
// 创建新节点
struct Signal *node = (struct Signal *)malloc(sizeof(struct Signal));
// 读取节点信息
fscanf(fp, "%s %d %f %d", node->Name, &(node->KB), &(node->Pos), &(node->Type));
// 将节点插入链表尾部
if (head == NULL) {
head = node;
node->next = NULL;
node->prev = NULL;
} else {
struct Signal *p = head;
while (p->next) {
p = p->next;
}
p->next = node;
node->prev = p;
node->next = NULL;
}
}
// 关闭文件
fclose(fp);
}
// 添加一个新的信号机
void addSignal() {
// 创建新节点
struct Signal *node = (struct Signal *)malloc(sizeof(struct Signal));
node->next = NULL;
node->prev = NULL;
// 读取节点信息
printf("请输入信号机名称:");
scanf("%s", node->Name);
printf("请输入信号机是否开放(0表示关闭,1表示开放):");
scanf("%d", &(node->KB));
printf("请输入信号机位置:");
scanf("%f", &(node->Pos));
printf("请输入信号机性质(0表示调车信号机,1表示列车信号机):");
scanf("%d", &(node->Type));
// 将节点插入链表尾部
if (head == NULL) {
head = node;
node->next = NULL;
node->prev = NULL;
} else {
struct Signal *p = head;
while (p->next) {
p = p->next;
}
p->next = node;
node->prev = p;
node->next = NULL;
}
// 更新信号机数量
count++;
printf("信号机添加成功\n");
}
// 修改一个已有的信号机
void modifySignal() {
// 获取要修改的信号机名称
char name[10];
printf("请输入要修改的信号机名称:");
scanf("%s", name);
// 遍历链表,查找要修改的信号机
struct Signal *p = head;
while (p) {
if (strcmp(p->Name, name) == 0) {
// 找到了要修改的信号机,提示用户输入新的信息
printf("请输入新的信号机是否开放(0表示关闭,1表示开放):");
scanf("%d", &(p->KB));
printf("请输入新的信号机位置:");
scanf("%f", &(p->Pos));
printf("请输入新的信号机性质(0表示调车信号机,1表示列车信号机):");
scanf("%d", &(p->Type));
printf("信号机信息修改成功\n");
return;
}
p = p->next;
}
Copy
// 没有找到要修改的信号机,输出提示信息
printf("没有找到该信号机\n");
}
// 查询一个已有的信号机
void searchSignal() {
// 获取要查询的信号机名称
char name[10];
printf("请输入要查询的信号机名称:");
scanf("%s", name);
less
Copy
// 遍历链表,查找要查询的信号机
struct Signal *p = head;
while (p) {
if (strcmp(p->Name, name) == 0) {
// 找到了要查询的信号机,输出信号机信息
printf("信号机名称:%s\n", p->Name);
printf("信号机是否开放:%d\n", p->KB);
printf("信号机位置:%.2f\n", p->Pos);
printf("信号机性质:%d\n", p->Type);
return;
}
p = p->next;
}
// 没有找到要查询的信号机,输出提示信息
printf("没有找到该信号机\n");
}
这里我们实现了三个菜单功能:添加信号机、修改信号机和查询信号机。在添加信号机功能中,我们创建了一个新的节点,并从用户输入中读取节点的各项信息,然后将该节点插入到链表的末尾。在修改信号机功能中,我们先从用户输入中获取要修改的信号机名称,然后遍历链表查找该信号机,如果找到了就提示用户输入新的信息并更新节点的各项属性。在查询信号机功能中,我们先从用户输入中获取要查询的信号机名称,然后遍历链表查找该信号机,如果找到了就输出该信号机的各项属性。
最后,在程序退出时,我们需要将所有信号机信息保存到文件中。我们可以在保存函数中遍历链表,将每个节点的信息写入文件中,然后关闭文件。具体实现可参考之前的代码:
// 将所有信号机信息保存到文件中
void saveToFile() {
// 打开文件,如果文件不存在则创建
FILE *fp = fopen("Signal.txt", "w");
if (fp == NULL) {
printf("文件打开失败\n");
return;
}
// 写入信号机数量
fprintf(fp, "%d\n", count);
// 遍历链表,将每个节点的信息写入文件中
struct Signal *p = head;
while (p) {
fprintf(fp, "%s %d %.2f %d\n", p->Name, p->KB, p->Pos, p->Type);
p = p->next;
}
// 关闭文件
fclose(fp);
}
这里我们先打开文件,如果文件不存在则创建。然后,我们先将信号机数量写入文件中,再遍历链表,将每个节点的信息依次写入文件中。写入完成后,关闭文件即可。
在程序启动时,我们需要读取之前保存的信号机信息。我们可以在程序启动时调用一个读取函数,遍历文件中的每一行,解析出每个信号机的各项信息,并创建对应的节点插入到链表中。具体实现可参考之前的代码:
c
Copy
```c
// 从文件中读取信号机信息
void loadFromFile() {
// 打开文件,如果文件不存在则直接返回
FILE *fp = fopen("Signal.txt", "r");
if (fp == NULL) {
return;
}
// 读取信号机数量
fscanf(fp, "%d", &count);
// 遍历文件中的每一行,解析出信号机的各项信息,并创建对应的节点插入链表中
for (int i = 0; i < count; i++) {
// 创建新节点
struct Signal *node = (struct Signal *)malloc(sizeof(struct Signal));
// 读取节点信息
fscanf(fp, "%s %d %f %d", node->Name, &(node->KB), &(node->Pos), &(node->Type));
// 将节点插入链表尾部
if (head == NULL) {
head = node;
node->next = NULL;
node->prev = NULL;
} else {
struct Signal *p = head;
while (p->next) {
p = p->next;
}
p->next = node;
node->prev =p;
node->next = NULL;
}
}
// 关闭文件
fclose(fp);
}
这里我们先打开文件,如果文件不存在则直接返回。然后,我们先读取信号机数量,然后遍历文件中的每一行,解析出信号机的各项信息,并创建对应的节点插入到链表中。创建节点的过程与添加信号机功能中的相同。最后,关闭文件即可。
综上所述,我们实现了一个基于双向链表的信号机管理系统,可以实现信号机的添加、修改、查询和保存等功能。如果需要扩展功能,可以在此基础上进行修改和拓展。