您的位置:首页 > 数据库

编程能力强化(4)——模拟SQL语句解析

2011-03-22 10:41 239 查看
这是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));
		}
		System.out.println("................................");
	}
	
	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));
			show();
			return true;
		}
		if(x.equals("weight")){
			Collections.sort(_v, new CaiPan(2));
			show();
			return true;
		}
		if(x.equals("power")){
			Collections.sort(_v, new CaiPan(3));
			show();
			return true;
		}
		if(x.equals("price")){
			Collections.sort(_v, new CaiPan(4));
			show();
			return true;
		}
		
		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{
		System.out.println("................................");
		//输出标题
		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("");
		
		
		//输出内容
		for(int i=0; i<_v.size(); i++){
			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"))
						System.out.print(row.getLength() + "/t");
					else if(sort.get(k).equals("power"))
						System.out.print(row.getLength() + "/t");
					else if(sort.get(k).equals("price"))
						System.out.print(row.getLength() + "/t");
					else if(sort.get(k).equals("*"))
						System.out.print(row + "/t");
					else
						return false;
				}// 枚举sort
				System.out.println("");
			}//检查过滤条件	
		}//对每个行处理
		
		System.out.println("................................");
		return true;
	}
	catch(Exception e){
		//e.printStackTrace();
		return false;
	}
	}
	
	
	// 返回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(op){
					if(row.getWeight() <= d_value) return false;
				}
				else{
					if(row.getWeight() >= d_value) return false;
				}
			}
			else if(field.equals("power")){
				if(op){
					if(row.getPower() <= d_value) return false;
				}
				else{
					if(row.getPower() >= d_value) return false;
				}
			}
			else if(field.equals("price")){
				if(op){
					if(row.getPrice() <= d_value) return false;
				}
				else{
					if(row.getPrice() >= d_value) return false;
				}
			}
			else
				throw new Exception("valid field name!");  // 无法识别的 field,则算错表达式错
		}
		
		return true;
	}
}

// 负责解释用户输入的命令
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("装入文件出错!");
			return true;
		}
			
		if(x1.equals("sort"))
			return data.sort(x2.trim());
		
		if(x1.equals("select"))
			return data.select(x2);
		
		return false;
	}
}

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("退出程序");
				System.out.println("----------------------------");
				continue;
			}
			
			if(!cmd.execute(s)){
				System.out.println("无效的命令");
			}
		}
		
	}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: