You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言学生管理系统多文件拆分、头文件及Makefile编写方法

C语言多文件拆分规则与问题修复

核心拆分规则

  • 头文件(.h)仅存放声明内容:包括公共结构体定义、函数声明、宏定义,禁止在头文件中写函数实现、全局变量的实际定义,否则多文件包含时会触发重复定义错误
  • 头文件必须添加防重复包含保护,避免同一头文件被多次引入引发编译冲突
  • 跨文件使用的全局变量,需要在头文件中用extern关键字声明,仅在某一个.c源文件中做实际的变量定义
  • 自定义头文件在.c文件中引入时使用双引号包裹,系统标准库头文件使用尖括号包裹
  • 主函数main()单独存放于main.c,业务处理逻辑独立存放于process.c

原代码自带bug说明

拆分前的原始代码本身存在多处逻辑错误,拆分时一并修复:

  • List函数循环条件书写错误:while(temp =! NULL)为赋值+逻辑非运算,正确写法为while(temp != NULL)
  • Search、Delete函数字符串比较逻辑错误:误用字符串拷贝函数strcpy做比较,会直接覆盖链表节点存储的姓名数据,正确比较函数为strcmp,字符串相等时返回值为0
  • Delete函数结构体类型书写错误:定义的结构体名为struct Person,代码中误写为struct Student
  • 主循环逻辑缺陷:执行完单次操作后未重新读取用户输入,会触发死循环
  • 打印语句缺少换行符,输出内容会挤在同一行

拆分后完整代码

1. main.h(公共头文件)

#ifndef MAIN_H
#define MAIN_H

// 引入依赖的标准库
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 公共结构体定义
struct Person{
    char name[20];
    char phone[15];
    struct Person* next;
};

// 跨文件全局变量声明
extern struct Person* head;

// 功能函数声明
void Enroll(char* name, char* phone);
void List();
void Search(char* name);
void Delete(char* name);

#endif

2. process.c(数据处理逻辑实现)

#include "main.h"

// 全局链表头节点实际定义,整个程序仅在此处定义一次
struct Person* head = NULL;

void Enroll(char* name, char* phone){
    struct Person* person = (struct Person*) malloc(sizeof(struct Person));
    strcpy(person->name, name);
    strcpy(person->phone, phone);
    person->next = NULL;

    if (head == NULL){
        head = person;
    }else{
        person->next = head;
        head = person;
    }
}

void List(){
    struct Person* temp = head;
    printf("---List---\n");
    while(temp != NULL){
        printf("%s      %s\n", temp->name, temp->phone);
        temp = temp->next;
    }
}

void Search(char* name){
    struct Person* temp = head;
    while(temp != NULL){
        if (strcmp(temp->name, name) == 0){
            printf("%s      %s\n", temp->name, temp->phone);
            return;
        }
        temp = temp->next;
    }
    printf("%s Could not find\n", name);
}


void Delete(char* name){
    struct Person* temp1 = head;
    struct Person* temp2 = head;
    while(temp1 != NULL){
        if (strcmp(temp1->name, name) == 0){
            if (temp1 == temp2){
                head = head->next;
                free(temp1);
            }else{
                temp2->next = temp1->next;
                free(temp1);
            }
            printf("%s Delete Success\n", name);
            return;
        }
        temp2 = temp1;
        temp1 = temp1->next;
    }
    printf("%s Could not find\n", name);
}

3. main.c(主函数交互逻辑)

#include "main.h"

int main(){
    char name[20];
    char phone[15];
    int select;

    printf("Welcome to the Enrollment Management System!\n");
    printf("[1] Enroll      [2] List        [3] Search      [4] Delete      [5]Quit\nSelection: ");
    scanf("%d", &select);
    while(select != 5){
        if (select == 1){
            printf("Name: ");
            scanf("%s", name);
            printf("Phone: ");
            scanf("%s", phone);
            Enroll(name, phone);
        }
        if (select == 2){
            List();
        }
        if (select == 3){
            printf("Name: ");
            scanf("%s", name);
            Search(name);
        }
        if (select == 4){
            printf("Name: ");
            scanf("%s", name);
            Delete(name);
        }
        // 每次操作完成后重新读取用户选择,避免死循环
        printf("\n[1] Enroll      [2] List        [3] Search      [4] Delete      [5]Quit\nSelection: ");
        scanf("%d", &select);
    }
    return 0;
}

4. Makefile(编译配置)

CC = gcc
CFLAGS = -Wall -g
TARGET = student_manage
OBJS = main.o process.o

all: $(TARGET)

$(TARGET): $(OBJS)
	$(CC) $(CFLAGS) -o $@ $^

clean:
	rm -f $(OBJS) $(TARGET)

编译运行方法

在代码所在目录执行make命令即可自动完成编译,生成名为student_manage的可执行文件,执行./student_manage即可启动程序;执行make clean可清除所有编译生成的中间文件和可执行程序。

内容的提问来源于stack exchange,提问作者Daulet Suyenish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 19:51:18