兩人一組結對編程:html
1、實驗過程:java
1.根據婁老師的博客,咱們先了解前綴表示法、中綴表示法和後綴表示法的概念:git
表達式Exp = S1 + OP + S2
(S1 ,S2是兩個操做數,OP爲運算符)有三種標識方法:算法
OP + S1 + S2
爲前綴表示法
S1 + OP + S2
爲中綴表示法
S1 + S2 + OP
爲後綴表示法
例如:Exp = a * b + (c - d / e) * f
express
前綴式: + * a b * - c / d e f
中綴式: a * b + c - d / e * f
後綴式: a b * c d e / - f * +
編程
2.中綴表達式轉化成後綴表達式的過程:數組
3.中綴表達式轉化成後綴表達式代碼實現:安全
import java.util.*; public class NewMyBC { String beforeExpression;//未轉化的中綴表達式 String afterExpression = "";//轉化後的後綴表達式 int left = 0;//定義左括號數 int right = 0;//定義右括號數 //判斷符號的級別 public int judgeGrade(char chi) { int grade = 0; switch (chi) { //左括號是第一級 case '(': grade = 1; break; //+和-是第二級 case '+': case '-': grade = 2; break; //*和÷是第三級 case '*': case '÷': grade = 3; break; // "/"是第四級 case '/': grade = 4; break; //右括號是第五級 case ')': grade = 5; break; default: grade = 0; } return grade; } public void setBeforeExpression(String exp) { beforeExpression=exp; } public String transformWay() { Stack stack = new Stack();//新建一個空棧 int i = 0; char op; while (i < beforeExpression.length()) { op = beforeExpression.charAt(i);//op存放從中綴表達式中取到的元素 if (op >= '0' && op <= '9') { afterExpression = afterExpression + op;//若是是數字,則直接輸出至後綴表達式 } else if (op == '+' || op == '-' || op == '*' || op == '÷') { afterExpression = afterExpression + ' ';//有運算符,在數字之間加空格 // 若是棧爲空,則運算符直接入棧 if (stack.empty()) { stack.push(op); } //根據符號的級別判斷操做 else if (judgeGrade(op) > judgeGrade((char) stack.peek())) { stack.push(op);//比棧頂級別高或相等,直接入棧 } else { afterExpression = afterExpression + String.valueOf(stack.pop()) + ' ';//不然直接輸出 i--; } } else if (op == '(') { left++; stack.push(op);//左括號直接入棧 } else if (op == ')') { afterExpression += " "; right++; while ((char) stack.peek() != '(') {//右括號,出棧,直到左括號爲止 afterExpression = afterExpression + String.valueOf(stack.pop()) + " "; } stack.pop(); } i++; } afterExpression += " "; while(!stack.empty()){ afterExpression=afterExpression+String.valueOf(stack.pop())+" "; } if (left != right) { System.out.println("括號有誤"); System.exit(0); } return afterExpression; } }
4.後綴表達式求值的步驟:服務器
5.求值代碼:網絡
import java.util.Stack; public class MyDC { /** * constant for addition symbol */ private final char ADD = '+'; /** * constant for subtraction symbol */ private final char SUBTRACT = '-'; /** * constant for multiplication symbol */ private final char MULTIPLY = '*'; /** * constant for division symbol */ private final char DIVIDE = '÷'; /** * the stack */ private Stack<Integer> stack;//存放操做數的棧 public MyDC() { stack = new Stack<Integer>(); } public int evaluate(String expr) { int op1, op2, result = 0; String token; StringTokenizer tokenizer = new StringTokenizer(expr);//劃分表達式 while (tokenizer.hasMoreTokens()) { token = tokenizer.nextToken();//將算數表達式分解的 if (isOperator(token))//見下方isOperateor方法,當是運算符的時候進入if語句 { op2 = (stack.pop()).intValue(); op1 = (stack.pop()).intValue();//彈出最上面兩個操做數 result = evalSingleOp(token.charAt(0), op1, op2);//見下方evaSingleOp方法 stack.push(new Integer(result));//將計算結果壓棧 } else{ stack.push(new Integer(Integer.parseInt(token)));//操做數入棧 } } return result;//輸出結果 } private boolean isOperator(String token)//判斷是否爲運算符,注意用equal語句比較字符串 { return (token.equals("+") || token.equals("-") || token.equals("*") || token.equals("÷")); } private int evalSingleOp(char operation, int op1, int op2) { int result = 0; switch (operation) { case ADD: result = op1 + op2; break; case SUBTRACT: result = op1 - op2; break; case MULTIPLY: result = op1 * op2; break; case DIVIDE: result = op1 / op2; } return result; } }
6.測試代碼以下:
import java.util.Scanner; public class MyDCTest { public static void main(String[] args) { String expression, again; int result; try { Scanner in = new Scanner(System.in); do { MyDC evaluator = new MyDC(); System.out.println("Enter a valid postfix expression: "); expression = in.nextLine(); result = evaluator.evaluate(expression); System.out.println(); System.out.println("That expression equals " + result); System.out.print("Evaluate another expression [Y/N]? "); again = in.nextLine(); System.out.println(); } while (again.equalsIgnoreCase("y")); } catch (Exception IOException) { System.out.println("Input exception reported"); } } }
2、實驗截圖:
3、碼雲連接
結對編程:1人負責客戶端,一人負責服務器
1、實驗過程:
1.通過與搭檔協商,我負責客戶端(Client.java)部分,搭檔負責服務端(Server.java)部分。
2.客戶端部分的代碼以下:
import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.*; import java.net.*; import java.util.*; public class Client { public static void main(String[] args) { Socket socket;//套接字對象 DataInputStream in=null;//輸入流 DataOutputStream out=null;//輸出流 //中綴表達式的輸入 String str; Scanner scanner=new Scanner(System.in); System.out.println("請輸入中綴表達式:"); str=scanner.nextLine(); try { socket=new Socket("localhost",5203); in=new DataInputStream(socket.getInputStream()); out=new DataOutputStream(socket.getOutputStream()); out.writeUTF(str); String s=in.readUTF(); System.out.println("結果爲:\n"+s); } catch (Exception e) { System.out.println("服務器已斷開"+e); } } }
2、實驗截圖:
3、碼雲連接
加密結對編程:1人負責客戶端,一人負責服務器
1、實驗過程:
1.我負責客戶端,負責編寫Client.java
.
2.根據婁老師的密碼學算法博客,我和搭檔所共同完成的DES算法代碼以下:
import java.io.*; import javax.crypto.*; public class Skey_DES{ public static void main(String args[]) throws Exception{ KeyGenerator kg=KeyGenerator.getInstance("DESede"); kg.init(168); SecretKey k=kg.generateKey( ); FileOutputStream f=new FileOutputStream("key1.dat"); ObjectOutputStream b=new ObjectOutputStream(f); b.writeObject(k); } }
3.Client.java代碼以下:
在以前的代碼上,增長以下代碼:
import java.io.*; import java.net.*; import java.util.Scanner; public class Client { public static void main(String[] args) { String mess; Scanner scanner=new Scanner(System.in); System.out.println("請輸入問題"); mess=scanner.nextLine(); String key=""; int n=-1; byte [] a=new byte[128]; try{ File f=new File("key1.dat"); InputStream in = new FileInputStream(f); while((n=in.read(a,0,100))!=-1) { key=key+new String (a,0,n); } in.close(); } catch(IOException e) { System.out.println("File read Error"+e); } System.out.println("客戶端提出的問題爲:"+mess); NewMyBC mybc=new NewMyBC(); String str; mybc.setBeforeExpression(mess); str=mybc.transformWay(); String mi=EncryptDecrypt.AESEncode(key,str); System.out.println("客戶端加密後密文爲:"+mi); Socket socket; DataInputStream in=null; DataOutputStream out=null; try{ socket=new Socket("localhost",5006); in=new DataInputStream(socket.getInputStream()); out=new DataOutputStream(socket.getOutputStream()); BufferedReader in1=new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter writer=new PrintWriter(socket.getOutputStream()); out.writeUTF(mi); String s=in.readUTF(); //in讀取信息,堵塞狀態 System.out.println("客戶收到服務器的回答爲:"+s); Thread.sleep(500); } catch(Exception e) { System.out.println("服務器已斷開"+e); } } }
2、實驗截圖:
3、碼雲連接
密鑰分發結對編程:1人負責客戶端,一人負責服務器
1、實驗過程:
1.我負責客戶端,搭檔負責服務器端。
2.根據婁老師的密碼學算法博客,我和搭檔共同完成的DES算法代碼以下:
import java.security.PublicKey; import java.security.PrivateKey; import java.io.*; import javax.crypto.KeyAgreement; import javax.crypto.spec.*; public class KeyAgree{ public static void main(String args[ ]) throws Exception{ // 讀取對方的DH公鑰 File file=new File("Ckey.dat"); FileInputStream f1=new FileInputStream("Apub.dat"); ObjectInputStream b1=new ObjectInputStream(f1); PublicKey pbk=(PublicKey)b1.readObject( ); //讀取本身的DH私鑰 FileInputStream f2=new FileInputStream("Bpri.dat"); ObjectInputStream b2=new ObjectInputStream(f2); PrivateKey prk=(PrivateKey)b2.readObject( ); // 執行密鑰協定 KeyAgreement ka=KeyAgreement.getInstance("DH"); ka.init(prk); ka.doPhase(pbk,true); //生成共享信息 byte[ ] sb=ka.generateSecret(); for(int i=0;i<sb.length;i++){ System.out.print(sb[i]+","); } OutputStream out=new FileOutputStream(file); out.write(sb); out.close(); SecretKeySpec k=new SecretKeySpec(sb,"AES"); } }
public class Dapart { String dapartstring(String str){ String s=""; char c[]=str.toCharArray(); for(int i=0;i<c.length;i++){ s=s+c[i]+" "; } return s; } }
部分代碼,具體代碼見碼雲連接
3.客戶端的代碼在實驗二的基礎上增長以下代碼:
import java.io.*; import java.net.*; import java.util.Scanner; public class Client { public static void main(String[] args)throws IOException{ String key=""; int n=-1; byte [] a=new byte[128]; try{ File f=new File("Ckey.dat"); InputStream in = new FileInputStream(f); while((n=in.read(a,0,100))!=-1) { key=key+new String (a,0,n); } in.close(); } catch(IOException e) { System.out.println("File read Error"+e); } String mess; Scanner scanner=new Scanner(System.in); System.out.println("請輸入問題:"); mess=scanner.nextLine(); NewMyBC mybc=new NewMyBC(); String str; mybc.setBeforeExpression(mess); str=mybc.transformWay(); String m=EncryptDecrypt.AESEncode(key, str); System.out.println("客戶加密以後的密文爲:"+m); Socket mysocket; DataInputStream in=null; DataOutputStream out=null; try{ mysocket=new Socket("localhost",6006); in=new DataInputStream(mysocket.getInputStream()); out=new DataOutputStream(mysocket.getOutputStream()); out.writeUTF(m); String s=in.readUTF(); //in讀取信息,堵塞狀態 System.out.println("客戶收到服務器的回答爲:"+s); Thread.sleep(500); } catch(Exception e) { System.out.println("服務器已斷開"+e); } } }
2、實驗截圖:
3、碼雲連接
實驗五 網絡編程與安全-5
完整性校驗結對編程:1人負責客戶端,一人負責服務器
1、實驗過程:
1.我負責客戶端,搭檔負責服務器端。
2.根據婁老師的密碼學算法博客,我和搭檔共同完成的算法代碼以下:
import java.security.*; public class DigestPass{ static String md5(String str) throws Exception{ MessageDigest m=MessageDigest.getInstance("MD5"); m.update(str.getBytes("UTF8")); byte s[ ]=m.digest( ); String result=""; for (int i=0; i<s.length; i++){ result+=Integer.toHexString((0x000000ff & s[i]) | 0xffffff00).substring(6); } return result; } }
3.客戶端代碼以下:
就以前實驗二的代碼添加以下代碼:
import java.net.*; import java.util.Scanner; public class Client { public static void main(String[] args) throws Exception { String key = ""; int n = -1; byte[] a = new byte[128]; try { File f = new File("Ckey.dat"); InputStream in = new FileInputStream(f); while ((n = in.read(a, 0, 100)) != -1) { key = key + new String(a, 0, n); } in.close(); } catch (IOException e) { System.out.println("File read Error" + e); } String mess; Scanner scanner = new Scanner(System.in); System.out.println("請輸入問題爲:"); mess = scanner.nextLine(); NewMyBC mybc = new NewMyBC(); String str; mybc.setBeforeExpression(mess); str = mybc.transformWay(); String md5 = DigestPass.md5(str); String mw = EncryptDecrypt.AESEncode(key, str); System.out.println("客戶端提供的MD—5爲:" + md5); System.out.println("客戶加密以後的密文爲:" + mw); Socket mysocket; DataInputStream in = null; DataOutputStream out = null; try { mysocket = new Socket("localhost", 2010); in = new DataInputStream(mysocket.getInputStream()); out = new DataOutputStream(mysocket.getOutputStream()); out.writeUTF(mw); out.writeUTF(md5); String answer = in.readUTF(); //in讀取信息,堵塞狀態 System.out.println("客戶收到服務器的回答爲:" + answer); Thread.sleep(500); } catch (Exception e) { System.out.println("服務器已斷開" + e); } } }
部分代碼,具體代碼見碼雲連接
2、實驗截圖:
3、碼雲連接
Q:在運行代碼時,提示Error:(1, 1) java: 非法字符: '\ufeff'
,該怎麼作?
A:我百度了一下,找到了一篇博客,根據博客裏的步驟,解決了問題。
步驟 | 耗時(h) | 百分比 |
---|---|---|
設計 | 2 | 20% |
代碼實現 | 5 | 50% |
測試 | 5 | 20% |
分析總結 | 1 | 10% |
本次實驗,我主要負責客戶端代碼,搭檔負責服務器端代碼,許多算法也是咱們根據婁老師的博客共同研究出來的。本次實驗是最後一次實驗了,本學期的確受Java折磨很多,可是仍是感謝婁老師給咱們提供了不少新的學習方法,相信之後Java會幫助咱們不少的。