全栈(C + HTML/CSS/JS + MySQL)开发学生管理系统教程(二)

简介: 教程来源本教程详解C语言CGI程序开发全流程:涵盖Linux环境搭建(GCC、MySQL、Apache)、数据库连接与安全操作、URL解码/HTML转义防XSS、POST数据解析、HTML模板生成及学生管理核心逻辑(增删改查),代码规范,注重安全与实用性。

第二部分:C语言CGI程序开发

2.1 开发环境准备
Linux环境:

# 安装gcc编译器
sudo apt install gcc make

# 安装MySQL开发库
sudo apt install libmysqlclient-dev

# 安装Apache Web服务器(或Nginx)
sudo apt install apache2
sudo a2enmod cgi  # 启用CGI模块
sudo systemctl restart apache2

编译命令模板:

# 编译CGI程序
gcc -o student.cgi student.c -lmysqlclient -I/usr/include/mysql

# 将编译好的程序放到CGI目录
sudo cp student.cgi /usr/lib/cgi-bin/
sudo chmod 755 /usr/lib/cgi-bin/student.cgi

2.2 公共头文件

// common.h - 公共头文件,包含数据库连接、宏定义等
#ifndef COMMON_H
#define COMMON_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>

// ========== 数据库配置宏 ==========
#define DB_HOST "localhost"
#define DB_USER "root"
// 安全提示:生产环境应从配置文件读取,不应硬编码
#define DB_PASS "123456"
#define DB_NAME "student_db"

// ========== HTTP响应头宏 ==========
// HTML内容类型响应头
#define HTTP_HTML "Content-Type: text/html; charset=utf-8\n\n"
// JSON内容类型响应头(用于API风格)
#define HTTP_JSON "Content-Type: application/json; charset=utf-8\n\n"
// 重定向响应头
#define HTTP_REDIRECT(url) "Location: " url "\n\n"

// ========== 方法宏 ==========
// 获取环境变量值的辅助宏
#define GET_ENV(name) getenv(name) ? getenv(name) : ""

// ========== 函数声明 ==========
MYSQL* db_connect();
void db_close(MYSQL *conn);
void url_decode(char *src, char *dest);
void html_escape(const char *src, char *dest);
char* get_post_data();

#endif

2.3 数据库操作函数

// db.c - 数据库操作函数实现
#include "common.h"

/**
 * 数据库连接函数
 * 
 * 功能:建立与MySQL数据库的连接
 * 返回:成功返回MYSQL*指针,失败返回NULL并输出错误信息
 * 
 * 说明:此函数会初始化连接句柄、设置字符集、进行身份认证
 */
MYSQL* db_connect() {
    MYSQL *conn = mysql_init(NULL);
    if (conn == NULL) {
        fprintf(stderr, "mysql_init() failed\n");
        return NULL;
    }

    // 设置字符集为utf8mb4,确保中文正确存储和显示
    mysql_options(conn, MYSQL_SET_CHARSET_NAME, "utf8mb4");

    // 连接数据库(主机、用户、密码、数据库名、端口、socket、标志)
    if (mysql_real_connect(conn, DB_HOST, DB_USER, DB_PASS, 
                           DB_NAME, 0, NULL, 0) == NULL) {
        fprintf(stderr, "mysql_real_connect() failed: %s\n", mysql_error(conn));
        mysql_close(conn);
        return NULL;
    }

    return conn;
}

/**
 * 数据库关闭函数
 * 
 * 功能:释放数据库连接资源
 */
void db_close(MYSQL *conn) {
    if (conn) {
        mysql_close(conn);
    }
}

/**
 * 执行SQL查询
 * 
 * 功能:执行给定的SQL语句
 * 返回:0成功,-1失败
 */
int db_query(MYSQL *conn, const char *sql) {
    if (mysql_query(conn, sql)) {
        fprintf(stderr, "Query failed: %s\nSQL: %s\n", mysql_error(conn), sql);
        return -1;
    }
    return 0;
}

2.4 URL解码与HTML转义函数

// utils.c - 工具函数实现
#include "common.h"
#include <ctype.h>

/**
 * URL解码函数
 * 
 * 功能:将URL编码的字符串解码为原始字符串
 * 例如:%E5%BC%A0%E4%B8%89 → 张三
 * 
 * 原理:URL编码中,%后跟两位十六进制数表示一个字节
 */
