通过c实现简易关系数据库,实现表的创建,数据的增删(改与查还未实现),并实现简单笔记本功能。
整个工程的思路是用记事簿(.txt)作为数据库的承载工具,用双链表作为数据库在内存中的承载工具,但这里不得不说双链表不是随机存储那如果数据库的主要功能是搜索,排序和修改的话那么链型数据结构的效率偏低(事实上,数据库的主要工作就是改和查),所以不得不说这次工程是一个失败的工程,但如果你不嫌效率低的话也可以参考一下。
实现难点:写这个工程我遇到过几个问题,1如何将成对出现的字符串储存在内存里,一开始我想的是用顺序表的结构,但由于顺序表大小有限,而数据库存储的数据是海量的,所以不好确定初始的表最大值。2.如何从记事本中提取信息,一开始我打算将信息转码然后存储,但由于转码后情况复杂,而另一方面我也没学过编码方面的知识,所以很容易出现各种情况的bug,为了保险起见我用*</这三个符号作为间隔符,一定程度上减低了任务的难度,同时在decodepart里第一次处理实际问题时使用了递归算法,应该也提高了不少效率。最后一点便是c的string太难用了,搜了很久才知道很多函数还是要自己手写。
以下是源码:
1.dbtype:数据库底层数据结构(双向链表,子单元为string):
#ifndef DBTYPE_H
#define DBTYPE_H
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#define ERROR -1
typedef struct list *PList;
typedef struct Node *PNode;
typedef char *Elem;
struct list{
int ava;
PNode head;
PNode tail;
};
struct Node{
Elem elem;
PNode next;
};
int initNode(PNode &p){
if(!(p=(PNode)malloc(sizeof(Node)))){
free(p);
return ERROR;
}
p->next=NULL;
return 1;
}
int initList(PList &p){
if(!(p=(PList)malloc(sizeof(list)))){
free(p);
return ERROR;
}
PNode pp;
initNode(pp);
p->head=NULL;
p->tail=NULL;
p->ava=1;
return 1;
}
int isEmpty(PList p){
if(p->ava==1) return 1;
return 0;
}
void append(PList p,Elem elem){
PNode pp;
initNode(pp);
int len=strlen(elem)+1;
pp->elem=(Elem)malloc(sizeof(char)*len);
strcpy(pp->elem,elem);
if(!(p->head)){
p->head=pp;
p->tail=pp;
}else{
p->tail->next=pp;
p->tail=pp;
}
}
int getlen(PList p){
PNode pp=p->head;
int re=0;
while(pp){
++re;
pp=pp->next;
}
return re;
}
void readAllList(PList p){
if(!isEmpty(p)){
return;
}
PNode pp=p->head;
while(pp){
printf("%c",pp->elem);
pp=pp->next;
}
printf("\n");
}
Elem getElem(PList p,int id){
PNode pp=p->head;
int i=1;
while(pp){
if(i==id){
return pp->elem;
}
pp=pp->next;
i++;
}
return 0;
}
void DelElem(PList p,int id){
PNode pp=p->head;
int i=1;
if(id==1){
p->head=pp->next;
free(pp);
}else{
while(pp){
if(i+1==id){
PNode ppp=pp->next;
pp->next=ppp->next;
free(ppp->elem);
free(ppp);
}
pp=pp->next;
i++;
}
}
}
void insert(PList p,Elem e,int id){
PNode p2=p->head;
PNode p3;
initNode(p3);
int i=1;
if(id==1){
p->head=p3;
p3->next=p2;
p3->elem=e;
}else{
while(p2){
if(i+1==id){
p3->next=p2->next;
p2->next=p3;
p3->elem=e;
}
i++;
p2=p2->next;
}
}
}
void clearList(PList p){
PNode pp=p->head;
while(pp){
PNode p3=pp;
pp=pp->next;
free(p3->elem);
free(p3);
}
free(p);
}
void listcat(PList p1,PList p2){
p1->tail->next=p2->head;
p1->tail=p2->tail;
free(p2);
}
#endif
2.集成数据库函数并建立笔记本系统
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include <stdlib.h>
#include"dbtype.h"
typedef char *pchar;
char* readFile(char *path){
FILE *fp;
char *ch1;
char ch;
if((fp=fopen(path,"r"))==NULL) {
printf("file cannot be opened/n");
}
int len=0;
while((ch=fgetc(fp))!=EOF)
len++;
ch1=(char*)malloc(sizeof(char)*((int)(len+1)));
strcpy(ch1,"");
fclose(fp);
if((fp=fopen("db.txt","r"))==NULL) {
printf("file cannot be opened/n");
}
int i=0;
while((ch=fgetc(fp))!=EOF) {
*(ch1+i)=ch;
i++;
}
fclose(fp);
return ch1;
}
void writeFile(char* ch,char* path){
FILE *fp;
if((fp=fopen(path,"w"))==NULL) {
printf("file cannot be opened/n");
}
int len=strlen(ch);
for(int i=0;i<len;i++){
fputc(ch[i],fp);
}
fclose(fp);
}
char* mix(PList p){
PNode pp=p->head;
int len=0;
while(pp){
len+=strlen(pp->elem)+1;
pp=pp->next;
}
char *ch=(char*)malloc(sizeof(char)*((len+1)+1));
strcpy(ch,"");
pp=p->head;
while(pp){
strcat(ch,pp->elem);
strcat(ch,"/");
pp=pp->next;
}
strcat(ch,"<");
clearList(p);
return ch;
}
char* mixTAC(PList p1,PList p2){
char *ch1=mix(p1);
char *ch2=mix(p2);
int len=strlen(ch1)+strlen(ch2)+2;
char *ch=(char*)malloc(sizeof(char)*len);
strcpy(ch,"");
strcat(ch,ch1);
strcat(ch,"*");
strcat(ch,ch2);
return ch;
}
char* strsub(char *ch,int start,int end){
char *cho=(char*)malloc(sizeof(char)*(end-start+2));
int i=start;
int j=0;
while(*(ch+i)){
*(cho+j)=*(ch+i);
if(i==end){
break;
}
i++;
j++;
}
*(cho+j+1)=0;
return cho;
}
void decodePart(char *ch,PList p){
int i=0;
while(*(ch+i)!=47) i++;
append(p,strsub(ch,0,i-1));
int len=strlen(ch);
if(*(ch+i+1)==60){
return;
}
decodePart(strsub(ch,i+1,len-1),p);
}
void decodeDB(char *ch,PList &p1,PList &p2){
char *ch1;
char *ch2;
int breakp=0;
int i=0;
while(*(ch+i)){
if(*(ch+i)==42){
break;
}
i++;
}
ch1=(char*)malloc(sizeof(char)*(i+1));
ch2=(char*)malloc(sizeof(char)*(strlen(ch)-i));
ch1=strcpy(ch1,"");
ch2=strcpy(ch2,"");
ch1=strsub(ch,0,i-1);
ch2=strsub(ch,i+1,strlen(ch)-1);
decodePart(ch1,p1);
decodePart(ch2,p2);
}
void readData(PList &p1,PList &p2){
int len1=getlen(p1);
int len2=getlen(p2);
for(int j=1;j<=len2;j++){
if(j%len1==0){
printf("%s :",getElem(p1,len1));
}else{
printf("%s :",getElem(p1,j%len1));
}
printf("%s\n",getElem(p2,j));
}
}
void getdata(char *path,PList &p1,PList &p2){
char *cho=readFile("db.txt");
int k=0;
int kk=0;
int len=strlen(cho);
while(kk!=2){
if(*(cho+k)==60){
kk++;
}
k++;
}
char *ch;
ch=strsub(cho,0,k);
initList(p1);
initList(p2);
decodeDB(ch,p1,p2);
}
void writedata(PList p1,PList p2){
char *ch=mixTAC(p1,p2);
writeFile(ch,"db.txt");
};
int main(){
printf("欢迎使用xperdit的私人日志,搭载xperdit1.0\n");
printf("输入log查询日志与id\n");
printf("输入id查询具体id的日志\n");
printf("输入write写日志\n");
printf("输入del删除日志\n");
printf("输入exit退出\n");
PList p1;PList p2;
getdata("db.txt",p1,p2);
while(1) {
char ch[50];
scanf("%s",ch);
if(strcmp(ch,"log")==0){
PNode p=p2->head;
while(p){
printf("ID :%s ",p->elem);
p=p->next;
printf("Title :%s\n",p->elem);
p=p->next->next;
}
}else if(strcmp(ch,"id")==0){
PNode p=p2->head;
char c[5];
printf("请输入id号");
scanf("%s",c);
int i=1;
while(p){
if(strcmp(p->elem,c)==0){
printf("Title:\n%s\n",p->next->elem);
printf("Content:\n%s\n",p->next->next->elem);
break;
}
p=p->next->next->next;
}
}else if(strcmp(ch,"write")==0){
gets(ch);
PNode p=p2->head;
char *id;
while(p){
id=p->elem;
p=p->next;
p=p->next;
p=p->next;
}
int index=atoi(id);
index++;
char iid[5];
itoa(index,iid,10);
append(p2,iid);
char in[20];
printf("Title:\n");
gets(in);
printf("\n");
append(p2,in);
char in2[1000];
printf("Content:\n");
gets(in2);
append(p2,in2);
printf("\n");
writedata(p1,p2);
getdata("db.txt",p1,p2);
}else if(strcmp(ch,"del")==0){
char in[5];
printf("输入要删除的id号");
scanf("%s",in);
PNode p=p2->head;
int i=1;
while(p){
if(strcmp(p->elem,in)==0){
p=p->next->next->next;
DelElem(p2,i);
DelElem(p2,i);
DelElem(p2,i);
i=i+3;
while(p){
char *cho;
cho=(char*)malloc(sizeof(char)*5);
cho=p->elem;
int id=atoi(cho);
id--;
itoa(id,cho,10);
strcpy(p->elem,cho);
p=p->next;
p=p->next;
p=p->next;
}
}else{
p=p->next->next->next;
i=i+3;
}
}
writedata(p1,p2);
getdata("db.txt",p1,p2);
}
}
return 0;
}
最后谈一下这次练手的心得,c作为现今高级语言中的底层语言真是开发不易,光是写这三百多行代码就用了我大半天,要是java最多一个小时就能完成。但效率损失的背后换来的是速度的提升,另一方面c单纯的作为一种学习语言可以让人更深入的了解语言与计算机衔接的那部分知识,而不像只学习面向对象的人那样迷失在黑箱的迷宫里。