BLOG-1_JavaHomework_Summary

来源:https://www.cnblogs.com/Pseach/archive/2022/04/10/16124608.html
-Advertisement-
Play Games

一、前言 雖說上學期為了助眠看了一點 Java 但是散而不精,看而不敲,所以這學期正式學 Java 並沒有想想中那麼容易... 直觀感受:Java有很多和C/C不一樣的地方,Java太嚴謹了,但是相比C/C來說也更安全(不需要領著指針亂跑).... 前三次PTA題目集的小總結 總體來看,前兩次的題目 ...


目錄

一、前言

雖說上學期為了助眠看了一點 Java 但是散而不精,看而不敲,所以這學期正式學 Java 並沒有想想中那麼容易...

直觀感受:Java有很多和C/C++不一樣的地方,Java太嚴謹了,但是相比C/C++來說也更安全(不需要領著指針亂跑)....

前三次PTA題目集的小總結

總體來看,前兩次的題目集偏基礎一點,會使用簡單的迴圈結構、條件判斷、格式化輸出和字元串操作便可輕鬆滿分,題量難度都不算大,但是第三次的題目集便立馬感受到了壓力;

第三次的題目集不僅提高了對Java基礎的要求,還要求從面向過程的思路轉化到面向對象的思維上,在做題前看題便可以註意到,若不使用類和對象便會大大增加代碼量且不易於維護,另外,第三次題目集還對輸入格式的把控提出了苛刻的要求,還要求將數學知識運用到程式中,並時刻註意變數的存儲類型和輸出格式。最重要的是在動手寫之前構思:如何分配對象的方法,如何聯繫對象與對象之間.....

二、設計與分析

題目集2_7-2

源碼的生成報表

LFEt3t.png

代碼類圖

LFcxeI.png

分析 : 一眼丁真:純純的面向過程,代碼簡潔,充斥著if-else ,可讀性不是很高

題目集3_7-1

源碼的生成報表

LFmfzR.png

代碼類圖

LFeqvq.png

分析 : 相比之前,有了更多的方法,代碼量也隨之增加

題目集3_7-2

源碼的生成報表

LFN9v8.png

代碼類圖

LFJiDJ.png

分析 : 使用了更多的類,並以對象進行數據計算代碼清晰了很多

題目集3_7-3

源碼的生成報表

LFN5ZQ.png

代碼類圖

LFNeCq.png

分析 : 使用了更多的類,並以對象進行數據計算代碼清晰了很多

三、採坑心得

這波?這波是Java搞偷襲,是我大意了啊,沒有閃。但沒關係....$%^&%$!$%$'']$]!]@.~\·.!@^[\//*';]/=/[/[\&/]]@=/]/!\-[/-'%/¥

1)數據存儲與輸出

為無限迴圈浮點數保留規定位數並四捨五入

需求:在不知道浮點數的位數是否有限的情況下,為無限迴圈浮點數保留規定位數並四捨五入

踩坑筆記

踩坑思路:printf會自動四捨五入,所以直接使用printf格式化輸出

//假定要保留六位小數
public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
       float a = in.nextFloat(), b = in.nextFloat();
       System.out.printf("a/b: %.6f a+b: %.6f", a / b, a + b);
}

發現問題:

a/b是確確實實按6位保留並四捨五入了,但是a+b本應輸出5.0卻也多了幾個0

//輸入
2 3
//輸出
a/b: 0.666667 a+b: 5.000000

影響:PTA答案錯誤!

解決方法

問題分析:%f會一視同仁格式化所有浮點數,所以只要讓其該根據數據位數來選擇是否要格式化為6位即可

正確寫法:

//假定要保留六位小數
public static void formatPrint(float n) {
       final int esp = (int)1e6;
       if(((n*esp)%10)!=0)            		//小數點後第六位數不為0
           System.out.printf("%.6f",n);    //格式化輸出
       else
           System.out.print(n);
   }

public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
       float a = in.nextFloat(), b = in.nextFloat();
       System.out.print("a/b: ");
       formatPrint(a/b);
       System.out.print(" a+b: ");
       formatPrint(a+b);
}

問題解決:

//輸入
2 3
//輸出
a/b: 0.666667 a+b: 5.0

反思:若第6位恰好是0呢?是否可以用String.format()格式化輸出?

2)其他

忽略if( )中的判斷順序

需求:將字元串根據逗號,或者空格 來分割成若幹部分字元串,並轉化為實數

踩坑筆記

踩坑原因:將迴圈邊界判斷放在了charAt() 之後

public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
       String str = in.nextLine();
       String[] nums = new String[10];
       int idx=0;
       for(int i=0,j=0;i<=str.length();i++){
           if(str.charAt(i)==',' || str.charAt(i)==' ' || i == str.length()){
               nums[idx++] = str.substring(j,i);
               j = ++i;
           }
       }
       System.out.println(nums[0] + " " + nums[1] + " " + nums[2] + " " + nums[3]);
}

