C语言如何向数组中动态添加数据库查询结果?

在C语言中,向数组中增加数据库相关的数据通常涉及将数据库查询结果存储到数组中,或者动态扩展数组以容纳新数据,以下是详细的实现步骤和代码示例,涵盖静态数组、动态数组以及与常见数据库(如SQLite)的交互方法。

静态数组存储数据库数据

静态数组的长度在编译时确定,适用于已知数据量的场景,以SQLite为例,假设有一个students表,包含idname字段,需将查询结果存入结构体数组。

c 怎么向数组中增加数据库

定义结构体和数组

#include <stdio.h>
#include <sqlite3.h>
#define MAX_STUDENTS 100
typedef struct {
    int id;
    char name[50];
} Student;
Student students[MAX_STUDENTS]; // 静态数组
int student_count = 0; // 当前存储的学生数量

查询数据库并填充数组

int callback(void *data, int argc, char **argv, char **azColName) {
    if (student_count < MAX_STUDENTS) {
        students[student_count].id = atoi(argv[0]);
        strcpy(students[student_count].name, argv[1]);
        student_count++;
    }
    return 0;
}
int main() {
    sqlite3 *db;
    char *errMsg = 0;
    int rc = sqlite3_open("test.db", &db);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "无法打开数据库: %sn", sqlite3_errmsg(db));
        return 1;
    }
    // 执行查询
    rc = sqlite3_exec(db, "SELECT id, name FROM students", callback, 0, &errMsg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL错误: %sn", errMsg);
        sqlite3_free(errMsg);
    }
    // 输出数组内容
    for (int i = 0; i < student_count; i++) {
        printf("ID: %d, Name: %sn", students[i].id, students[i].name);
    }
    sqlite3_close(db);
    return 0;
}

注意事项

  • 静态数组需预先定义最大容量,超出部分会导致数据丢失。
  • 适用于数据量固定且较小的场景。

动态数组存储数据库数据

动态数组通过内存分配(如mallocrealloc)实现长度扩展,适合数据量不确定的情况。

c 怎么向数组中增加数据库

动态分配数组

#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
typedef struct {
    int id;
    char name[50];
} Student;
Student *students = NULL; // 动态数组指针
int capacity = 0; // 当前数组容量
int size = 0; // 当前数据量
void add_student(int id, const char *name) {
    if (size >= capacity) {
        capacity = (capacity == 0) ? 1 : capacity * 2; // 容量不足时扩容
        students = realloc(students, capacity * sizeof(Student));
        if (!students) {
            fprintf(stderr, "内存分配失败n");
            exit(1);
        }
    }
    students[size].id = id;
    strcpy(students[size].name, name);
    size++;
}

查询数据库并动态填充

int callback(void *data, int argc, char **argv, char **azColName) {
    add_student(atoi(argv[0]), argv[1]);
    return 0;
}
int main() {
    sqlite3 *db;
    char *errMsg = 0;
    int rc = sqlite3_open("test.db", &db);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "无法打开数据库: %sn", sqlite3_errmsg(db));
        return 1;
    }
    rc = sqlite3_exec(db, "SELECT id, name FROM students", callback, 0, &errMsg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL错误: %sn", errMsg);
        sqlite3_free(errMsg);
    }
    // 输出数组内容
    for (int i = 0; i < size; i++) {
        printf("ID: %d, Name: %sn", students[i].id, students[i].name);
    }
    free(students); // 释放内存
    sqlite3_close(db);
    return 0;
}

注意事项

  • 动态数组需手动管理内存,避免内存泄漏。
  • 扩容策略通常采用倍增(如capacity *= 2)以减少频繁realloc调用。

数据库与数组的交互优化

使用批量插入减少查询次数

// 假设从CSV文件读取数据并批量插入数据库
void batch_insert(sqlite3 *db, const char *filename) {
    FILE *file = fopen(filename, "r");
    if (!file) return;
    char line[100];
    char sql[200];
    sqlite3_exec(db, "BEGIN TRANSACTION;", 0, 0, 0); // 开启事务
    while (fgets(line, sizeof(line), file)) {
        int id;
        char name[50];
        sscanf(line, "%d,%49s", &id, name);
        sprintf(sql, "INSERT INTO students (id, name) VALUES (%d, '%s');", id, name);
        sqlite3_exec(db, sql, 0, 0, 0);
    }
    sqlite3_exec(db, "COMMIT;", 0, 0, 0); // 提交事务
    fclose(file);
}