void url_decode(char *src, char *dest) {
    char *p = src;
    char *q = dest;

    while (*p) {
        if (*p == '%' && isxdigit(*(p+1)) && isxdigit(*(p+2))) {
            // 解析十六进制数转换为字符
            char hex[3] = {*(p+1), *(p+2), '\0'};
            *q++ = (char)strtol(hex, NULL, 16);
            p += 3;
        } else if (*p == '+') {
            // '+'在URL编码中代表空格
            *q++ = ' ';
            p++;
        } else {
            *q++ = *p++;
        }
    }
    *q = '\0';
}

/**
 * HTML转义函数
 * 
 * 功能:将HTML特殊字符转换为实体,防止XSS攻击
 * 例如:< → <  > → >  & → &  " → "
 */
void html_escape(const char *src, char *dest) {
    while (*src) {
        switch (*src) {
            case '<': strcpy(dest, "<"); dest += 4; break;
            case '>': strcpy(dest, ">"); dest += 4; break;
            case '&': strcpy(dest, "&"); dest += 5; break;
            case '"': strcpy(dest, """); dest += 6; break;
            case '\'': strcpy(dest, "'"); dest += 5; break;
            default: *dest++ = *src; break;
        }
        src++;
    }
    *dest = '\0';
}

/**
 * 获取POST数据
 * 
 * 功能:从标准输入读取POST请求的数据
 * 
 * 说明:环境变量CONTENT_LENGTH指示POST数据长度
 *       需要读取对应长度的数据
 */
char* get_post_data() {
    char *post_data = NULL;
    char *content_length_str = getenv("CONTENT_LENGTH");

    if (content_length_str != NULL) {
        int content_length = atoi(content_length_str);
        if (content_length > 0) {
            post_data = (char*)malloc(content_length + 1);
            if (post_data) {
                fread(post_data, 1, content_length, stdin);
                post_data[content_length] = '\0';
            }
        }
    }

    return post_data;
}

/**
 * 解析查询字符串
 * 
 * 功能:将key1=value1&key2=value2格式的字符串解析为键值对
 */
void parse_query_string(char *query_string, char *params[][2], int *count) {
    char *token;
    char *saveptr;
    *count = 0;

    if (query_string == NULL || *query_string == '\0') return;

    token = strtok_r(query_string, "&", &saveptr);
    while (token != NULL && *count < 50) {
        char *eq_pos = strchr(token, '=');
        if (eq_pos != NULL) {
            *eq_pos = '\0';
            strncpy(params[*count][0], token, 99);
            url_decode(eq_pos + 1, params[*count][1]);
            (*count)++;
        }
        token = strtok_r(NULL, "&", &saveptr);
    }
}

2.5 HTML模板函数

// template.c - HTML页面生成函数
#include "common.h"

/**
 * 输出HTML页面头部
 * 
 * 功能:生成HTML文档的开始部分,包括<!DOCTYPE>、<html>、<head>和
 *       引用的CSS/JS文件
 */
void print_html_header() {
    printf("<!DOCTYPE html>\n");
    printf("<html lang=\"zh-CN\">\n");
    printf("<head>\n");
    printf("    <meta charset=\"UTF-8\">\n");
    printf("    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n");
    printf("    <title>学生管理系统</title>\n");
    printf("    <style>\n");
    printf("        * { margin: 0; padding: 0; box-sizing: border-box; }\n");
    printf("        body { font-family: 'Microsoft YaHei', sans-serif; background: #f0f2f5; }\n");
    printf("        .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; }\n");
    printf("        .container { max-width: 1200px; margin: 20px auto; padding: 0 20px; }\n");
    printf("        .card { background: white; border-radius: 8px; box-shadow: 0 2px 12px rgba(0,0,0,0.1); padding: 20px; margin-bottom: 20px; }\n");
    printf("        .form-group { margin-bottom: 15px; }\n");
    printf("        .form-group label { display: block; margin-bottom: 5px; font-weight: bold; }\n");
    printf("        .form-group input, .form-group select { width: 100%; padding: 8px 12px; border: 1px solid #ddd; border-radius: 4px; }\n");
    printf("        button { background: #667eea; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; }\n");
    printf("        button:hover { background: #5a67d8; }\n");
    printf("        table { width: 100%; border-collapse: collapse; }\n");
    printf("        th, td { padding: 12px; text-align: left; border-bottom: 1px solid #eee; }\n");
    printf("        th { background: #f5f5f5; }\n");
    printf("        .btn-edit { background: #28a745; margin-right: 5px; }\n");
    printf("        .btn-delete { background: #dc3545; }\n");
    printf("        .btn-small { padding: 4px 10px; font-size: 12px; }\n");
    printf("        .filter-bar { margin-bottom: 20px; display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }\n");
    printf("    </style>\n");
    printf("</head>\n");
    printf("<body>\n");
}

/**
 * 输出页面头部导航
 */
void print_navbar() {
    printf("<div class=\"header\">\n");
    printf("    <div class=\"container\">\n");
    printf("        <h1>📚 学生管理系统</h1>\n");
    printf("        <p>欢迎使用学生管理系统,管理学生信息、成绩和班级</p>\n");
    printf("    </div>\n");
    printf("</div>\n");
}

/**
 * 输出HTML页面尾部
 */
void print_html_footer() {
    printf("</body>\n");
    printf("</html>\n");
}

/**
 * 输出错误页面
 */
void print_error_page(const char *message) {
    print_html_header();
    print_navbar();
    printf("<div class=\"container\">\n");
    printf("    <div class=\"card\" style=\"text-align:center; color:#dc3545;\">\n");
    printf("        <h2>操作失败</h2>\n");
    printf("        <p>%s</p>\n", message);
    printf("        <a href=\"/cgi-bin/student.cgi?action=list\"><button>返回首页</button></a>\n");
    printf("    </div>\n");
    printf("</div>\n");
    print_html_footer();
}

2.6 学生管理核心逻辑

// student.c - 学生管理CGI主程序
#include "common.h"
#include <stdlib.h>
#include <string.h>

// 函数声明
void handle_list(MYSQL *conn, char *class_id);
void handle_detail(MYSQL *conn, char *id);
void handle_add(MYSQL *conn);
void handle_edit(MYSQL *conn);
void handle_delete(MYSQL *conn, char *id);
void show_form_add();
void show_form_edit(MYSQL *conn, int id);
void render_student_table(MYSQL_RES *res);

/**
 * 主函数 - CGI程序入口
 * 
 * 执行流程:
 * 1. 获取环境变量REQUEST_METHOD,判断请求类型(GET/POST)
 * 2. 解析查询参数(action、id等)
 * 3. 连接数据库
 * 4. 根据action参数调用对应的处理函数
 * 5. 输出HTTP响应头(Content-Type)
 * 6. 执行具体业务逻辑并输出HTML内容
 */
int main() {
    MYSQL *conn;
    char *method = GET_ENV("REQUEST_METHOD");
    char *query_string = GET_ENV("QUERY_STRING");
    char action[50] = "list";
    char id[10] = "";
    char class_id[10] = "";

    // 解析查询参数
    if (query_string != NULL && strlen(query_string) > 0) {
        char *token;
        char query_copy[512];
        strncpy(query_copy, query_string, 511);
        query_copy[511] = '\0';

        token = strtok(query_copy, "&");
        while (token != NULL) {
            if (strncmp(token, "action=", 7) == 0) {
                strncpy(action, token + 7, 49);
                action[49] = '\0';
            } else if (strncmp(token, "id=", 3) == 0) {
                strncpy(id, token + 3, 9);
                id[9] = '\0';
            } else if (strncmp(token, "class_id=", 9) == 0) {
                strncpy(class_id, token + 9, 9);
                class_id[9] = '\0';
            }
            token = strtok(NULL, "&");
        }
    }

    // 连接数据库
    conn = db_connect();
    if (conn == NULL) {
        printf(HTTP_HTML);
        printf("<html><body><h1>数据库连接失败</h1></body></html>\n");
        return 1;
    }

    // 输出HTTP响应头
    printf(HTTP_HTML);

    // 根据action分发请求
    if (strcmp(action, "list") == 0) {
        handle_list(conn, class_id);
    } else if (strcmp(action, "detail") == 0) {
        handle_detail(conn, id);
    } else if (strcmp(action, "add") == 0) {
        if (strcmp(method, "POST") == 0) {
            handle_add(conn);
        } else {
            show_form_add();
        }
    } else if (strcmp(action, "edit") == 0) {
        if (strcmp(method, "POST") == 0) {
            handle_edit(conn);
        } else if (strlen(id) > 0) {
            show_form_edit(conn, atoi(id));
        }
    } else if (strcmp(action, "delete") == 0 && strlen(id) > 0) {
        handle_delete(conn, id);
    } else {
        handle_list(conn, NULL);
    }

    db_close(conn);
    return 0;
}

/**
 * 处理学生列表查询
 * 
 * 功能:查询学生信息(可选班级筛选),并渲染为表格
 */
void handle_list(MYSQL *conn, char *class_id) {
    char sql[1024];
    MYSQL_RES *res;
    MYSQL_ROW row;

    // 构建SQL查询(支持班级筛选)
    if (class_id != NULL && strlen(class_id) > 0) {
        snprintf(sql, sizeof(sql),
            "SELECT s.id, s.student_no, s.name, s.gender, "
            "c.name as class_name, s.phone "
            "FROM students s "
            "LEFT JOIN classes c ON s.class_id = c.id "
            "WHERE s.class_id = %s "
            "ORDER BY s.id", class_id);
    } else {
        snprintf(sql, sizeof(sql),
            "SELECT s.id, s.student_no, s.name, s.gender, "
            "c.name as class_name, s.phone "
            "FROM students s "
            "LEFT JOIN classes c ON s.class_id = c.id "
            "ORDER BY s.id");
    }

    if (db_query(conn, sql) != 0) {
        print_error_page("查询数据失败");
        return;
    }

    res = mysql_store_result(conn);

    print_html_header();
    print_navbar();

    // 输出筛选栏
    printf("<div class=\"container\">\n");
    printf("    <div class=\"filter-bar\">\n");
    printf("        <form method=\"GET\" action=\"/cgi-bin/student.cgi\" style=\"display:flex; gap:10px;\">\n");
    printf("            <input type=\"hidden\" name=\"action\" value=\"list\">\n");
    printf("            <select name=\"class_id\">\n");
    printf("                <option value=\"\">全部班级</option>\n");

    // 查询班级列表用于筛选下拉框
    MYSQL_RES *class_res;
    MYSQL_ROW class_row;
    if (db_query(conn, "SELECT id, name FROM classes") == 0) {
        class_res = mysql_store_result(conn);
        while ((class_row = mysql_fetch_row(class_res))) {
            printf("                <option value=\"%s\"", class_row[0]);
            if (class_id != NULL && strcmp(class_id, class_row[0]) == 0) {
                printf(" selected");
            }
            printf(">%s</option>\n", class_row[1]);
        }
        mysql_free_result(class_res);
    }

    printf("            </select>\n");
    printf("            <button type=\"submit\">筛选</button>\n");
    printf("            <a href=\"/cgi-bin/student.cgi?action=add\">\n");
    printf("                <button type=\"button\" style=\"background:#28a745;\">+ 添加学生</button>\n");
    printf("            </a>\n");
    printf("        </form>\n");
    printf("    </div>\n");

    // 输出学生表格
    printf("    <div class=\"card\">\n");
    printf("        <h2>学生列表</h2>\n");
    printf("        <table>\n");
    printf("            <thead>\n");
    printf("                <tr><th>学号</th><th>姓名</th><th>性别</th><th>班级</th><th>电话</th><th>操作</th></tr>\n");
    printf("            </thead>\n");
    printf("            <tbody>\n");

    while ((row = mysql_fetch_row(res))) {
        printf("            <tr>");
        printf("<td>%s</td>", row[1] ? row[1] : "");
        printf("<td>%s</td>", row[2] ? row[2] : "");
        printf("<td>%s</td>", row[3] ? row[3] : "");
        printf("<td>%s</td>", row[4] ? row[4] : "");
        printf("<td>%s</td>", row[5] ? row[5] : "");
        printf("<td>");
        printf("<a href=\"/cgi-bin/student.cgi?action=detail&id=%s\">", row[0]);
        printf("<button class=\"btn-small\">查看</button></a>\n");
        printf("<a href=\"/cgi-bin/student.cgi?action=edit&id=%s\">", row[0]);
        printf("<button class=\"btn-small btn-edit\">编辑</button></a>\n");
        printf("<a href=\"/cgi-bin/student.cgi?action=delete&id=%s\" onclick=\"return confirm('确定删除?')\">", row[0]);
        printf("<button class=\"btn-small btn-delete\">删除</button></a>\n");
        printf("</td>");
        printf("</tr>\n");
    }

    printf("            </tbody>\n");
    printf("        </table>\n");
    printf("    </div>\n");
    printf("</div>\n");

    mysql_free_result(res);
    print_html_footer();
}

/**
 * 处理学生详情查看
 * 
 * 功能:根据学生ID查询详细信息,包括基本信息和成绩
 */
void handle_detail(MYSQL *conn, char *id) {
    char sql[1024];
    MYSQL_RES *res;
    MYSQL_ROW row;

    // 查询学生基本信息
    snprintf(sql, sizeof(sql),
        "SELECT s.student_no, s.name, s.gender, s.birth_date, "
        "c.name as class_name, s.phone, s.address "
        "FROM students s "
        "LEFT JOIN classes c ON s.class_id = c.id "
        "WHERE s.id = %s", id);

    if (db_query(conn, sql) != 0) {
        print_error_page("查询学生信息失败");
        return;
    }

    res = mysql_store_result(conn);
    row = mysql_fetch_row(res);

    if (row == NULL) {
        mysql_free_result(res);
        print_error_page("学生不存在");
        return;
    }

    print_html_header();
    print_navbar();

    printf("<div class=\"container\">\n");
    printf("    <div class=\"card\">\n");
    printf("        <h2>学生详细信息</h2>\n");
    printf("        <table style=\"width:100%;\">\n");
    printf("            <tr><th style=\"width:120px;\">学号:</th><td>%s</td></tr>\n", row[0] ? row[0] : "");
    printf("            <tr><th>姓名:</th><td>%s</td></tr>\n", row[1] ? row[1] : "");
    printf("            <tr><th>性别:</th><td>%s</td></tr>\n", row[2] ? row[2] : "");
    printf("            <tr><th>出生日期:</th><td>%s</td></tr>\n", row[3] ? row[3] : "");
    printf("            <tr><th>班级:</th><td>%s</td></tr>\n", row[4] ? row[4] : "");
    printf("            <tr><th>家长电话:</th><td>%s</td></tr>\n", row[5] ? row[5] : "");
    printf("            <tr><th>家庭地址:</th><td>%s</td></tr>\n", row[6] ? row[6] : "");
    printf("        </table>\n");
    printf("        <div style=\"margin-top:20px;\">\n");
    printf("            <a href=\"/cgi-bin/student.cgi?action=edit&id=%s\"><button>编辑信息</button></a>\n", id);
    printf("            <a href=\"/cgi-bin/student.cgi?action=list\"><button>返回列表</button></a>\n");
    printf("        </div>\n");
    printf("    </div>\n");

    mysql_free_result(res);

    // 查询成绩信息
    snprintf(sql, sizeof(sql),
        "SELECT subject, score, exam_date, semester FROM scores WHERE student_id = %s", id);

    if (db_query(conn, sql) == 0) {
        res = mysql_store_result(conn);
        int score_count = mysql_num_rows(res);

        if (score_count > 0) {
            printf("    <div class=\"card\">\n");
            printf("        <h2>考试成绩</h2>\n");
            printf("        <table>\n");
            printf("            <thead><tr><th>科目</th><th>分数</th><th>考试日期</th><th>学期</th></tr></thead>\n");
            printf("            <tbody>\n");

            while ((row = mysql_fetch_row(res))) {
                printf("            <tr>");
                printf("<td>%s</td><td>%s</td><td>%s</td><td>%s</td>", 
                       row[0] ? row[0] : "", row[1] ? row[1] : "", 
                       row[2] ? row[2] : "", row[3] ? row[3] : "");
                printf("</tr>\n");
            }

            printf("            </tbody>\n");
            printf("        </table>\n");
            printf("    </div>\n");
        }
        mysql_free_result(res);
    }

    printf("</div>\n");
    print_html_footer();
}

/**
 * 添加学生表单页面
 * 
 * 功能:显示添加学生的HTML表单
 */
void show_form_add() {
    MYSQL *conn = db_connect();

    print_html_header();
    print_navbar();

    printf("<div class=\"container\">\n");
    printf("    <div class=\"card\">\n");
    printf("        <h2>添加学生</h2>\n");
    printf("        <form method=\"POST\" action=\"/cgi-bin/student.cgi?action=add\">\n");
    printf("            <div class=\"form-group\">\n");
    printf("                <label>学号:</label>\n");
    printf("                <input type=\"text\" name=\"student_no\" required>\n");
    printf("            </div>\n");
    printf("            <div class=\"form-group\">\n");
    printf("                <label>姓名:</label>\n");
    printf("                <input type=\"text\" name=\"name\" required>\n");
    printf("            </div>\n");
    printf("            <div class=\"form-group\">\n");
    printf("                <label>性别:</label>\n");
    printf("                <select name=\"gender\">\n");
    printf("                    <option value=\"男\">男</option>\n");
    printf("                    <option value=\"女\">女</option>\n");
    printf("                </select>\n");
    printf("            </div>\n");
    printf("            <div class=\"form-group\">\n");
    printf("                <label>出生日期:</label>\n");
    printf("                <input type=\"date\" name=\"birth_date\">\n");
    printf("            </div>\n");
    printf("            <div class=\"form-group\">\n");
    printf("                <label>班级:</label>\n");
    printf("                <select name=\"class_id\">\n");

    // 查询班级列表
    if (conn && db_query(conn, "SELECT id, name FROM classes") == 0) {
        MYSQL_RES *res = mysql_store_result(conn);
        MYSQL_ROW row;
        while ((row = mysql_fetch_row(res))) {
            printf("                    <option value=\"%s\">%s</option>\n", row[0], row[1]);
        }
        mysql_free_result(res);
    }

    printf("                </select>\n");
    printf("            </div>\n");
    printf("            <div class=\"form-group\">\n");
    printf("                <label>家长电话:</label>\n");
    printf("                <input type=\"text\" name=\"phone\">\n");
    printf("            </div>\n");
    printf("            <div class=\"form-group\">\n");
    printf("                <label>家庭地址:</label>\n");
    printf("                <input type=\"text\" name=\"address\">\n");
    printf("            </div>\n");
    printf("            <button type=\"submit\">保存</button>\n");
    printf("            <a href=\"/cgi-bin/student.cgi?action=list\"><button type=\"button\">取消</button></a>\n");
    printf("        </form>\n");
    printf("    </div>\n");
    printf("</div>\n");

    if (conn) db_close(conn);
    print_html_footer();
}

/**
 * 处理添加学生请求
 * 
 * 功能:接收POST数据,验证并插入数据库
 */
void handle_add(MYSQL *conn) {
    char *post_data = get_post_data();
    char params[30][2][100] = {0};
    int param_count = 0;
    char sql[2048];
    char escaped_name[200], escaped_no[200], escaped_phone[200], escaped_addr[200];

    if (post_data == NULL) {
        print_error_page("未收到表单数据");
        free(post_data);
        return;
    }

    // 解析POST数据
    parse_query_string(post_data, params, &param_count);

    // 提取字段值
    char student_no[50] = "";
    char name[50] = "";
    char gender[10] = "";
    char birth_date[20] = "";
    char class_id[10] = "";
    char phone[50] = "";
    char address[200] = "";

    for (int i = 0; i < param_count; i++) {
        if (strcmp(params[i][0], "student_no") == 0)
            strcpy(student_no, params[i][1]);
        else if (strcmp(params[i][0], "name") == 0)
            strcpy(name, params[i][1]);
        else if (strcmp(params[i][0], "gender") == 0)
            strcpy(gender, params[i][1]);
        else if (strcmp(params[i][0], "birth_date") == 0)
            strcpy(birth_date, params[i][1]);
        else if (strcmp(params[i][0], "class_id") == 0)
            strcpy(class_id, params[i][1]);
        else if (strcmp(params[i][0], "phone") == 0)
            strcpy(phone, params[i][1]);
        else if (strcmp(params[i][0], "address") == 0)
            strcpy(address, params[i][1]);
    }

    // 验证必填字段
    if (strlen(student_no) == 0 || strlen(name) == 0 || strlen(gender) == 0 || strlen(class_id) == 0) {
        print_error_page("请填写必填字段");
        free(post_data);
        return;
    }

    // 转义特殊字符防止SQL注入
    mysql_real_escape_string(conn, escaped_no, student_no, strlen(student_no));
    mysql_real_escape_string(conn, escaped_name, name, strlen(name));
    mysql_real_escape_string(conn, escaped_phone, phone, strlen(phone));
    mysql_real_escape_string(conn, escaped_addr, address, strlen(address));

    // 构建INSERT语句
    snprintf(sql, sizeof(sql),
        "INSERT INTO students (student_no, name, gender, birth_date, class_id, phone, address) "
        "VALUES ('%s', '%s', '%s', %s, %s, '%s', '%s')",
        escaped_no, escaped_name, gender,
        strlen(birth_date) > 0 ? birth_date : "NULL",
        class_id, escaped_phone, escaped_addr);

    if (db_query(conn, sql) != 0) {
        print_error_page("添加失败,学号可能重复");
    } else {
        // 添加成功,重定向到列表页
        printf("Location: /cgi-bin/student.cgi?action=list\n\n");
    }

    free(post_data);
}
相关文章
|
8天前
|
缓存 人工智能 自然语言处理
我对比了8个Claude API中转站,踩了不少坑,总结给你
本文是个人开发者耗时1周实测的8大Claude中转平台横向评测,聚焦Claude Code真实体验:以加权均价(¥/M token)、内部汇率、缓存支持、模型真实性及稳定性为核心指标。
3435 20
|
20天前
|
人工智能 自然语言处理 安全
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
本文介绍了Claude Code终端AI助手的使用指南,主要内容包括:1)常用命令如版本查看、项目启动和更新;2)三种工作模式切换及界面说明;3)核心功能指令速查表,包含初始化、压缩对话、清除历史等操作;4)详细解析了/init、/help、/clear、/compact、/memory等关键命令的使用场景和语法。文章通过丰富的界面截图和场景示例,帮助开发者快速掌握如何通过命令行和交互界面高效使用Claude Code进行项目开发,特别强调了CLAUDE.md文件作为项目知识库的核心作用。
17984 60
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
|
1天前
|
SQL 人工智能 弹性计算
阿里云发布 Agentic NDR,威胁检测与响应进入智能体时代
欢迎前往阿里云云防火墙控制台体验!
1158 2
|
4天前
|
人工智能 JSON BI
DeepSeek V4 来了!超越 Claude Sonnet 4.5,赶紧对接 Claude Code 体验一把
JeecgBoot AI专题研究 把 Claude Code 接入 DeepSeek V4Pro 的真实体验与避坑记录 本文记录我将 Claude Code 对接 DeepSeek 最新模型(V4Pro)后的真实体验,测试了 Skills 自动化查询和积木报表 AI 建表两个场景——有惊喜,也踩
1857 8
|
15天前
|
人工智能 JavaScript Ubuntu
低成本搭建AIP自动化写作系统:Hermes保姆级使用教程,长文和逐步实操贴图
我带着怀疑的态度,深度使用了几天,聚焦微信公众号AIP自动化写作场景,写出来的几篇文章,几乎没有什么修改,至少合乎我本人的意愿,而且排版风格,也越来越完善,同样是起码过得了我自己这一关。 这个其实OpenClaw早可以实现了,但是目前我觉得最大的区别是,Hermes会自主总结提炼,并更新你的写作技能。 相信就冲这一点,就值得一试。 这篇帖子主要就Hermes部署使用,作一个非常详细的介绍,几乎一步一贴图。 关于Hermes,无论你赞成哪种声音,我希望都是你自己动手行动过,发自内心的选择!
3172 29
|
3天前
|
人工智能 缓存 BI
Claude Code + DeepSeek V4-Pro 真实评测:除了贵,没别的毛病
JeecgBoot AI专题研究 把 Claude Code 接入 DeepSeek V4Pro,跑完 Skills —— OA 审批、大屏、报表、部署 5 大实战场景后的真实体验 ![](https://oscimg.oschina.net/oscnet/up608d34aeb6bafc47f
1479 3
Claude Code + DeepSeek V4-Pro 真实评测:除了贵,没别的毛病
|
4天前
|
机器学习/深度学习 缓存 测试技术
DeepSeek-V4开源:百万上下文,Agent能力比肩顶级闭源模型
DeepSeek-V4正式开源!含V4-Pro(1.6T参数)与V4-Flash(284B参数)双版本,均支持百万token上下文。首创混合注意力架构,Agent能力、世界知识与推理性能全面领先开源模型,数学/代码评测比肩顶级闭源模型。
1737 6
|
5天前
|
人工智能 测试技术 API
阿里Qwen3.6-27B正式开源:网友直呼“太牛了”!
阿里云千问3.6系列重磅开源Qwen3.6-27B稠密大模型!官网:https://t.aliyun.com/U/JbblVp 仅270亿参数,编程能力媲美千亿模型,在SWE-bench等权威基准中表现卓越。支持多模态理解、本地部署及OpenClaw等智能体集成,已开放Hugging Face与ModelScope下载。