📜  C中CSV文件的关系数据库(1)

📅  最后修改于: 2023-12-03 14:40:25.031000             🧑  作者: Mango

C中CSV文件的关系数据库

CSV(Comma Separated Values)文件是一种常见的数据存储格式,它通常用来存储简单的表格数据。在C语言中,我们可以通过读写CSV文件来实现简单的关系数据库。

CSV文件格式

在CSV文件中,每行代表一条记录,每个字段用逗号(或其他字符)分隔。例如,下面是一个简单的CSV文件:

id,name,age
1,Alice,20
2,Bob,25
3,Charlie,30

第一行通常是字段名,后面每行代表一条记录。可以看出,CSV文件类似于一个表格形式的数据,其中每一列代表一种数据类型。

读取CSV文件

在C语言中,我们可以使用fgets()函数逐行读取CSV文件,并使用strtok()函数解析每行中的字段。下面是一个简单的例子:

#include <stdio.h>
#include <string.h>

#define MAX_LINE_LEN 1024
#define MAX_FIELD_NUM 10
#define FIELD_DELIMITER ','

typedef struct {
    int id;
    char name[64];
    int age;
} Person;

int main() {
    FILE *fp = fopen("data.csv", "r");
    if (fp == NULL) {
        printf("failed to open file\n");
        return 1;
    }

    char line[MAX_LINE_LEN];
    char *fields[MAX_FIELD_NUM];
    int row = 0;
    while (fgets(line, sizeof(line), fp) != NULL) {
        int col = 0;
        for (char *field = strtok(line, ",\n"); field != NULL; field = strtok(NULL, ",\n")) {
            fields[col++] = field;
        }
        if (row > 0) {
            Person person;
            person.id = atoi(fields[0]);
            strcpy(person.name, fields[1]);
            person.age = atoi(fields[2]);
            printf("id=%d, name=%s, age=%d\n", person.id, person.name, person.age);
        }
        row++;
    }

    fclose(fp);
    return 0;
}

上述例子中,我们定义了一个Person结构体表示CSV文件中的一条记录,使用fgets()函数逐行读取文件,并使用strtok()函数解析每行中的字段。由于第一行是字段名,我们可以通过row变量的值来判断当前行是否是第一行,再决定是否要将字段的值读取到对应的Person结构体中。

写入CSV文件

与读取CSV文件相反,我们同样可以使用fprintf()函数将一条记录写入到CSV文件中。下面是一个简单的例子:

#include <stdio.h>

#define CSV_FILE "data.csv"

typedef struct {
    int id;
    char name[64];
    int age;
} Person;

int main() {
    FILE *fp = fopen(CSV_FILE, "a");
    if (fp == NULL) {
        printf("failed to open file\n");
        return 1;
    }

    Person person = {4, "David", 35};
    fprintf(fp, "%d,%s,%d\n", person.id, person.name, person.age);

    fclose(fp);
    return 0;
}

上述例子中,我们同样定义了一个Person结构体表示要写入到CSV文件中的一条记录,使用fprintf()函数将这条记录写入到CSV文件中。

使用CSV文件作为关系数据库

通过读取和写入CSV文件,我们可以实现一个简单的关系数据库。例如,我们可以定义一个PersonList结构体来表示一个人员名单:

#include <stdio.h>
#include <string.h>

#define MAX_LINE_LEN 1024
#define MAX_FIELD_NUM 10
#define FIELD_DELIMITER ','
#define CSV_FILE "person_list.csv"

typedef struct {
    int id;
    char name[64];
    int age;
} Person;

typedef struct {
    Person persons[100];
    int count;
} PersonList;

void load_person_list(PersonList *person_list) {
    FILE *fp = fopen(CSV_FILE, "r");
    if (fp == NULL) {
        printf("failed to open file\n");
        return;
    }

    char line[MAX_LINE_LEN];
    char *fields[MAX_FIELD_NUM];
    int row = 0;
    while (fgets(line, sizeof(line), fp) != NULL) {
        int col = 0;
        for (char *field = strtok(line, ",\n"); field != NULL; field = strtok(NULL, ",\n")) {
            fields[col++] = field;
        }
        if (row > 0) {
            Person person;
            person.id = atoi(fields[0]);
            strcpy(person.name, fields[1]);
            person.age = atoi(fields[2]);
            person_list->persons[row-1] = person;
            person_list->count++;
        }
        row++;
    }

    fclose(fp);
}

void save_person_list(PersonList *person_list) {
    FILE *fp = fopen(CSV_FILE, "w");
    if (fp == NULL) {
        printf("failed to open file\n");
        return;
    }

    fprintf(fp, "id,name,age\n");
    for (int i = 0; i < person_list->count; i++) {
        Person person = person_list->persons[i];
        fprintf(fp, "%d,%s,%d\n", person.id, person.name, person.age);
    }

    fclose(fp);
}

void add_person(PersonList *person_list, Person person) {
    person_list->persons[person_list->count] = person;
    person_list->count++;
}

void remove_person(PersonList *person_list, int id) {
    for (int i = 0; i < person_list->count; i++) {
        if (person_list->persons[i].id == id) {
            for (int j = i+1; j < person_list->count; j++) {
                person_list->persons[j-1] = person_list->persons[j];
            }
            person_list->count--;
            break;
        }
    }
}

int main() {
    PersonList person_list = {0};
    load_person_list(&person_list);

    Person person = {4, "David", 35};
    add_person(&person_list, person);

    remove_person(&person_list, 2);

    save_person_list(&person_list);

    return 0;
}

上述代码中,我们定义了一个PersonList结构体来表示一个人员名单,包含了人员记录数组和人员记录数量。使用load_person_list()函数将CSV文件中的记录读取到PersonList结构体中,使用save_person_list()函数将PersonList结构体中的记录保存到CSV文件中。我们同时还定义了add_person()remove_person()函数来添加和删除一条记录。在程序中,我们首先调用load_person_list()函数将CSV文件中的记录读取到person_list变量中,然后调用add_person()函数添加一条记录,再调用remove_person()函数删除一条记录,最后调用save_person_list()函数将person_list变量中的记录保存到CSV文件中。

总之,通过读写CSV文件,我们可以实现简单的关系数据库。和传统的关系数据库相比,CSV文件具有易读易写的特点,对于一些简单的应用场景非常适用。