列表

详情


NC14116. Simple Database

描述

小Q同学受SQL启发,设计了更为简单更易上手的QAQL,该语言拥有如下语法:
 
1.创建表:
CREATE 表名称 (列名称1, 列名称2, 列名称3, ...)
该语句创建了一个表。保证语句中至少有一个列名称,至多有十个列名称,且表中的列名称互不相同。
例如:
CREATE person (name, age, gender)
该语句创建了一个如下所示的数据表:
person表

 
 
 
 
请注意,QAQL中所有数据均为字符串类型,判断数据相等时要求全字符匹配。
 
2.删除表:
DROP 表名称
该语句删除了一个表。
例如:
DROP person
该语句删除了表名称为person的表。
 
3.插入数据:
INSERT 表名称 ("值1", "值2", "值3", ...)
该语句向表尾插入一行数据,并且每个INSERT语句只插入一行数据,数据值要由引号引起。保证语句中至少有一个值,至多有十个值,如果表存在,保证值的数量等于表中列的数量。
例如:
INSERT person ("quailty", "20", "male")
该语句向person表尾中插入一行name="quailty",age="20",gender="male"的数据,
 
4.删除数据:
DELETE 表名称 WHERE 列名称1 = "值1", 列名称2 = "值2", ...
该语句删除表中满足条件的数据行,其中WHERE语句表示对表中所有满足条件的数据行进行操作,如省略,则对表中所有数据行进行操作。
例如:
DELETE person WHERE name = "quailty"
该语句删除person表中所有满足name="quailty"的数据行。
 
5.修改数据:
UPDATE 表名称 SET 列名称1 = "新值1", 列名称2 = "新值2", ... WHERE 列名称1 = "值1", 列名称2 = "值2", ...
该语句修改表中满足条件的数据行的指定列的值。保证进行修改的列不少于一个,不多于十个,且这些列的列名称互不相同。
例如:
UPDATE person SET name = "fzirsqh" WHERE age = "20", gender = "male"
该语句将person表中所有满足age="20"且gender="male"的数据行的"name"列改为"fzirsqh"。
 
6.查询数据:
SELECT 表名称 WHERE 列名称1 = "值1", 列名称2 = "值2", ...
该语句查询表中所有满足条件的数据行。
例如:
SELECT person WHERE age = "20"
该语句查询person表中所有满足age="20"的数据行。
 
对于所有语句,如果使用WHERE子句增加限制条件,保证条件不少于一个,不多于十个,且这些条件的列名称互不相同。
 
现在你需要解析QAQL语句,并响应QAQL的操作,SELECT语句的查询结果按照给定格式输出,其他语句执行后无需任何输出。
保证语句严格符合上述语法,所有语句中的表名称、列名称、数据值均为长度不超过10的只包含英文字母、数字和下划线的非空字符串。但不保证逻辑合法,如果操作不合法,即创建的数据表已经存在,或者删除的数据表不存在,或者插入、删除、修改、查询的数据表名称或列名称不存在(无论表是否为空),则输出"error"(不含引号),并忽略该条语句,但如果查询结果为空(即没有满足条件的数据),则只需按照给定格式输出表中的列名称。
查询结果的输出格式如下:
第一行为查询的数据表的列名称,用一个空格隔开,
接下来若干行,按照数据表中的顺序,输出所有满足条件的数据行,用空格隔开每一列的值,一个数据行输出一行。

输入描述

第一行是一个正整数T(≤ 10),表示测试数据的组数,
对于每组测试数据,
第一行是一个整数n(0 ≤ n ≤ 1000),表示操作语句的数量,
接下来n行,每行是一个字符串,表示操作语句。
请注意操作语句中空格位置及数量,保证操作语句严格符合语法。

输出描述

对于第k组测试数据,先输出一行"Case #k:"(不含引号),
对于每个查询语句,按照给定的输出格式输出查询结果,
对于每个不合法操作,输出一行"error"(不含引号)。
保证输出文件大小不超过10MB。

示例1

输入:

1
10
CREATE person (name)
DROP person
CREATE person (name, age, gender)
INSERT person ("quailty", "20", "male")
SELECT person WHERE age = "20"
UPDATE person SET name = "fzirsqh" WHERE age = "20", gender = "male"
SELECT person WHERE name = "quailty"
DELETE person
SELECT person WHERE rating = "2323"
DROP person

输出:

Case #1:
name age gender
quailty 20 male
name age gender
error

说明:

敢写敢过。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 244ms, 内存消耗: 10160K, 提交时间: 2019-01-07 12:09:21

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<list>
#include<queue>
#include<map>

using namespace std;

bool IsValidChar(char x)
{
    if(x>='A' && x<='Z')return 1;
    if(x>='a' && x<='z')return 1;
    if(x>='0' && x<='9')return 1;
    return x=='_';
}

const string command[7]=
{
    "","CREATE","DROP","INSERT","DELETE","UPDATE","SELECT"
};

map<string,int>keyOfTable;
struct Table
{
    static int capacity;
    string name;
    map<string,int>keyOfList;
    vector<list<string> >value;
};
int Table::capacity=0;
vector<Table>database;
queue<int>recycle;

