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() + 1];
  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 对于复合查询采用递归方式的查询

三 代码

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 struct head {
  4   vector <string> col;
  5 };
  6 head h[10]; int cnt = 0;
  7 map <string, int> mapp;
  8 struct data {
  9   int id;// 对应的表头
 10   int num; // 有多少行 
 11   vector <string> c [100];  //存储每行的信息
 12   int a[10];  // 存储每行各元素所对应的列
 13 };
 14 data d[10];
 15 const char* dem = ", ";
 16 string sub (const string& str, int p, char last) {// 截取从p位置到以last结尾的字符串(不包括last)
 17   int p2 = str.find(last, p);// 从p位置开始查找last
 18   return str.substr(p, p2 - p);// 从p位置开始长度为(p2-p)的字符串
 19 }
 20 vector <string> split (const string & str) {// 将以dem为分隔的字符串分割
 21   vector <string> res;
 22   char *ss = new char[str.size() + 1];
 23   strcpy (ss, str.c_str());// string转字符串
 24   char*p = strtok(ss, dem);
 25   while (p) {
 26     string s = p;
 27     res.push_back(s);
 28     p = strtok(NULL, dem);
 29   }
 30   return res;
 31 }
 32 int find_c (const string& str, const vector <string>& res) {  //查找str 对应表头列的序号
 33   for (int i = 0; i < res.size(); i++)
 34     if (str == res[i])
 35       return i;
 36 }
 37 void m_print (const data& t) {
 38   for (int i = 1; i <= t.num; i++) {
 39     cout << t.c[i][0];
 40     for (int j = 1; j < t.c[i].size(); j++)
 41       cout << " " << t.c[i][j];
 42     cout << endl;  
 43   }
 44   cout << endl;
 45 }
 46 void creat (const string& s) {
 47   string ta = sub(s, 13, '(');// 截取表头
 48   int p = s.find('(');
 49   string s1 = sub(s, p + 1, ')'); // 截取各列信息
 50   mapp[ta] = ++cnt;// 各个表与id对应
 51   h[cnt].col = split(s1);
 52   return ;
 53 }
 54 void inser (const string&s) {
 55   // 表的信息
 56   string ta = sub(s, 12, '(');
 57 
 58   // 插入的列表
 59   int p1 = s.find('(');
 60   string s1 = sub(s, p1 + 1, ')');
 61   vector <string> r1 = split (s1);
 62 
 63    // 插入的信息
 64   int p2 = s.rfind('(');
 65   string s2 = sub(s, p2 + 1, ')');
 66   vector <string> r2 = split(s2);
 67 
 68   int id = mapp[ta]; int len = h[id].col.size()
 69   int k = ++d[id].num;
 70   for (int i = 0; i < len; i++) d[id].c[k].push_back("0");
 71 
 72   for (int i = 0; i < r1.size(); i++) { 
 73     int t = find_c(r1[i], h[id].col); // 找到要出插入列 在表头列表中的位置
 74     d[id].c[k][t] = r2[i];
 75   }
 76 }
 77 data se1 (const string& s) {// 无递归查询 返回一个集合
 78   data ans; ans.num = 0;
 79   // res 查询的列集合
 80   int p1 = s.rfind("from ");
 81   string s1 = s.substr (7, p1 - 8);
 82   vector <string> res = split(s1);
 83 
 84   string ta = sub (s, p1 + 5, ';');// 表头
 85   int id = mapp[ta];
 86   ans.num = d[id].num;
 87   ans.id = id;
 88 
 89   for (int i = 1; i <= ans.num; i++)// 每一行
 90     for (int j = 0; j < res.size(); j++) {// 每一列
 91       int k = find_c(res[j], h[id].col);
 92       ans.a[j] = k;
 93       ans.c[i].push_back(d[id].c[i][k]);
 94     }
 95   return ans;
 96 }
 97 data se2 (const string&s ) {//递归求解查询2
 98   data ans; ans.num = 0;
 99   // 得到前半部分t1集合(先忽略条件)
100   int p1 = s.find ("where ");
101   if (p1 == string::npos) return se1(s);
102   string s1 = s.substr (0, p1);
103   s1[p1 - 1] = ';';  data t1 = se1(s1);
104 
105   int p2 = s.find ("in ");
106   string ss = s.substr(p1 + 6, p2 - 7 - p1);
107   int k = find_c (ss, h[t1.id].col);// 得到指定列
108 
109   //得到条件集合t2
110   string s2 = s.substr(p2 + 3);
111   data t2 = se2(s2);
112 
113   //按条件筛选t1
114   for (int i = 1; i <= t1.num; i++)
115     for (int j = 1; j <= t2.num; j++)
116       if (   d[t1.id].c[i][k]  == t2.c[j][0]) {
117         ans.num++;
118         ans.c[ans.num] = t1.c[i];
119         break;
120       }
121   return ans;
122 }
123 int main ()
124 {
125   string s;
126   while (getline(cin, s)) {
127     if (s[0] == 'c')  creat (s);
128     else if (s[0] == 'i') inser(s);
129     else if (s[0] == 's' && s.find(" where ") == string::npos) {
130       data t = se1(s);  m_print(t);
131     }
132     else  {
133       data t = se2(s); m_print(t);
134     }
135   }
136   return 0;
137 }

后记:

  缺点 :采用STL速度较慢.

  优点: 代码简洁易懂

   

抓住青春的尾巴。。。
原文地址:https://www.cnblogs.com/xidian-mao/p/9597088.html