天天看點

程式設計能力強化(4)——模拟SQL語句解析

這是2010年軟體大賽的樣題,用到的知識點比較多,也比較實用。

題目:

資料庫中有“表”的概念。“表”由若幹“行”組成,每“行”由許多“列”組成。一般的資料庫都提供了對sql的支援。

我們可以模拟一個最簡單版的sql,隻能實作簡單的排序,簡單的選擇條件,列的顯示順序等功能。

具體如下:

(1)輸入help,會輸出幫助資訊

(2)輸入load data.txt,會輸出檔案中的内容

(3)輸入sort weight,會根據重量排序,然後輸出,也可以根據其他幾個屬性排序,每次指定一個

(4)輸入select *,顯示所有的資料

(5)輸入select name,顯示某一列,如果要顯示多列,多列之間使用空格隔開

(6)輸入select * where price>50,條件隻能使用大于或者小于,單個條件不用空格,多個條件之間使用空格隔開

(7)輸入exit,程式退出

自己看看能不能做出來,如果做不出來,看看後面的參考答案。

資料檔案(data.txt)内容如下:

名稱 長度 重量 威力 價格

a 25.1 12.3 24.6 105.3

b 180.5 11.6 41.2 36.5

c 103.6 33.1 28.4 78

d 21.5 18.6 17.6 38.5

e 33.6 28.5 11.9 27.0

f 31.6 19.8 23.5 36.3

g 88.3 17.9 16.4 22.9

下面是參考答案:

import java.io.*;  

import java.util.*;  

// 代表每行資料  

class myrow  

{  

    private string name;    // 名字  

    private double length;  // 長度  

    private double weight;  // 重量  

    private double power;   // 威力  

    private double price;   // 價格  

    public myrow(string x)  

    {  

        string[] ss = x.split("/t");  

        name = ss[0].trim();  

        length = double.parsedouble(ss[1]);  

        weight = double.parsedouble(ss[2]);  

        power = double.parsedouble(ss[3]);  

        price = double.parsedouble(ss[4]);  

    }  

    public string tostring()  

        return name + "/t" + length + "/t" + weight + "/t" + power + "/t" + price;  

    public string getname() { return name; }  

    public double getlength() { return length; }  

    public double getweight() { return weight; }  

    public double getpower() { return power; }  

    public double getprice() { return price; }  

}  

// 代表所有資料  