struct Analyser
{
    int type;
    string table_name;
    vector<string>list_name;
    vector<pair<string,string> >target;
    vector<pair<string,string> >limit;
    Analyser(){}
    Analyser(string sentence)
    {
        stringstream stream(sentence);
        string word;
        stream>>word;
        for(int i=1;i<=6;i++)
            if(word==command[i])type=i;
        stream>>table_name;
        switch(type)
        {
        case 1:
        case 3:
            {
                while(stream>>word)
                {
                    int l=0,r=(int)word.size()-1;
                    while(!IsValidChar(word[l]))l++;
                    while(!IsValidChar(word[r]))r--;
                    list_name.push_back(word.substr(l,r-l+1));
                }
                break;
            }
        case 4:
        case 5:
        case 6:
            {
                bool isLimit=0,isValue=0;
                string key,value;
                while(stream>>word)
                {
                    if(word=="WHERE")
                    {
                        isLimit=1;
                        continue;
                    }
                    if(word=="SET" || word=="=")continue;
                    int l=0,r=(int)word.size()-1;
                    while(!IsValidChar(word[l]))l++;
                    while(!IsValidChar(word[r]))r--;
                    if(!isValue)
                    {
                        key=word.substr(l,r-l+1);
                        isValue=1;
                    }
                    else
                    {
                        value=word.substr(l,r-l+1);
                        if(!isLimit)target.push_back(make_pair(key,value));
                        else limit.push_back(make_pair(key,value));
                        isValue=0;
                    }
                }
            }
            break;
        default:
            break;
        }
    }
};

void Create(Analyser &working)
{
    int id=0;
    if(recycle.empty())id=Table::capacity++,database.push_back(Table());
    else id=recycle.front(),recycle.pop();
    keyOfTable[working.table_name]=id;
    database[id]=Table();
    database[id].name=working.table_name;
    for(int i=0;i<(int)working.list_name.size();i++)
        database[id].keyOfList[working.list_name[i]]=i;
    database[id].value.resize((int)working.list_name.size());
    for(int i=0;i<(int)working.list_name.size();i++)
        database[id].value[i].push_back(working.list_name[i]);
}

void Drop(Analyser &working)
{
    int id=keyOfTable[working.table_name];
    recycle.push(id);
    keyOfTable.erase(working.table_name);
}

void Insert(Analyser &working)
{
    int id=keyOfTable[working.table_name];
    for(int i=0;i<(int)working.list_name.size();i++)
        database[id].value[i].push_back(working.list_name[i]);
}

void Others(Analyser &working)
{
    int id=keyOfTable[working.table_name];
    for(int i=0;i<(int)working.target.size();i++)
        if(database[id].keyOfList.find(working.target[i].first)==database[id].keyOfList.end())
        {
            cout<<"error"<<endl;
            return;
        }
    for(int i=0;i<(int)working.limit.size();i++)
        if(database[id].keyOfList.find(working.limit[i].first)==database[id].keyOfList.end())
        {
            cout<<"error"<<endl;
            return;
        }
    list<string>::iterator *itr=new list<string>::iterator[(int)database[id].value.size()];
    for(int i=0;i<(int)database[id].value.size();i++)
    {
        itr[i]=database[id].value[i].begin();
        if(working.type==6)
        {
            if(i>0)cout<<" ";
            cout<<*itr[i];
            if(i==(int)database[id].value.size()-1)cout<<endl;
        }
        itr[i]++;
    }
    while(itr[0]!=database[id].value[0].end())
    {
        bool isMatch=1;
        for(int i=0;i<(int)working.limit.size();i++)
            if(*itr[database[id].keyOfList[working.limit[i].first]]!=working.limit[i].second)
                isMatch=0;
        if(isMatch && working.type==5)
            for(int i=0;i<(int)working.target.size();i++)
                *itr[database[id].keyOfList[working.target[i].first]]=working.target[i].second;
        for(int i=0;i<(int)database[id].value.size();i++)
        {
            if(isMatch)
            {
                switch(working.type)
                {
                case 4:
                    database[id].value[i].erase(itr[i]++);
                    break;
                case 6:
                    if(i>0)cout<<" ";
                    cout<<*itr[i]++;
                    if(i==(int)database[id].value.size()-1)cout<<endl;
                    break;
                default:
                    itr[i]++;
                    break;
                }
            }
            else itr[i]++;
        }
    }
    delete[] itr;
}

void Init()
{
    Table::capacity=0;
    keyOfTable.clear();
    database.clear();
    while(!recycle.empty())recycle.pop();
}

void Process()
{
    Init();
    int n;
    cin>>n;
    string sentence;
    getline(cin,sentence);
    while(n--)
    {
        getline(cin,sentence);
        Analyser working(sentence);
        if((working.type==1 && keyOfTable.find(working.table_name)!=keyOfTable.end())
           ||(working.type>1 && keyOfTable.find(working.table_name)==keyOfTable.end()))
        {
            cout<<"error"<<endl;
            continue;
        }
        switch(working.type)
        {
        case 1:
            Create(working);
            break;
        case 2:
            Drop(working);
            break;
        case 3:
            Insert(working);
            break;
        case 4:
        case 5:
        case 6:
            Others(working);
            break;
        default:
            break;
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    int T;
    cin>>T;
    for(int i=1;i<=T;i++)
    {
        cout<<"Case #"<<i<<":"<<endl;
        Process();
    }
    return 0;
}

上一题