【C实现简易内存数据库】4、create实现
来源:互联网 发布:sharpdesk软件 编辑:程序博客网 时间:2024/04/30 09:44
需要在C盘根目录下有create.txt和create2.txt方可运行。
如:create1.txt
create table Student ( id float(4) NOT NULL; name char(100) NULL; grade float(4) NULL; )create2.txt
create table Student2 ( id2 float(4) NOT NULL; name2 char(100) NULL; grade2 float(4) NULL; )
完整源码:
#include <stdio.h> #include <stdlib.h> #include <string.h> enum DataType {floatType, stringType}; struct Row {void** data;Row* next;};struct Column {DataType type;int length;bool allowNull;char name[256];Column* next;};struct Table{char name[256];Row* rowHead;Column* columnHead;int columnCount;Table* next;};Table* tableHead;int createTable(char*,Table*);int getLength(char*);int getColumnTypeLength(char* , DataType* , int*);int main(){Table* t = (Table *)malloc(sizeof(Table));memset(t, 0, sizeof(Table)); char* path;path = "C://create.txt";createTable(path,t);t = (Table *)malloc(sizeof(Table));memset(t, 0, sizeof(Table)); path = "C://create2.txt";createTable(path,t);//testprintf("%s\n",tableHead->name);//Studentprintf("%s\n",tableHead->columnHead->name);//idprintf("%s\n",tableHead->columnHead->next->name);//nameprintf("%s\n",tableHead->next->name);//Student2printf("%s\n",tableHead->next->columnHead->name);//id2printf("%s\n",tableHead->next->columnHead->next->name);//name2getchar();return 1;}/* * 描述:根据给定文件,在内存里填充数据库格式 * 参数:已经打开的文件 * 返回:返回0说明创建失败。返回1则创建成功 */ int createTable(char* path,Table* t){FILE *fp = fopen(path,"r"); t->columnHead = NULL;t->columnCount = 0; char buffer[100]; //第一次读应该读到create fscanf(fp,"%s",buffer); if (stricmp(buffer,"create")) return 0; //第二次读应该读到table fscanf(fp,"%s",buffer); if (stricmp(buffer,"table")) return 0; //第三次读应该读到表名 fscanf(fp,"%s",buffer); strcpy(t->name, buffer); //第四次读应该读到( fscanf(fp,"%s",buffer); if (strcmp(buffer,"(")) return 0; //接下去开始读column内容 Column * current = NULL; fscanf(fp,"%s",buffer); while (!feof(fp) && strcmp(buffer,")")){ //每次循环先创建一个column对象 Column * column = (Column *)malloc(sizeof(Column)); //清空column memset(column, 0, sizeof(Column)); //第一次读应该读到 column name strcpy(column->name, buffer); //第二次读应该读到 column type(column length) fscanf(fp,"%s",buffer); getColumnTypeLength(buffer, &column->type, &column->length)==0; //第三次可能读到NULL; 可能读到; 这两种都代表着可以为空 fscanf(fp,"%s",buffer); if (strcmp(buffer,";")==0 || strcmp(strupr(buffer),"null;")==0) column->allowNull = 1; //第三次读也可能读到NOT,代表着不能为空 else if (stricmp(buffer,"not")==0){ //第四次读应该读到null; fscanf(fp,"%s",buffer); if (!stricmp(buffer,"NULL;")) return 0; column->allowNull = 0; } //因为column是链表结构,所以必有一下几句 1)保留住链表头 2)把链表连起来 3)当前的指针往后移一个 if (t->columnHead == NULL){t->columnHead = column; current = column;}else{current->next = column; current = current->next;}//每创建一个Column,columnCount+1t->columnCount++;//继续读应该读到下一行内容了 fscanf(fp,"%s",buffer); } //将当前Table加到Table链表尾if(tableHead == NULL)tableHead = t;else{Table* last_t = tableHead;while(last_t->next != NULL)last_t = last_t->next;last_t->next = t;}return 1;}/* * 描述:float(4)或者char(100)把括号前后的内容分别保存 * 参数:string -- 整体字符串 * 参数:type -- 解析后返回的type(float/char)(返回) * 参数:length -- 解析后返回的长度(返回) * 返回:返回0说明创建失败。返回1则创建成功 */ int getColumnTypeLength(char * string, DataType * type, int * length){ char * floatHead = "float("; char * charHead = "char("; //如果是float打头的 if (strncmp(string,floatHead,strlen(floatHead))==0){ *type = floatType; string = string+strlen(floatHead); *length = getLength(string); return 1; } else if (strncmp(string,charHead,strlen(charHead))==0){ *type = stringType; string = string+strlen(charHead); *length = getLength(string); return 1; } else{ printf("文件格式有误\n"); return 0; } } /* * 描述:4)或者100)把括号前的数字返回 * 参数:string -- 整体字符串 * 返回:返回解析后的数字 */ int getLength(char * string){ //找到')'的位置 char * end=string; while( *end !=')' ) end++; //把')赋值成'\0' *end='\0'; //把字符串转成数字 return atoi(string); }
常见问题:
#include <stdio.h> #include <string.h> struct Table{char name[256];};Table* tableHead = NULL;int createTable(){Table t;strcpy(t.name,"Student");tableHead = &t;return 0;}int main(){createTable();printf(tableHead->name);getchar();return 0;}
在这段代码中,我们在createTable函数中声明了Table t,将t.name赋值Student,然后将变量t的地址交给全局变量tableHead保存。在main函数中,我们打印tableHead的name,希望得到Student但却发现错误。
原因在于t是声明在createTable函数中的,在函数执行完后,变量t即被释放。虽然我们存下了t的地址,但这个地址上的数据实际上已经被释放了,现在这个地址上存储的数据已经不是我们可以预知的了。
在这种情况下,我们很容易想到在main函数中声明t后再作为参数传给createTable函数。
#include <stdio.h> #include <string.h> struct Table{char name[256];};Table* tableHead = NULL;int createTable(Table t){strcpy(t.name,"Student");tableHead = &t;return 0;}int main(){Table t = {};createTable(t);printf(tableHead->name);getchar();return 0;}但是这样的写法仍是错误的。
原因在于在createTable中的t实际上已经不是main函数中的那个t了,在函数调用时拷贝了一个t的副本传给createTable函数,所以所有的操作都是对这个t的副本操作的,原始的t并没有改变。
解决方法是不要传递t本身,而是传递t的地址,即t的指针。
#include <stdio.h> #include <stdlib.h>#include <string.h> struct Table{char name[256];};Table* tableHead = NULL;int createTable(Table* t){strcpy(t->name,"Student");tableHead = t;return 0;}int main(){Table* t = (Table *)malloc(sizeof(Table)); createTable(t);printf(tableHead->name);getchar();return 0;}这样的写法传递了t的地址,那么createTable函数中的操作都是对这个地址上的变量(即main中的t)进行的。这样我们就可以在main函数中打印出我们想要的“Student”了。
新址:http://www.limisky.com/114.html
0 0
- 【C实现简易内存数据库】4、create实现
- c简易实现数据库
- 【C实现简易内存数据库】3、数据结构设计(2)
- 【C实现简易内存数据库】1、命令的接收解析分发
- 【C实现简易内存数据库】2、数据结构设计(1) --未采用
- 用C语言实现的简易内存池
- 简易array内存池实现
- 简易内存池的实现
- 【C#】简易网页计算器实现
- C语言实现简易三子棋
- C语言实现简易通讯录
- 【简易通讯录】-----C语言实现
- C语言实现简易通讯录
- C语言实现简易版三子棋
- 简易的字符串内存池实现
- 用python实现简易内存监控
- 一个数据库简易浏览功能的实现
- HTML5本地储存实现--简易数据库
- iphone——NSRunLoop概念
- 微信公众帐号开发教程第3篇-开发模式启用及接口配置
- 虚拟机下mac os x10.8 eclipse+svn
- 输出程序Crash时的详细堆栈信息(四)
- nginx 配置高并发
- 【C实现简易内存数据库】4、create实现
- 链队列的基本操作
- OpenNMS技术分析与扩展开发
- 2013-12-23 17:32:05
- 看懂SQL SERVER执行计划
- Spring MVC3 默认页面(welcome-file)问题
- 字符串函数
- Ubuntu上安裝JDK
- 在Eclipse中使用JDBC连接SQL Server 2005 Express