20192321 實驗四 《資料結構與面向物件程式設計》實驗報告
20192321 實驗四 《資料結構與面向物件程式設計》實驗報告
課程:《程式設計與資料結構》
班級:1923
姓名:李錦程
學號:20192321
實驗教師:王志強
實驗日期:2020年10月8日
必修/選修:必修
1.實驗內容
- (一)Java Socket程式設計
1.學習藍墨雲上教材《Java和Android程式設計》“第16章 輸入/輸出 ”和“第22章 網路”,學習JavaSocket程式設計
2.結對程式設計。結對夥伴A編寫客戶端SocketClient.java,結對夥伴B編寫伺服器端。
3.截圖加學號水印上傳藍墨雲,程式碼push到碼雲,並撰寫實驗報告。 - (二)Java和密碼學
以結對的方式完成Java密碼學相關內容的學習(帖子中所有程式碼和相關知識點需要學習)。提交學習成果碼雲連結和代表性成果截圖,要有學號水印。 - (三)編寫有理數/複數計算器
結對程式設計,結對夥伴A編寫有理數計算器。結對夥伴B編寫複數計算器。截圖加水印上傳藍墨雲,程式碼push碼雲。 - (四)遠端有理數計算器
結對程式設計,結對夥伴A程式設計實現客戶端,結果夥伴B實現伺服器端。
客戶端通過鍵盤輸入一個有理數計算的公式(例如:1/4 + 1/6 = ),並把該公式以字串的形式傳送給夥伴B(伺服器端),伺服器端根據字串計算出結果為5/12,並把結果返回給客戶端A,A收到結果後輸出結果。截圖加水印上傳藍墨雲,程式碼push碼雲。 - (五)遠端複數計算器
結對程式設計,結對夥伴B程式設計實現客戶端,結果夥伴A實現伺服器端。
客戶端通過鍵盤輸入一個有理數計算的公式(例如:1/4 + 1/6 = ),並把該公式以字串的形式傳送給夥伴A(伺服器端),伺服器端根據字串計算出結果為5/12,並把結果返回給客戶端B,B收到結果後輸出結果。截圖加水印上傳藍墨雲,程式碼push碼雲。
注意實驗四(4)和實驗四(5),一個人不能僅實現客戶端,必須實現一個客戶端和伺服器,否則兩個實驗均不得分!!! - (六)實驗報告
在規定時間前發表部落格,標題“學號 實驗四 《資料結構與面向物件程式設計》實驗報告”
2.實驗過程及結果
(一)Java Socket程式設計
//import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class server { public static void main(String[] args) throws IOException { //1.建立一個伺服器Socket(ServerSocket)繫結指定埠 ServerSocket serverSocket=new ServerSocket(8809); //2.使用accept()方法阻止等待監聽,獲得新連線 Socket socket=serverSocket.accept(); //3.獲得輸入流 InputStream inputStream=socket.getInputStream(); BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream)); //獲得輸出流 OutputStream outputStream=socket.getOutputStream(); PrintWriter printWriter=new PrintWriter(outputStream); //4.讀取使用者輸入資訊 String info=null; System.out.println("伺服器已經建立......"); while(!((info = bufferedReader.readLine()) ==null)){ System.out.println("我是伺服器,使用者資訊為:" + info); } //給客戶一個響應 String reply="welcome"; printWriter.write(reply); printWriter.flush(); //5.關閉資源 printWriter.close(); outputStream.close(); bufferedReader.close(); inputStream.close(); socket.close(); serverSocket.close(); } }
(二)Java和密碼學
參考 http://www.cnblogs.com/rocedu/p/6683948.html
以結對的方式完成Java密碼學相關內容的學習(帖子中所有程式碼和相關知識點需要學習)。提交學習成果碼雲連結和代表性成果截圖,要有學號水印。
(三)編寫有理數/複數計算器
結對程式設計,結對夥伴A編寫有理數計算器。結對夥伴B編寫複數計算器。截圖加水印上傳藍墨雲,程式碼push碼雲。
複數計算器
package Complex;
public class ComplexNumber
{
double Realpart;
double Imagepart;
public double getRealpart() {
return Realpart;
}
public double getImagepart() {
return Imagepart;
}
public void setRealpart(double realpart) {
Realpart = realpart;
}
public void setImagepart(double imagepart) {
Imagepart = imagepart;
}
public ComplexNumber()
{
}
public ComplexNumber(double realpart, double imagepart) {
Realpart = realpart;
Imagepart = imagepart;
}
@Override
public String toString() {
return "ComplexNumber{" +
"Realpart=" + Realpart +
", Imagepart=" + Imagepart +
'}';
}
}
package Complex;
public class ComplexNumCal extends ComplexNumber implements Comparable
{
public ComplexNumCal(double realpart, double imagepart)
{super(realpart,imagepart);}
public ComplexNumCal (){}
public ComplexNumCal add(ComplexNumCal a,ComplexNumCal b)
{
ComplexNumCal temp=new ComplexNumCal();
temp.Realpart=a.Realpart+b.Realpart;
temp.Imagepart=a.Imagepart+b.Imagepart;
return temp;
}
public ComplexNumCal contract(ComplexNumCal a,ComplexNumCal b)
{
ComplexNumCal temp=new ComplexNumCal();
temp.Realpart=a.Realpart-b.Realpart;
temp.Imagepart = a.Imagepart - b.Imagepart;
return temp;
}
public ComplexNumCal multi(ComplexNumCal a,ComplexNumCal b)
{
ComplexNumCal temp=new ComplexNumCal();
temp.Realpart = a.Realpart * b.Realpart - a.Imagepart * b.Imagepart;
temp.Imagepart = a.Realpart * b.Imagepart + a.Imagepart * b.Realpart;
return temp;
}
public ComplexNumCal div(ComplexNumCal a,ComplexNumCal b)
{
ComplexNumCal temp=new ComplexNumCal();
temp.Realpart = a.Realpart * b.Realpart - a.Imagepart * b.Imagepart;
temp.Imagepart = a.Realpart * b.Imagepart + a.Imagepart * b.Realpart;
return temp;
}
public int compareTo(ComplexNumCal o) {
Integer i=-5;
if((this.Realpart+this.Imagepart)<(o.Realpart+o.Imagepart))
i=-1;
else if((this.Realpart+this.Imagepart)==(o.Realpart+o.Imagepart))
i=0;
else if((this.Realpart+this.Imagepart)>(o.Realpart+o.Imagepart))
i=1;
return i;
}
@Override
public int compareTo(Object o) {
return 0;
}
}
有理數計算器
package myRocket;
import duotai.Pets;
public class RationNumber {
private int numerator,denominator;
public RationNumber(int numer,int denom)
{
if(denom==0)
denom=1;
if(denom<0)
{
numer=numer*-1;
denom=denom*-1;
}
numerator=numer;
denominator=denom;
}
public RationNumber(){}
public int getNumerator() {
return numerator;
}
public int getDenominator() {
return denominator;
}
public RationNumber reciprocal()
{
return new RationNumber(denominator, numerator);
}
public RationNumber add(RationNumber op2)
{
int commonDenominator=denominator*op2.getDenominator();
int numerator1=numerator*op2.getDenominator();
int numerator2=op2.getNumerator()*denominator;
int sum=numerator1+numerator2;
return new RationNumber(sum, commonDenominator);
}
public RationNumber subtract(RationNumber op2)
{
int commonDenominator=denominator*op2.getDenominator();
int numerator1=numerator*op2.getDenominator();
int numerator2=op2.getNumerator()*denominator;
int difference=numerator1-numerator2;
return new RationNumber(difference, commonDenominator);
}
public RationNumber multiply(RationNumber op2)
{
int numer=numerator*op2.getDenominator();
int denom=denominator*op2.getDenominator();
return new RationNumber(numer, denom);
}
public RationNumber divide(RationNumber op2)
{
return multiply(op2.reciprocal());
}
private void reduce()
{
if(numerator!=0)
{
int common=gcd(Math.abs(numerator),denominator);
numerator=numerator/common;
denominator=denominator/common;
}
}
private int gcd(int num1,int num2)
{
while (num1!=num2)
if(num1>num2)
num1=num1-num2;
else
num2=num2-num1;
return num1;
}
@Override
public String toString() {
return "RationNumber{" +
"numerator=" + numerator +
", denominator=" + denominator +
'}';
}
}
package myRocket;
import duotai.Pets;
public class RationNumber {
private int numerator,denominator;
public RationNumber(int numer,int denom)
{
if(denom==0)
denom=1;
if(denom<0)
{
numer=numer*-1;
denom=denom*-1;
}
numerator=numer;
denominator=denom;
}
public RationNumber(){}
public int getNumerator() {
return numerator;
}
public int getDenominator() {
return denominator;
}
public RationNumber reciprocal()
{
return new RationNumber(denominator, numerator);
}
public RationNumber add(RationNumber op2)
{
int commonDenominator=denominator*op2.getDenominator();
int numerator1=numerator*op2.getDenominator();
int numerator2=op2.getNumerator()*denominator;
int sum=numerator1+numerator2;
return new RationNumber(sum, commonDenominator);
}
public RationNumber subtract(RationNumber op2)
{
int commonDenominator=denominator*op2.getDenominator();
int numerator1=numerator*op2.getDenominator();
int numerator2=op2.getNumerator()*denominator;
int difference=numerator1-numerator2;
return new RationNumber(difference, commonDenominator);
}
public RationNumber multiply(RationNumber op2)
{
int numer=numerator*op2.getDenominator();
int denom=denominator*op2.getDenominator();
return new RationNumber(numer, denom);
}
public RationNumber divide(RationNumber op2)
{
return multiply(op2.reciprocal());
}
private void reduce()
{
if(numerator!=0)
{
int common=gcd(Math.abs(numerator),denominator);
numerator=numerator/common;
denominator=denominator/common;
}
}
private int gcd(int num1,int num2)
{
while (num1!=num2)
if(num1>num2)
num1=num1-num2;
else
num2=num2-num1;
return num1;
}
@Override
public String toString() {
return "RationNumber{" +
"numerator=" + numerator +
", denominator=" + denominator +
'}';
}
}
(四)遠端有理數計算器
結對程式設計,結對夥伴A程式設計實現客戶端,結果夥伴B實現伺服器端。
客戶端通過鍵盤輸入一個有理數計算的公式(例如:1/4 + 1/6 = ),並把該公式以字串的形式傳送給夥伴B(伺服器端),伺服器端根據字串計算出結果為5/12,並把結果返回給客戶端A,A收到結果後輸出結果。截圖加水印上傳藍墨雲,程式碼push碼雲。
(五)遠端複數計算器
結對程式設計,結對夥伴B程式設計實現客戶端,結果夥伴A實現伺服器端。
客戶端通過鍵盤輸入一個有理數計算的公式(例如:1/4 + 1/6 = ),並把該公式以字串的形式傳送給夥伴A(伺服器端),伺服器端根據字串計算出結果為5/12,並把結果返回給客戶端B,B收到結果後輸出結果。截圖加水印上傳藍墨雲,程式碼push碼雲。
注意實驗四(4)和實驗四(5),一個人不能僅實現客戶端,必須實現一個客戶端和伺服器,否則兩個實驗均不得分!!!
package myRocket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class 客戶端初步嘗試 {
public static void main(String[] args) throws IOException {
String host = "127.0.0.1";
int port = 8080;
//Socket socket = new Socket(host, port);
//OutputStream output = socket.getOutputStream();
Scanner scan = new Scanner(System.in);
String message=new String();
while(true){
Socket socket = new Socket(host, port);
OutputStream output = socket.getOutputStream();
System.out.println("輸入資訊");
message=scan.next();
output.write(message.getBytes("utf-8"));
socket.shutdownOutput();
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String read = input.readLine();
System.out.println("伺服器的內容 " +read);
input.close();
if(message.equals("end")) break;
}
//message="1/4+1/3";
//output.write(message.getBytes("utf-8"));
//正常來說,客戶端開啟一個輸出流,如果不做約定,也不關閉它,那麼服務端永遠不知道客戶端是否傳送完訊息,
//那麼服務端會一直等待下去,直到讀取超時。所以怎麼告知服務端已經發送完訊息就顯得特別重要。
//socket.close();
//Socket關閉的時候,服務端就會收到響應的關閉訊號,那麼服務端也就知道流已經關閉了,這個時候讀取操作完成,就可以繼續後續工作
}
}
package myRocket;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class 伺服器初步嘗試 {
public static void main(String[] args) throws Exception{
//指定監聽的埠
int myport = 8080;
ServerSocket myserver = new ServerSocket(myport,1);
//等待連線的到來
//System.out.println("server將一直等待連線的到來");
//Socket socket = myserver.accept();
//accept 偵聽並接受到此套接字的連線。此方法在連線傳入之前一直阻塞。
//即 伺服器呼叫 accept() 方法,該方法將一直等待直到客戶端連線到伺服器上給定的埠。.
// 讀取客戶端資料
//BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String clientInputStr =new String();
while(true) {
//等待連線的到來
System.out.println("server將一直等待連線的到來");
Socket socket = myserver.accept();
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
clientInputStr = input.readLine();
/*Scanner scan = new Scanner(socket.getInputStream());
clientInputStr = scan.next();//這也是一種方法*/
System.out.println("客戶端發過來的內容:" + clientInputStr);
if(clientInputStr.equals("end")) {input.close();break;}
OutputStream output = socket.getOutputStream();
output.write(複數計算/*有理數計算嘗試*/.計算(clientInputStr).getBytes());
input.close();
output.close();
}
//public InputStream getInputStream()throws IOException返回此套接字的輸入流。
//------------------------------------
// public BufferedReader(Reader in) :建立一個使用預設大小輸入緩衝區的緩衝字元輸入流。
//InputStreamReader 是位元組流通向字元流的橋樑:它使用指定的 charset ***讀取位元組並將其解碼為字元*** 。它使用的字符集可以由名稱指定或顯式給定,或者可以接受平臺預設的字符集。
//每次呼叫 InputStreamReader 中的一個 read() 方法都會導致從底層輸入流讀取一個或多個位元組。要啟用從位元組到字元的有效轉換,可以提前從底層流讀取更多的位元組,使其超過滿足當前讀取操作所需的位元組。
//為了達到最高效率,可要考慮在 BufferedReader 內包裝 InputStreamReader。例如:
// BufferedReader in
// = new BufferedReader(new InputStreamReader(System.in));
//位元組流->字元流->字元流緩衝區
//-----------------------------------
//String clientInputStr = input.readLine();//這裡要注意和客戶端輸出流的寫方法對應,否則會拋 EOFException
// 處理客戶端資料
//System.out.println("客戶端發過來的內容:" + clientInputStr);
//有理數計算嘗試.計算(clientInputStr);
//input.close();
//socket.close();
myserver.close();
}
}
3.實驗過程中遇到的問題和解決過程
- 問題1:有理數計算器的最小公倍數與最大公約數演算法
- 問題1解決方案:找到網上程式碼和部落格學長學姐程式碼,研讀演算法
- 問題2:遠端計算器分配引數、識別運算子號
- 問題2解決方案:參考同學程式碼運算方式,網上查詢陌生關鍵詞
其他(感悟、思考等)
在這次實驗過程中,我遇到了許多問題,其中既有知識上的漏洞,也有不細心導致的馬虎,這一切都補充,完善,豐富,擴充套件了我的計算機知識體系。在這個過程中,我還進一步熟悉了IDEA這個平臺的使用與執行方式,提高了自己自主學習的能力,為我接下來學習資料結構以及JAVA語言程式設計打下了堅實的基礎,並在不斷探索的過程中逐步提升了自己。