POJ-3699(模擬SQL查詢)

好久沒做題了,手速慢得不成樣子了呀,寫這個水題寫了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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章