网络版计算器的实现及中缀转后缀

       首先说一下,我这个网络版计算器要实现的效果,首先,我们由客户端输入要计算的公式,然后传递给服务器,进行计算,然后再返回给客户端计算结果。

     首先会讲解一下我的代码大致的实现过程,然后会说一下中缀表达式转后缀表达式,最后附上代码。

    第一步我们创建服务端,首先是创建ServerSocket对象,指定端口号,然后调用accept方法,等待客户机的接收,这里的话accept方法是阻塞式的,所谓的阻塞式就是说,accept方法它在等待客户机连接,如果没有客户机连接上来的话,那么他会一直在哪儿处于等待的状态,程序不会往下执行,然后创建一个字节输入流,读取由客户端发送过来的字符串。这里是部分代码。

ServerSocket ss = null;
		Socket s = null;
		InputStream ips = null;
		DataInputStream dis = null;
		OutputStream ops = null;
		DataOutputStream dps = null;
		
		try {
			ss = new ServerSocket(6666);
			while(true){
				s = ss.accept();
				System.out.println("a client connect");
				
				ips = s.getInputStream();
				dis = new DataInputStream(ips);
				String s2 = dis.readUTF();
				
				ops = s.getOutputStream();
				dps = new DataOutputStream(ops);
				try{
					Long result = countAll_1(s2);
					if(result == 0 && folmatFlag == true){
						dps.writeUTF("您输入的格式有误");
						dps.flush();
					}else if(result == 0 && Doubleflag1 == true){
						Double r = countAll_2(s2);
						dps.writeUTF(r.toString());
						dps.flush();
					}else{	
					dps.writeUTF(result.toString());
					dps.flush();
					}
				}catch(ArithmeticException ae){
					ae.printStackTrace();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				ss.close();
				s.close();
				ips.close();
				dis.close();
				ops.close();
				dps.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}

然后我们调用了一个方法,countAll(s2), 这里的这个方法就是我们将接收的字符串传递给这个方法,然后转换成数字进行计算,

代码如下:

public static long countAll_1(String s){
		Stack<Character> ms = new Stack<>();
		String[] s1 = new String[30];
		int p1 = 0;
		int p2 = -1;
		int j = 0;
		//1, 转为后缀表达式
		for(int i = 0; i < s.length(); i++){
			
			if(s.charAt(i) == '.'){
				Doubleflag1  = true;
				return (long)0;
			}
			if(decide(s.charAt(i))){
				s1[j] = s.substring(p2+1, p1);
				p2 = p1;
				j++;
				if(ms.isEmpty()){
					ms.push(s.charAt(i));
				}else if(ms.peek() == '('){
					ms.push(s.charAt(i));
				}else if(s.charAt(i) == ')'){
					if(ms.peek() != '('){
					s1[j] = ms.pop().toString();
					j++;
					}
					ms.pop();
				}else if((s.charAt(i) == '+' || s.charAt(i) == '-') && (ms.peek() == '*' || ms.peek() == '/')){
					while(!ms.isEmpty()){
						s1[j] = ms.pop().toString();
						j++;
					}
					ms.push(s.charAt(i));
					
				}else if((s.charAt(i) == '*' || s.charAt(i) == '/') && (ms.peek() == '+' || ms.peek() == '-')){
					ms.push(s.charAt(i));
				}else{
					ms.push(s.charAt(i));
				}
				p1++;
			}else if(decideNum(s.charAt(i))){
				p1++;
			}else{
				folmatFlag = true;
				return (long)0;
			}
			
		}
		s1[j] = s.substring(s.length() - 1);
		j++;
		while(!ms.isEmpty()){
			s1[j] = ms.pop().toString();
			j++;
		}
		//2,计算
		Long l = (long) 0;
		Stack<String> ms2 = new Stack<>();
		for(int i = 0; i < j; i++){
			if(s1[i].equals("+")){
				if(ms2.isEmpty())break;		
				l = Long.valueOf(ms2.pop()) + Long.valueOf(ms2.pop());
				ms2.push(l.toString());
			}else if(s1[i].equals("-")){
				Long t1 = Long.valueOf(ms2.pop());
				Long t2 = Long.valueOf(ms2.pop());
				l = t2-t1;
				ms2.push(l.toString());
			}else if(s1[i].equals("*")){
				l = Long.valueOf(ms2.pop()) * Long.valueOf(ms2.pop());
				ms2.push(l.toString());
			}else if(s1[i].equals("/")){
				Long t3 = Long.valueOf(ms2.pop());
				Long t4 = Long.valueOf(ms2.pop());
				l = t4/t3;
				ms2.push(l.toString());
			}else if(s1[i].equals("")){
				;
			}else{
				ms2.push(s1[i]);
			}
		}
		return Long.valueOf(ms2.pop());
	}

可以大致分为两步理解,因为在我们一般生活中都是用的中缀表达式,1,转后缀,2, 计算。

那么中缀表达式时如何转后缀表达式: 

 那么转成后缀过后,就再用一个栈,是数字就进栈,是符号就将栈顶的两个元素拿出来在运算,然后再再将运算结果进栈,注意的是,假如我们遇到减号,是3-2,是拿栈顶元素做被减数,除法也一样。然后最后返回栈里面的元素。

我这里面的decide方法是判断是不是基本运算的符号:+ - * / ( )

decideNum是判断是不是数字,如果不是,那么肯定就输入有问题。

然后还有一个判断有没有符号 " . ",有的话,就是小时运算,就另做处理。

追后返回运算结果就可以了。 

然后再用一个输出流,返回给客户端就可以了。

客户端代码:

public static void main(String[] args){
		Socket s = null;
		DataOutputStream dos = null;
		InputStream ips = null;
		DataInputStream dips = null;
		try{
			s = new Socket("127.0.0.1", 6666);
			OutputStream fos = null;
			fos = s.getOutputStream();
			System.out.println("请输入你想计算的公式:");
			dos = new DataOutputStream(fos);
			Scanner c = new Scanner(System.in);
			String alls = c.nextLine();
			dos.writeUTF(alls);
			ips = s.getInputStream();
			dips = new DataInputStream(ips);
			String s3 = dips.readUTF();
			System.out.println(s3);
		}catch(IOException io){
			io.printStackTrace();
		}finally{
			try {
				dips.close();
				dos.close();
				s.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
	}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值