xdoj-1298(模拟--简易SQL解释器)
一 知识点:
1 substr有2种用法:
假设:string s = "0123456789";
string sub1 = s.substr(5); //只有一个数字5表示从下标为5开始一直到结尾:sub1 = "56789"
string sub2 = s.substr(5, 3); //从下标为5开始截取长度为3位:sub2 = "567"
2 find( x, p ) 从p位置开始查找字符x的位置
3 c++的split函数(自己搭建),利用strtok函数
vector <string> split (const string& dem,const string & str) {// 将以dem为分隔的字符串分割
vector <string> res;
char *ss = new char[str.size() + ];
strcpy (ss, str.c_str());// string转字符串
char*p = strtok(ss, dem);
while (p) {
string s = p;
res.push_back(s);
p = strtok(NULL, dem);
}
return res;
}
二 想法
1 用split提取有用信息
2 对于复合查询采用递归方式的查询
三 代码
#include <bits/stdc++.h>
using namespace std;
struct head {
vector <string> col;
};
head h[]; int cnt = ;
map <string, int> mapp;
struct data {
int id;// 对应的表头
int num; // 有多少行
vector <string> c []; //存储每行的信息
int a[]; // 存储每行各元素所对应的列
};
data d[];
const char* dem = ", ";
string sub (const string& str, int p, char last) {// 截取从p位置到以last结尾的字符串(不包括last)
int p2 = str.find(last, p);// 从p位置开始查找last
return str.substr(p, p2 - p);// 从p位置开始长度为(p2-p)的字符串
}
vector <string> split (const string & str) {// 将以dem为分隔的字符串分割
vector <string> res;
char *ss = new char[str.size() + ];
strcpy (ss, str.c_str());// string转字符串
char*p = strtok(ss, dem);
while (p) {
string s = p;
res.push_back(s);
p = strtok(NULL, dem);
}
return res;
}
int find_c (const string& str, const vector <string>& res) { //查找str 对应表头列的序号
for (int i = ; i < res.size(); i++)
if (str == res[i])
return i;
}
void m_print (const data& t) {
for (int i = ; i <= t.num; i++) {
cout << t.c[i][];
for (int j = ; j < t.c[i].size(); j++)
cout << " " << t.c[i][j];
cout << endl;
}
cout << endl;
}
void creat (const string& s) {
string ta = sub(s, , '(');// 截取表头
int p = s.find('(');
string s1 = sub(s, p + , ')'); // 截取各列信息
mapp[ta] = ++cnt;// 各个表与id对应
h[cnt].col = split(s1);
return ;
}
void inser (const string&s) {
// 表的信息
string ta = sub(s, , '('); // 插入的列表
int p1 = s.find('(');
string s1 = sub(s, p1 + , ')');
vector <string> r1 = split (s1); // 插入的信息
int p2 = s.rfind('(');
string s2 = sub(s, p2 + , ')');
vector <string> r2 = split(s2); int id = mapp[ta]; int len = h[id].col.size()
int k = ++d[id].num;
for (int i = ; i < len; i++) d[id].c[k].push_back(""); for (int i = ; i < r1.size(); i++) {
int t = find_c(r1[i], h[id].col); // 找到要出插入列 在表头列表中的位置
d[id].c[k][t] = r2[i];
}
}
data se1 (const string& s) {// 无递归查询 返回一个集合
data ans; ans.num = ;
// res 查询的列集合
int p1 = s.rfind("from ");
string s1 = s.substr (, p1 - );
vector <string> res = split(s1); string ta = sub (s, p1 + , ';');// 表头
int id = mapp[ta];
ans.num = d[id].num;
ans.id = id; for (int i = ; i <= ans.num; i++)// 每一行
for (int j = ; j < res.size(); j++) {// 每一列
int k = find_c(res[j], h[id].col);
ans.a[j] = k;
ans.c[i].push_back(d[id].c[i][k]);
}
return ans;
}
data se2 (const string&s ) {//递归求解查询2
data ans; ans.num = ;
// 得到前半部分t1集合(先忽略条件)
int p1 = s.find ("where ");
if (p1 == string::npos) return se1(s);
string s1 = s.substr (, p1);
s1[p1 - ] = ';'; data t1 = se1(s1); int p2 = s.find ("in ");
string ss = s.substr(p1 + , p2 - - p1);
int k = find_c (ss, h[t1.id].col);// 得到指定列 //得到条件集合t2
string s2 = s.substr(p2 + );
data t2 = se2(s2); //按条件筛选t1
for (int i = ; i <= t1.num; i++)
for (int j = ; j <= t2.num; j++)
if ( d[t1.id].c[i][k] == t2.c[j][]) {
ans.num++;
ans.c[ans.num] = t1.c[i];
break;
}
return ans;
}
int main ()
{
string s;
while (getline(cin, s)) {
if (s[] == 'c') creat (s);
else if (s[] == 'i') inser(s);
else if (s[] == 's' && s.find(" where ") == string::npos) {
data t = se1(s); m_print(t);
}
else {
data t = se2(s); m_print(t);
}
}
return ;
}
后记:
缺点 :采用STL速度较慢.
优点: 代码简洁易懂
xdoj-1298(模拟--简易SQL解释器)的更多相关文章
- Python模拟简易版淘宝客服机器人
对于用Python制作一个简易版的淘宝客服机器人,大概思路是:首先从数据库中用sql语句获取相关数据信息并将其封装成函数,然后定义机器问答的主体函数,对于问题的识别可以利用正则表达式来进行分析,结合现 ...
- 模拟实现SQL Server字段列显示的数据类型
本文目录列表: 1.SQL Server表设计视图中的数据类型列展示效果 2.模拟实现类似的数据类型显示效果 3.测试效果 4.总结语 5.参考清单列表 1.SQL Server表设计视图中的数据 ...
- 模拟实现SQL Server中的datepart(week,date)的功能
本文目录列表: 1.为什么要模拟实现datepart(week,date)的功能 2.具体实现思路 3.T-SQL代码实现逻辑 4.总结语 5.参考清单列表 1.为什么要模拟实现datepart( ...
- WindowsPhone模拟简易Toast弹出框
Coding4Fun这个开源控件中有ToastPrompt这个弹出框组件,但是由于Coding4Fun太庞大,如果只用到ToastPrompt这个控件的话,整个引用不太值当的.于是自己写了一个差不多的 ...
- java模拟简易按键精灵
很多小伙伴们都有过抢课的经历,有时候抢不到自己想上的课,只能盼望有人退选,可是很多时候别人退选了,但是很快又被别人抢走了,我们不可能时刻盯着电脑, 这时候如果有一个抢课的程序岂不是很棒.. 出于这个目 ...
- 简易SQL语句
/*创建 模式 为用户 User1*/ CREATE SCHEMA test authorization User1; CREATE SCHEMA test USER User1; CREATE TA ...
- linux c++模拟简易网络爬虫
/* * To change this license header, choose License Headers in Project Properties. * To change this t ...
- .NET面试题系列[14] - LINQ to SQL与IQueryable
.NET面试题系列目录 名言警句 "理解IQueryable的最简单方式就是,把它看作一个查询,在执行的时候,将会生成结果序列." - Jon Skeet LINQ to Obje ...
- SQL Server Profiler
一.SQL Profiler工具简介 SQL Profiler是一个图形界面和一组系统存储过程,其作用如下: 图形化监视SQL Server查询: 在后台收集查询信息: 分析性能: 诊断像死锁之类的问 ...
随机推荐
- std::string 的方法c_str() 和 data() 有什么区别
1.从C++标准上的解释来看,只有一点区别: c_str() 返回一个指向正规C字符串的指针常量,该指针保证指向一个 size() + 1 长度的空间,而且最后一个字符肯定是 \0 : 而 data( ...
- mac mysql 操作
参考 http://www.cnblogs.com/chenmo-xpw/p/6102933.html http://www.cnblogs.com/uoar/p/6492521.html 1.启动M ...
- U帮忙U盘装系统工具使用教程
在用U盘装系统时首先我们需要了解一下U帮忙U盘启动盘的制作以及BIOS设置U盘启动和U盘装系统步骤后才能让操作更顺利的完成,下面就来说说U帮忙U盘装系统工具使用教程,希望对大家有所帮助! 如果您不了解 ...
- python之路-python字符编码
编码的发展 py2的字符编码 py3的字符编码 编码的发展: 编码表:编码是信息从一种形式或格式转换为另一种形式的过程也称为计算机编程语言的代码简称编码.编码表记录着我们常见的明文所对应的计算机二进制 ...
- java中JDBC连接数据库操作的基本步骤
JDBC基本步骤 创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.lan ...
- 数据库-->记录操作
一.概览 MySQL数据操作: DML 在MySQL管理软件中,可以通过SQL语句中的DML语言来实现数据的操作,包括 使用INSERT实现数据的插入 UPDATE实现数据的更新 使用DELETE实现 ...
- :状态模式:GumballMachine
#ifndef __STATE_H__ #define __STATE_H__ #include <iostream> #include<stdlib.h> using nam ...
- 自定义String
// ShStringNew.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #inclu ...
- 进程创建过程详解 CreateProcess
转载请您注明出处:http://www.cnblogs.com/lsh123/p/7405796.html 0x01 CreateProcessW CreateProcess的使用有ANSI版本的Cr ...
- VCL界面控件DevExpress VCL Controls发布v18.2.3|附下载
DevExpress VCL Controls是 Devexpress公司旗下最老牌的用户界面套包.所包含的控件有:数据录入,图表,数据分析,导航,布局,网格,日程管理,样式,打印和工作流等,让您快速 ...