發現問題:

數組越界?

//輸入
12,23 34.1,45
//報錯
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 13
	at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:47)
	at java.base/java.lang.String.charAt(String.java:693)
	at Main.main(Main.java:24)

影響:程式運行異常終止

解決方法

問題分析:根據調試發現,if()括弧中的判斷遵循從左到右順序,由於i == str.length() 放在最後,所以先判斷str.charAt(i) 但是迴圈的條件是i<=str.length() 會使str.charAt(i)越界

正確寫法:

public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
       String str = in .nextLine();
       String[] nums = new String[10];
       int idx=0;
       for(int i=0,j=0;i<=str.length();i++){
           //先判斷i是否為末位
           if(i==str.length() || str.charAt(i)==',' || str.charAt(i)==' '){	
               nums[idx++] = str.substring(j,i);
               j = ++i;
           }
       }
       System.out.println(nums[0] + " " + nums[1] + " " + nums[2] + " " + nums[3]);
   }

問題解決:

//輸入
12,23 34.1,45
//輸出
12 23 34.1 45

反思:挺完美了吧(指按格式正常輸入的話)

C/C++帶來的習慣

需求:簡化題目中多組數據的輸入,

踩坑筆記

踩坑原因:不知 Java 的類型一定要完全匹配

//輸入T為組數,每組輸入一個數並將其輸出
public static void main(String[] args) {
   Scanner in = new Scanner(System.in);
   int T = in.nextInt();
   int t;
   while(T--){
       t = in.nextInt();
       System.out.println(t);
   }
}

影響:直接error

解決方法

問題分析:C/C++中,0false,非0的數便是true,但Java不這麼認為,所以只要將int轉化為boolean就好

正確寫法:

//輸入T為組數,每組輸入一個數並將其輸出
public static void main(String[] args) {
   Scanner in = new Scanner(System.in);
   int T = in.nextInt();
   int t;
   while(T-->0){
       t = in.nextInt();
       System.out.println(t);
   }
}

問題解決:

3	//輸入
111	//輸入
111
222	//輸入
222
333	//輸入
333

//進程已結束,退出代碼0

反思:若每組數據要輸入String,怎麼使其不讀入組數後的回車?

四、改進建議

由於前期的小題不需要有整體的構思,導致第三次實驗潦草起手,使得後期維護難上加難,所以動手之前應該考慮工程大小、各部分的責任範圍、

引言:貫穿始終的一條原則就是“想好再做”。如果實在“想不好”,那就“做一點”,出了問題再“好好想”。在實踐中,“做一點”的度很難把握,常常是開了閘就一瀉千里。怎麼判斷這個度呢?我覺得說到底是你對程式的掌控感,要保持程式始終在你的控制之下。比如如果一個函數超過了50行,就是一個危險的信號。
————————————————原文鏈接:https://blog.csdn.net/RiderOnStorm/article/details/594775
在第三次作業最開始的版本中,有很嚴重的代碼複製情況:

//比如這段	作用是將字元串從第二位下標開始,根據空格和逗號分割為若幹部分字元串,並將其轉化為實數存於數組
public static void main(String[] args) {
	Scanner in = new Scanner(System.in);
	String str = in.nextLine();
	int choice = str.charAt(0) - '0';
	str = str.substring(2);	//跳過開始的兩個字元
	String[][] nums = new String[4][];
	
	String[] location = str.split(" ");		//按空格分為若幹個字元串數組
	for (int i = 0; i < 4; i++)
	    nums[i] = location[i].split(",");	//按逗號分為若幹個字元串數組
	
	float[] fls = new float[8];
	fls[0] = Float.parseFloat(nums[0][0]);
	fls[1] = Float.parseFloat(nums[0][1]);
	fls[2] = Float.parseFloat(nums[1][0]);
	fls[3] = Float.parseFloat(nums[1][1]);
	fls[4] = Float.parseFloat(nums[2][0]);
	fls[5] = Float.parseFloat(nums[2][1]);
	fls[6] = Float.parseFloat(nums[3][0]);
	fls[7] = Float.parseFloat(nums[3][1]);
	
	for (float j : fls) System.out.println(j);	//僅供測試功能
}
////////////////////////////////////////////////////
//輸入
1:1,2 3,4 5,6 7,8			
//輸出
1.0
2.0
3.0
4.0
5.0
6.0
7.0
8.0
////////////////////////////////////////////////////

其他地方或許只是數量不同