使用预处理语句防止SQL注入

void safe_insert(sqlite3 *db, int id, const char *name) {
    sqlite3_stmt *stmt;
    const char *sql = "INSERT INTO students (id, name) VALUES (?, ?);";
    if (sqlite3_prepare_v2(db, sql, -1, &stmt, 0) != SQLITE_OK) {
        fprintf(stderr, "预处理失败: %sn", sqlite3_errmsg(db));
        return;
    }
    sqlite3_bind_int(stmt, 1, id);
    sqlite3_bind_text(stmt, 2, name, -1, SQLITE_STATIC);
    if (sqlite3_step(stmt) != SQLITE_DONE) {
        fprintf(stderr, "执行失败: %sn", sqlite3_errmsg(db));
    }
    sqlite3_finalize(stmt);
}

性能对比与选择建议

方法 优点 缺点 适用场景
静态数组 内存连续,访问速度快 容量固定,无法动态扩展 数据量小且固定
动态数组 容量可扩展,灵活 需手动管理内存,可能频繁扩容 数据量不确定或动态增长
批量插入+事务 减少I/O操作,提升性能 需事务支持,代码复杂度增加 大数据量导入

相关问答FAQs

Q1: 如何处理数据库查询结果为空的情况?
A1: 在回调函数或查询逻辑中检查返回的行数,SQLite的sqlite3_exec回调中可通过argc判断每列数据是否存在,若argc == 0则表示无数据,可在查询后检查student_countsize是否为0,若为空则提示用户或执行默认逻辑。

c 怎么向数组中增加数据库

Q2: 动态数组扩容时如何避免内存碎片?
A2: 可以采用指数扩容策略(如每次容量翻倍)减少realloc调用次数,或使用内存池技术预分配大块内存,在程序结束时务必调用free释放动态数组内存,避免内存泄漏,对于高频操作场景,可考虑使用第三方库(如GLib的GArray)优化内存管理。

【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!

(0)
热舞的头像热舞
上一篇 2025-09-24 11:42
下一篇 2025-09-24 12:04

相关推荐

  • 服务器内存多是什么原因?服务器内存多大合适

    服务器内存资源充足直接决定了业务系统的上限,高内存配置是保障高并发、低延迟及数据高可用的基石,对于企业级应用而言,内存不再是简单的硬件参数,而是决定数据处理效率的核心资产,大容量内存能够显著减少磁盘I/O瓶颈,将频繁访问的热点数据常驻内存,从而实现数量级的性能提升, 这不仅是硬件成本的投入,更是业务连续性和用户……

    2026-03-02
    0012
  • nike fuelband服务器为何关闭?数据还能找回吗?

    Nike FuelBand服务器是支撑整个Nike FuelBand生态系统运行的核心技术基础设施,它不仅负责处理用户运动数据的存储与计算,还通过云端服务实现设备与用户终端的实时连接,随着智能穿戴设备的兴起,Nike FuelBand服务器的设计与运维成为可穿戴技术领域的重要研究案例,其技术架构、数据处理能力和……

    2025-12-10
    005
  • 服务API 发布秒杀

    # 服务API发布秒杀,,通过服务API发布秒杀,实现高效、稳定的限时抢购活动,提升用户参与度和购买体验。

    2025-04-04
    0010
  • 外国动态服务器是做什么的?为何如此受欢迎?

    在当今全球化与数字化深度融合的时代,互联网已成为商业、科研和日常生活的核心基础设施,网络的边界性——基于地理位置的访问限制、内容差异化和安全策略——也为许多跨国活动带来了挑战,为了突破这些无形的壁垒,一种关键技术工具应运而生,它就是外国动态服务器,它不仅仅是一个简单的网络节点,更像是一个数字世界的“变色龙”,为……

    2025-10-09
    007

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

广告合作

QQ:14239236

在线咨询: QQ交谈

邮件:asy@cxas.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信