好久沒做題了,手速慢得不成樣子了呀,寫這個水題寫了2個小時,好在1A了。。。
沒什麼難度,就是麻煩,注意輸出是居中就對了
#include <cctype>
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
#define MAX_COL 12
#define MAX_ROW 10005
enum Type{
kUnknown = 0,
kStr,
kInt
};
typedef vector<string> Column;
typedef vector<string> Row;
struct RowChecker{
int col;
virtual ~RowChecker(){}
virtual bool check(const Row& row) = 0;
};
struct StrEqualChecker : public RowChecker{
string key;
bool check(const Row& row){
return row[col] == key;
}
};
#define DEFINE_CHECKER(NAME, BINARY_OP) \
struct NAME##Checker : public RowChecker{ \
int key; \
bool check(const Row& row){ \
return atoi(row[col].c_str()) BINARY_OP key; \
} \
};
DEFINE_CHECKER(IntLess, <);
DEFINE_CHECKER(IntEqual, ==);
DEFINE_CHECKER(IntGreater, >);
int C, R, Q;
Column columns;
Type columnTypes[MAX_COL];
Row rows[MAX_ROW];
StrEqualChecker sec;
IntLessChecker ilc;
IntEqualChecker iec;
IntGreaterChecker igc;
void inputTable()
{
cin >> C >> R >> Q;
string type;
columns.resize(C);
for(int i = 0; i < C; ++i){
cin >> columns[i] >> type;
if(type == "STR") columnTypes[i] = kStr;
else if(type == "INT") columnTypes[i] = kInt;
else columnTypes[i] = kUnknown;
}
for(int i = 0; i < R; ++i){
rows[i].resize(C);
for(int j = 0; j < C; ++j){
cin >> rows[i][j];
}
}
}
string chomp(string& src, const string& delim)
{
size_t i = src.find(delim);
string res;
if(i == string::npos){
res.swap(src);
}
else{
res = src.substr(0, i);
src.erase(0, i + delim.size());
}
return res;
}
string trim(const string& s)
{
size_t i = 0, n = s.size(), j = n-1;
for(; i < n; ++i){
if(!isspace(s[i])) break;
}
for(; j >= i; --j){
if(!isspace(s[j])) break;
}
if(i <= j) return s.substr(i, j-i+1);
return "";
}
void parseQuery(const string& query, vector<string>& targetColumns, string& condition)
{
size_t i = query.find("select");
size_t j = query.find("where");
//find target columns
string names = trim(query.substr(i + 6, j - (i + 6)));
while(!names.empty()) targetColumns.push_back(chomp(names, ","));
//find condition
condition = trim(query.substr(j + 5));
}
void select(const string& query, vector<int>& resultColIds, vector<int>& resultRowIds)
{
resultColIds.clear();
resultRowIds.clear();
//parse query string
string condition;
vector<string> targetColumns;
parseQuery(query, targetColumns, condition);
/*
cout << "target columns:\n";
for(int i = 0; i < targetColumns.size(); ++i) cout << targetColumns[i] << " ";
cout << endl;
*/
//figure out target column ids
int i, j;
for(i = 0; i < targetColumns.size(); ++i){
for(j = 0; j < C; ++j){
if(targetColumns[i] == columns[j]){
resultColIds.push_back(j);
break;
}
}
if(j >= C) return;
}
/*
cout << "result column ids:\n";
for(int i = 0; i < resultColIds.size(); ++i) cout << resultColIds[i] << " ";
cout << endl;
*/
//find condition column
size_t op = condition.find_first_of("<=>");
string conditionColumnName = trim(condition.substr(0, op));
int conditionColumn = 0;
for(; conditionColumn < C; ++conditionColumn){
if(columns[conditionColumn] == conditionColumnName) break;
}
if(conditionColumn >= C) return;
//check if column has same type as key
string compareKey = trim(condition.substr(op+1));
Type keyType;
RowChecker* prc = NULL;
if(compareKey[0] == '"'){
keyType = kStr;
sec.key = compareKey.substr(1, compareKey.size() - 2);
if(condition[op] != '=') return;
prc = &sec;
}
else{
keyType = kInt;
switch(condition[op]){
case '=': iec.key = atoi(compareKey.c_str()); prc = &iec; break;
case '<': ilc.key = atoi(compareKey.c_str()); prc = &ilc; break;
case '>': igc.key = atoi(compareKey.c_str()); prc = &igc; break;
}
}
if(keyType != columnTypes[conditionColumn] || !prc) return;
//use the checker to filter rows
prc->col = conditionColumn;
for(int i = 0; i < R; ++i){
if(prc->check(rows[i])) resultRowIds.push_back(i);
}
/*
cout << "result row ids:\n";
for(int i = 0; i < resultRowIds.size(); ++i) cout << resultRowIds[i] << " ";
cout << endl;
*/
}
void figureColumnSize(vector<size_t>& colSizes, const vector<int>& colIds, const vector<int>& rowIds)
{
colSizes.resize(colIds.size());
int i, j, rid, cid;
for(i = 0; i < colIds.size(); ++i){
cid = colIds[i];
colSizes[i] = columns[cid].size() + 2;
}
for(i = 0; i < rowIds.size(); ++i){
rid = rowIds[i];
for(j = 0; j < colIds.size(); ++j){
cid = colIds[j];
colSizes[j] = max(colSizes[j], rows[rid][cid].size() + 2);
}
}
/*
for(i = 0; i < colSizes.size(); ++i){
cout << "column " << i << " occupies " << colSizes[i] << " spaces\n";
}
*/
}
void printRow(const Row& row, const vector<int>& colIds, const vector<size_t>& colSizes)
{
for(int i = 0; i < colIds.size(); ++i){
int cid = colIds[i];
size_t size = colSizes[i];
cout << "|";
//figure padding spaces
size_t lhs = (size - row[cid].size()) >> 1;
size_t rhs = size - row[cid].size() - lhs;
while(lhs--) cout << " ";
cout << row[cid];
while(rhs--) cout << " ";
}
cout << "|\n";
}
void showResult(const vector<int>& resultColIds, const vector<int>& resultRowIds)
{
//figure out each output column's size
vector<size_t> colSizes;
figureColumnSize(colSizes, resultColIds, resultRowIds);
//output header
int m = resultColIds.size(), n = resultRowIds.size();
int HR = accumulate(colSizes.begin(), colSizes.end(), 0) + m - 1;
cout << "+";
for(int i = 0; i < HR; ++i) cout << "-";
cout << "+\n";
//print column label
printRow(columns, resultColIds, colSizes);
//print separator line
for(int i = 0; i < m; ++i){
cout << "|";
for(int k = colSizes[i]; k--; ) cout << "-";
}
cout << "|\n";
//print each row
for(int i = 0; i < n; ++i){
int rid = resultRowIds[i];
printRow(rows[rid], resultColIds, colSizes);
}
//output footer
cout << "+";
for(int i = 0; i < HR; ++i) cout << "-";
cout << "+\n";
}
int main()
{
ios::sync_with_stdio(false);
inputTable();
while(cin.get() != '\n') ;
string query;
vector<int> resultColIds, resultRowIds;
while(Q--){
getline(cin, query);
select(query, resultColIds, resultRowIds);
showResult(resultColIds, resultRowIds);
cout << "\n";
}
return 0;
}