public static void main(String[] args) {
	Scanner in = new Scanner(System.in);
	String str = in.nextLine();
	int choice = str.charAt(0) - '0';
	str = str.substring(2);	
	String[][] nums = new String[4][];
	
	String[] location = str.split(" ");		
	for (int i = 0; i < 3; i++)
	    nums[i] = location[i].split(",");	
	
	float[] fls = new float[6];
	fls[0] = Float.parseFloat(nums[0][0]);
	fls[1] = Float.parseFloat(nums[0][1]);
	fls[2] = Float.parseFloat(nums[1][0]);
	fls[3] = Float.parseFloat(nums[1][1]);
	fls[4] = Float.parseFloat(nums[2][0]);
	fls[5] = Float.parseFloat(nums[2][1]);
	
	for (float j : fls) System.out.println(j);
}

還有好幾段這樣類似的代碼,因為寫的過程中為了縮短工期而寫出的屎山

明顯看到,可以對其進行優化,大大提升可維護性,並使代碼更簡潔

public static void main(String[] args) {
   Scanner in = new Scanner(System.in);
   String str = in.nextLine();
   int choice = str.charAt(0) - '0';
   str = str.substring(2);
   String[][] nums = new String[4][];
   int len = 4;
   float[] fls = transform(len, str, nums);        //傳入數據

   for (float j : fls) System.out.println(j);
}

public static float[] transform(int size, String str, String[][] num) {
   float[] res = new float[2 * size];
   String[] location = str.split(" ");
   for (int i = 0; i < size; i++)
       num[i] = location[i].split(",");
	////////////////////這真的算是變‘簡潔’了嗎。。。
   for (int i = 0, j = 0, k = 0; i < 2 * size; i++, k++, j += k / 2, k %= 2) {
       res[i] = Float.parseFloat(num[j][k]);
   }

   return res;
}
///////////之前怎麼寫不出呢 ?_?

五、總結

通過該階段的學習,學到了程式基本的整體構思思路、類與類的分工。但對於輸入數據格式問題,仍存在考慮不全不周的問題,需要在今後的學習中著重註意。

對作業的感覺:挺有挑戰性的,值得一做!

對今後學習方法的建議:不要只看不敲,看懂不等於學會,當然,若能用最精簡的語言點通不懂的人,那便證明你真正學到點東西了。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 3天時間從零到上架AppStore流程記錄 清明假期剛過去一周,我如願以償把自己想要的一個App上架了AppStore 從有idea到技術選型,從設計稿到框架開發,從提審AppStore到上架一共經歷了3天,這3天里我踩了很多坑,忙得焦頭爛額,期間發現網上很多信息都是過時的,所以本著一個總結的想法, ...
  • 迭代: 啥子是迭代?可以簡單地理解為按順序訪問目標(數組、對象等)中的每一項(其實和遍歷概念沒什麼差別) 上代碼 1 var fruits = ["Apple", "Orange", "Apple", "Mango"]; 2 var a = fruits.indexOf("Apple"); 3 co ...
  • 我們可以很輕鬆的去遍歷一棵樹,無論是廣度優先遍歷還是深度優先遍歷,那麼怎麼在小程式當中渲染一棵樹呢? 先看一下我們深度優先遍歷的代碼 function dfs(tree) { if(!tree) return console.log(tree.value) if (tree.children) { ...
  • 今天是我們最後一天ajax的學習,這次學完總可以去vue了吧,我不信還有什麼攔路石,先不說其他的先看看今天的內容。 1. 首先是同源策略,什麼叫做同源? 如果兩個頁面的協議、功能變數名稱、埠都相同的話,我們將這兩個頁面為同源。 那麼什麼同源策略呢? 是瀏覽器提供的一個安全功能,如果說兩個頁面不同源,那麼A ...
  • 一、基礎使用 1、變數、表達式、class style、子元素和組件 2、if else、三元表達式、邏輯運算符 && || 3、map、key 4、bind this 5、關於event參數,react的event不是原生的,event.nativeEvent才是指向原生event,所有的事件都是 ...
  • 1. 今天的內容其實挺多的,我們慢慢來說。首先第一個是xhr的基本使用,什麼是xhr? XMLHTTPRequest是瀏覽器提供的js對象,可以請求伺服器上的數據資源,包括我們前面一直用的jq裡面的三個請求資源的方法都是基於xhr來封裝的。 那麼首先我們看到xhr的get請求怎麼來實現 首先要創建x ...
  • 1. 今天繼續ajax的一個學習,首先明確一個觀念,介面,什麼是介面,當使用ajax請求數據時,被請求的url就叫做數據介面也就是介面,註意每個介面必須有請求方式,這裡有一個介面的測試工具,postman自稱是全球最快的,反正使用起來沒多大毛病,使用這個軟體的時候有一個註意點就是在post請求的時候 ...
  • 進入ajax了,想要進入vue還有一個前提就是要把ajax給熟悉一下,看一看客戶端與伺服器之間是怎麼一個通信的過程,第一天主要是先瞭解了一下ajax的一些介紹,ajax嘛,在進入之前,肯定是要瞭解一下客戶端與伺服器之間的一個通信過程,其實不管是請求還是發送都遵循的一個原則,即請求、處理、響應,如何來 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...