class mydata  

    // 内部類,“裁判”類,用于裁決vector中的對象的比較大小問題    

    class caipan implements comparator  

        private int type;  

        public caipan(int type)  

        {  

            this.type = type;  

        }  

        public int compare(object o1, object o2)      

            if(!(o1 instanceof myrow)) return 0;  

            if(!(o2 instanceof myrow)) return 0;  

            myrow r1 = (myrow)o1;  

            myrow r2 = (myrow)o2;  

            switch(type){  

            case 1:  

                return double.compare(r1.getlength(),r2.getlength());  

            case 2:  

                return double.compare(r1.getweight(),r2.getweight());  

            case 3:  

                return double.compare(r1.getpower(),r2.getpower());  

            case 4:  

                return double.compare(r1.getprice(),r2.getprice());  

            default:  

                return 0;  

            }  

    private vector _v = new vector();  

    public void show()  

        system.out.println("................................");  

        system.out.println("名稱/t長度/t重量/t威力/t價格");  

        for(int i=0; i<_v.size(); i++){  

            system.out.println(_v.get(i));  

    public boolean load(string x)  

        try{  

            bufferedreader br = new bufferedreader(new inputstreamreader(new fileinputstream(x)));  

            _v.clear();  

            br.readline();  // 第一行不要  

            for(;;){  

                string s = br.readline();  

                if(s==null) break;  

                myrow row = new myrow(s);  

                _v.add(row);  

            }         

            show();  

            return true;      

        catch(exception e){  

            //e.printstacktrace();  

            return false;  

    public boolean sort(string x)  

        if(x.equals("length")){  

            collections.sort(_v, new caipan(1));  

            return true;  

        if(x.equals("weight")){  

            collections.sort(_v, new caipan(2));  

        if(x.equals("power")){  

            collections.sort(_v, new caipan(3));  

        if(x.equals("price")){  

            collections.sort(_v, new caipan(4));  

        return false;  

    // 初步解析指令  

    public boolean select(string x)  

        vector sort = new vector();  // 顯示的字段  

        vector where = new vector();  // 過濾的條件語句  

        string[] ss = x.split(" ");  

        vector t = sort;  

        for(int i=0; i<ss.length; i++){  

            if(ss[i].length()==0) continue;  // 防止多個空格  

            if(ss[i].equals("where")){  

                t = where;  

                continue;  

            t.add(ss[i]);  

        if(sort.size()==0) return false;  // 字段必須指定  

        if(sort.size()>5) return false;  // 字段太多  

        return select(sort, where);   

    }     

    // 執行select任務  

    public boolean select(list sort, list where)  

    try{  

        //輸出标題  

        for(int k=0; k<sort.size(); k++){  

            if(sort.get(k).equals("name"))  

                system.out.print("姓名/t");  

            else if(sort.get(k).equals("length"))  

                system.out.print("長度/t");  

            else if(sort.get(k).equals("weight"))  

                system.out.print("重量/t");  

            else if(sort.get(k).equals("power"))  

                system.out.print("威力/t");  

            else if(sort.get(k).equals("price"))  

                system.out.print("價格/t");  

            else if(sort.get(k).equals("*"))  

                system.out.print("名稱/t長度/t重量/t威力/t價格/t");  

            else  

                return false;  

        }// 枚舉sort  

        system.out.println("");  

        //輸出内容  

            myrow row = (myrow)_v.get(i);  

            if(checkwhere(row, where)){  

                for(int k=0; k<sort.size(); k++){  

                    if(sort.get(k).equals("name"))  

                        system.out.print(row.getname() + "/t");  

                    else if(sort.get(k).equals("length"))  

                        system.out.print(row.getlength() + "/t");  

                    else if(sort.get(k).equals("weight"))  

                    else if(sort.get(k).equals("power"))  

                    else if(sort.get(k).equals("price"))  

                    else if(sort.get(k).equals("*"))  

                        system.out.print(row + "/t");  

                    else  

                        return false;  

                }// 枚舉sort  

                system.out.println("");  

            }//檢查過濾條件     

        }//對每個行處理  

        return true;  

    catch(exception e){  

        //e.printstacktrace();  

    // 傳回true 則該行記錄顯示,傳回false,則不顯示  

    public boolean checkwhere(myrow row, list where) throws exception  

        boolean op=true;  // true: 表示比較符号為 > , 否則為 <  

        string field = "";  // 過濾條件的字段  

        string value = "";  // 過濾值  

        // 對每一個條件處理   

        for(int i=0; i<where.size(); i++){  

            string s = (string)where.get(i);  

            string[] ss = s.split(">");  

            if(ss.length==2){  

                field = ss[0];  

                op = true;  

                value = ss[1];  

            else{  

                ss = s.split("<");  

                if(ss.length==2){  

                    field = ss[0];  

                    op = false;  

                    value = ss[1];  

                }  

                else  

                    return false;  // 既沒有"<"也沒有">"的情況  

            double d_value = double.parsedouble(value);  

            if(field.equals("length")){  

                if(op){  

                    if(row.getlength() <= d_value)   return false;  

                }         

                else{  

                    if(row.getlength() >= d_value) return false;  

            else if(field.equals("weight")){  

                    if(row.getweight() <= d_value) return false;  

                    if(row.getweight() >= d_value) return false;  

            else if(field.equals("power")){  

                    if(row.getpower() <= d_value) return false;  

                    if(row.getpower() >= d_value) return false;  

            else if(field.equals("price")){  

                    if(row.getprice() <= d_value) return false;  

                    if(row.getprice() >= d_value) return false;  

                throw new exception("valid field name!");  // 無法識别的 field,則算錯表達式錯  

// 負責解釋使用者輸入的指令  

class mycommand  

    private mydata data;  

    public mycommand(mydata x)  

        data = x;  

    public boolean execute(string x)  

        int d = x.indexof(" ");  // 找第一個空格的位置  

        if(d<0) return false;  

        string x1 = x.substring(0,d);    

        string x2 = x.substring(d+1);    

        if(x1.equals("load")){  

            if(!data.load(x2.trim()))  

                system.out.println("裝入檔案出錯!");  

        if(x1.equals("sort"))  

            return data.sort(x2.trim());  

        if(x1.equals("select"))  

            return data.select(x2);  

public class my  

    private static bufferedreader br_keyboard;    

    static  

        br_keyboard = new bufferedreader(new inputstreamreader(system.in));  // 将它用于從鍵盤讀入  

    public static void main(string[] args) throws exception  

        mydata data = new mydata();  

        mycommand cmd = new mycommand(data);  // cmd 服務于 data  

        for(;;){  

            system.out.print("請輸入指令(輸入help顯示幫助資訊):");  

            string s = br_keyboard.readline();  

            if(s.equals("exit")) break;  

            if(s.equals("help")){  

                system.out.println("----------------------------");  

                system.out.println("load data.txt");  

                system.out.println("從目前目錄裝入檔案data.txt,并顯示");  

                system.out.println("sort weight");  

                system.out.println("按“重量”排序,并顯示");  

                system.out.println("類似地,還可以是 sort length, sort price,sort power等");  

                system.out.println("select weight length");  

                system.out.println("隻顯示 重量,長度兩列");  

                system.out.println("select weight length where price > 50");  

                system.out.println("隻顯示 重量,長度兩列, 隻包含價格 > 50 的行");  

                system.out.println("select * where price>50 length<30");  

                system.out.println("顯示所有列, 隻包含價格>50 且 長度<30 的行");  

                system.out.println("其它的組合,從上邊類推");  

                system.out.println("exit");  

                system.out.println("退出程式");  

            if(!cmd.execute(s)){  

                system.out.println("無效的指令");