一 知识点:
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速度较慢.
优点: 代码简洁易懂