1. 程式人生 > 其它 >三次題目集的總結

三次題目集的總結

       在前三次題目集中,從第一次的Java基礎語句的使用和簡單的輸入輸出,到第二次字串解析和字串相關函式,再到第三次類與物件的定義和使用還有方法的建立與呼叫,並且還考察了正則表示式,難度是層層遞進,尤其是第三次題目集的測試點眾多和演算法較難,所以分數也丟了不少。

       以下部分是三次題目集的實現分析,作業總結。

三次題目集的設計與分析

題目集1

   第一次作業共有9題,主要是考察一些資料的輸入和輸出,加上if、while、switch、for語句的使用,if 以及else if的巢狀,還有資料型別的正確選擇以及型別轉換,題目相對簡單,因為有了C語言的基礎,可以更快的過渡到Java語言中。

  例如題目集1的7-1 身體質量指數(BMI)測算,給出一組輸入,得到相應的輸出,要運用到輸入輸出語句,首先就要判斷輸入資料的型別,這裡我選擇double資料型別,然後計算出結果,通過if語句判斷輸入資料是否超出範圍,再通過if與if else巢狀判斷結果得到相應的輸出。

            if(BMI < 18.5)
                System.out.print("thin");
            else if(BMI >= 18.5 && BMI <= 24)
                System.out.print(
"fit"); else if(BMI >= 24 && BMI <= 28) System.out.print("overweight"); else System.out.print("fat");

  7-3 奇數求和 首先通過把輸出的資料存入陣列再判斷奇偶性實行累加,使用一個for語句來遍歷陣列,同時包含if語句判斷奇偶性,如果為奇數就累加,最後輸出count。

for(int i = 0; i < a.length; i++){
            a[i] 
= in.nextInt(); if(a[i]%2 == 1 || a[i]%2 == -1){ count += a[i]; } }

 

  7-9 二進位制數值提取的操作為輸入一組字串,去掉非0、1字元以-1結尾,那麼首先將輸入的字串通過toCharArray()函式轉換為字元陣列,然後通過遍歷陣列查詢是否含有-1結束符來判斷字串是為Wrong Format,因為-1佔兩個數組長度,所以判斷時要先判斷是否為-再判斷後一位是否為1,所以我使用了一個while語句來實行判斷,同樣輸出時再遍歷陣列輸出字串中的0和1。                    

while(j<mes.length)
        {
            if(mes[j] == '-' && j+1<mes.length)
            {
                if(mes[j+1] == '1'){
                    found = false;
                    break;
                }
            }
            j++;
        }

 

  第一次題目集雖然相對簡單,包含了Java語言基礎的語句和各種資料型別,但十分重要且關鍵,因為第二次,第三次題目集都是以這個為基礎建立。

  題目集1是我們對從c語言語法向Java語法的一個轉變,考察的相對簡單,題目也相對簡單,更多的是讓我們瞭解Java的一些基本的語法,習題集1的答題情況都為100分,在第7-9的測試點上有所欠缺,練習了好幾遍才通過了所有的測試點。

題目集2

  第二次作業較第一次難度有所提升,共有3題,主要考察Char,String型別的輸入輸出和相關函式,字元和字串作為最常用資料型別之一,其中的相關函式也是比較多和實用的,引入了字串處理String.用for迴圈對字串的遍歷處理,對二進位制的處理應用到字串中,同樣也考察了我們在C語言中學習到的排序演算法,選擇排序,將兩個排序後的數組合併成一個新的陣列,

  7-1 字母-數字轉換就用到了isLowerCase()、isUpperCase()函式來判斷字元是大寫還是小寫,同樣可以判斷字串中有沒有字母,以此來判斷字串是否為Wrong Format,字母轉化為數字時,因為字母大寫和小寫的ASCII碼值不同,所以來建立一個wordtonumber方法將字母轉化為數字並輸出。

    public static void wordtonumber(char ss)
    {
        int num;
        if(Character.isLowerCase(ss)){
             num = (int) (ss - 'a' + 1);
        }
        else{
             num = (int) (ss - 'A' + 1);
        }
        System.out.print(num);
    }

  7-2 串列埠字元解析,由0、1組成的二進位制資料流,過濾掉空閒、起始、結束以及奇偶校驗位之後的資料,資料之前加上序號和英文冒號。這個題目考察了我們對於字串的處理,怎樣定義一個字串以及怎樣提取出字串的某一波分進行單獨處理。這些都是這個題目考察的亮點也是難點,解這道題我們首先要去定義一個字串,而且在解這道題目的同時我們也要明白二進位制轉化的方式,首先將字串轉換為字元陣列,然後遍歷陣列判斷字串中有無起始位,是否為null data,由於資料太長且判斷太多我用了一個for語句包攬了所有的判斷和輸出,包括資料的結束符不為1、資料奇偶校驗錯誤、資料結束符和奇偶校驗均不合格,這個方法可能顯得有些贅餘不夠簡便,還可以做出修改讓程式碼精簡一點。

            for(int a = 1,j = 0; j < ss.length; j++)
            {
                if(ss[j] == '0'&&j+10<ss.length)
                {
                    int h1 = 0;
                    boolean jiou = false;
                    for(int h = j; h < j+8; h++){
                        if(ss[h+1] == '1'){
                            h1++;
                        }
                    }
                    if(h1%2==0){
                        if(ss[j+9] == '1')
                            jiou = true;
                    }
                    else{
                        if(ss[j+9] == '0')
                            jiou = true;
                    }
                    if(ss[j+10] == '1'&&jiou){
                        System.out.print(a+":");
                        for(int k = j; j < k+8; j++){
                            System.out.print(ss[j+1]);
                        }
                        a++;
                    }
                    else if(ss[j+10] != '1'){
                        System.out.print(a+":");
                        System.out.print("validate error");
                        j += 10;
                        a++;
                    }
                    else if(!jiou){
                        System.out.print(a+":");
                        System.out.print("parity check error");
                        j += 10;
                        a++;
                    }
                    if(j+10<ss.length)
                    System.out.println();
                }

  7-3 String的格式判斷與內容提取主要是判斷字串是否匹配,然後輸出相應的資料,注意要判斷字元陣列的長度是否符合格式和字串中是否有非法輸入,例如輸入中有空格,就可以用一個isSpaceChar()函式判斷資料為WrongFormat,主要是條件判斷,選擇排序輸出。

        for(int k = 0;k < num.length; k++){
            if(Character.isSpaceChar(num[k])){
                found = true;
            }
        }

  第二次題目集主要考查字串,字串廣泛應用 在Java 程式設計中,在 Java 中字串屬於物件,Java 提供了 String 類來建立和操作字串。只要建立了一個String物件,那麼就不能再修改它的值,如果一個操作要修改某個字串的內容或長度,並不能直接做到,而是要返回一個新的String物件,.length()可以獲取字串的長度,StringBuffer類是執行緒安全的可變字元序列,一個類似於String類的字串緩衝區,兩者本質上是一樣的,但StringBuffer比String效率快很多,建立StringBuffer物件必須用關鍵字new,而不能像String物件那樣直接引用字串常量。。

  

題目集3

  第三次作業較前兩次難度大幅度提升,共有三題,主要考察的是類與物件的定義和使用,方法的呼叫和正則表示式的使用,其中也有許多數學的演算法需要去理解和使用,7-1、7-2、7-3都需要建立點的座標,那麼都建立一個類來儲存點的座標,點連成線,線又可以組成不同的形狀,而點與線的關係,點與圖形的關係,線與圖形的關係,每一種都要做出計算,難度大大提升。

  7-1 點線形系列1-計算兩點之間的距離首先輸入點的座標,因為是連貫輸入,所以我把它存入字串中,但是其中有各種符號和空格,例如+2,-2.3 0.9,-3.2,那麼這裡就需要用到replace()split()函式來分割各組資料,先把空格換為逗號,然後統一去除逗號就得到了2個點的座標資料:+2 -2.3 0.9 -3.2,但因為它還是字串型別所以就需要通過Double.parseDouble()函式將字串轉化為double型別數字。

        string = string.replace(" ",",");
        String[] str1 = string.split(",");

建立一個Point類儲存點的座標,然後在類中建立方法Distance計算兩點座標距離。

class Point {
    private double x;
    private double y;

    public Point(double x, double y) {
        super();
        this.x = x;
        this.y = y;
    }
    public Point() {
        super();
    }
    public double Distance(Point p1,Point p2) {
        return Math.sqrt(Math.pow(p1.x-p2.x,2)+Math.pow(p1.y-p2.y,2));
    }
}

在判斷輸入格式非法時,例如++2,-2.3 0.9,-3.2,要用到正則表示式來判斷是否為正確輸入。

boolean strResult = str1[0].matches("-[0-9]+(.[0-9]+)?|[0-9]+(.[0-9]+)?");

  7-2 點線形系列2-線的計算因為有多個點的輸入,那就建立一個Point陣列來儲存所有點的資料,處理輸入的字串資料和7-1大同小異,總共有5個選項,那麼我就在Point類建立相對應的五個方法,通過在main方法中使用switch函式來選擇呼叫哪個方法,若點的數量不對,則輸出wrong number of points,第一個計算斜率比較簡單,用數學的斜率計算公式:(y2-y1)/(x2-x1),第二個計算點到直線的距離,同樣用數學公式去推導,然後將點的座標資料帶入其中,第三個判斷三個點是否在同一條線上,判斷向量(p1-->p2)和向量(p1-->p3)的斜率是否相等。即 (y2-y1)/(x2-x1) == (y3-y1)/(x3-x1).  這個除式判斷可以改寫成乘式判斷:(y3−y1)(x2−x1)−(y2−y1)(x3−x1)=0  (改寫的原因是除法有分母為0或精度等問題,總之乘法更方便!) ,第四個判斷兩條直線是否平行,也是判斷斜率是否相等,第五個計算兩直線的交點座標,用數學公式去推導求交點,然後代入資料。

int options = Integer.parseInt(str1[0]);
switch (options) {
                case 1:
                    if(point[1] != null && point[2] == null)
                        Pnt.Option1(point[0], point[1]);
                    else
                        Pnt.Wrong();
                    break;

                                   判斷兩直線是否平行

if((p1.y-p.y)*(p3.x-p2.x)-(p3.y-p2.y)*(p1.x-p.x) == 0)
{
      System.out.println("true");
}
else
{
      System.out.println("false");
}

                                   計算點到線的距離

 System.out.println(Math.abs(p.x*(p2.y-p1.y)+p.y*(p1.x-2.x)+p2.x* p1.y-p2.y*p1.x)/Math.sqrt(Math.pow(p2.y-p1.y,2)+Math.pow(p1.x-p2.x,2)));                  

                                   計算兩直線的交點

double X = ((p3.x*p2.y-p2.x*p3.y)*(p.x-p1.x)-(p1.x*p.y-p1.y*p.x)*(p2.x-p3.x))/((p1.y-p.y)*(p2.x-p3.x)-(p3.y-p2.y)*(p.x-p1.x));
double Y = ((p1.x*p.y-p1.y*p.x)*(p3.y-p2.y)-(p3.x*p2.y-p2.x*p3.y)*(p1.y-p.y))/((p1.y-p.y)*(p2.x-p3.x)-(p3.y-p2.y)*(p.x-p1.x));

 

 7-3 點線形系列3-三角形的計算框架和7-1大同小異,但其中的計算量更大演算法更難,1.判斷是否是等腰三角形、等邊三角形,2.輸出周長、面積、重心座標,3.輸出是鈍角、直角還是銳角三角形,4.輸出前兩個點所在的直線與三個點所構成的三角形相交的交點數量,5.輸出第一個是否在後三個點所構成的三角形的內部。判斷1主要先通過Distance方法來計算線段長度,然後再通過線段的關係判斷三角形的形狀,輸出2也是先計算線段長度,累加為周長,再通過三角形面積公式計算面積,重心是三個座標的平均值,輸出3通過勾股定理來判斷三角形的形狀,但是出現了問題,因為精度問題,如果是直角三角形,數值不一定完全相等,所以我設定了一個誤差範圍,使結果在範圍內成立,輸出4則比較複雜,我通過intersection方法去判斷線段和另一條線段是否相交,但出現了問題,則是當線段與三角形的交點在頂點時,相當於與兩條線都有交點,實則與三角形只有一個交點,這時我就通過if判斷交點是否為頂點來避免交點重複,輸出5規定要用射線法來判斷點是否在三角形內部,射線法就是做一條從該點出發的射線,當穿過區域邊界的次數為偶數時該點在區域外,如果是奇數則在區域內,原理為一條射線穿過區域的邊界時只有兩種情況:一種是穿入一種是穿出。對於射線來說,只要一次穿入必定對應一次穿出。

                                    判斷是否為鈍角三角形,直角三角形,銳角三角形

            if(Distance(p, p1)==Distance(p1, p2)||Distance(p,p1)==Distance(p,p2)||Distance(p1,p2)==Distance(p,p2))
            {
                isosceles = true;
                if(Distance(p, p1)==Distance(p1, p2)&&Distance(p,p1)==Distance(p,p2)&&Distance(p1,p2)==Distance(p,p2)) {
                    equilateral = true;
                }
            }

                                    計算周長、面積、重心座標

       double a = Distance(p, p1),b = Distance(p, p2),c = Distance(p1, p2);
            double cir = a+b+c, s = cir/2;
            double area = Math.sqrt(s*(s-a)*(s-b)*(s-c));
            double X = (p.x+p1.x+p2.x)/3, Y = (p.y+p1.y+p2.y)/3;

                                    判斷三角形是鈍角、銳角還是直角

       boolean Rui = false, Dun = false, Zhi = false;
            double a = Distance(p, p1),b = Distance(p, p2),c = Distance(p1, p2);
            if(a*a+b*b>=c*c||a*a+c*c>=b*b||b*b+c*c>=a*a)
            {
                Dun = true;
                if(Math.abs(a*a+b*b-c*c)<0.001||Math.abs(a*a+c*c-b*b)<0.001||Math.abs(b*b+c*c-a*a)<0.001){
                    Zhi = true;
                    Dun = false;
                }
            }
            else
            {
                Rui = true;
            }
            System.out.println(Dun+" "+Zhi+" "+Rui);

                                    判斷兩條線段是否相交

    public double intersection(Point p, Point p1, Point p2, Point p3)
    {
        double fC = (p2.y - p.y) * (p.x - p1.x) - (p2.x - p.x) * (p.y - p1.y);
        double fD = (p3.y - p.y) * (p.x - p1.x) - (p3.x - p.x) * (p.y - p1.y);
        return fC * fD;
    }

 

作業總結

踩坑心得

     剛開始我以為前三次的題目集並不會太難,但是結果給我當頭一棒,第一、第二次作業還好,到第三次我直接失去了方向,明顯的掉以輕心,不夠重視Java這門語言,以為和C語言一樣基礎容易學,確實,我掌握的知識還是太少了,以為程式碼能實現功能就行了,不管if多不多,復不復雜,但如果進入社會,這不分分鐘被淘汰嗎,畢竟是我們安身立命的東西,應該把它精雕細琢,能夠簡潔實用,而不是一大堆贅餘的程式碼,讓人難以下眼。這一次題目集過後,也給我敲響了警鐘,混日子是混不過去的,只有潛心鑽研程式設計,不斷地掌握新的知識,提高自己的技能,迎難而上,Java是一門靈活的語言,不花心思在上面是不會獲得收穫的,提前學習,自主學習是十分重要的,筆記本記下老師講的重要內容,多去練習題目,提高自己的程式設計思維和程式碼效率。

收穫

    通過這三次作業的練習,我獲得了很多收穫。
 
  首先,在面向物件程式設計的學習方面,每次作業雖然不需要特別複雜的演算法,但對於我們面向物件程式設計思維和程式設計能力的訓練確有很大幫助。通過短短几周的學習,我們已經能夠用java來實現簡單的面向物件程式,儘管現在寫出的程式可能存在許多問題,但對於我們今後的學習來說無疑具有十分重要的奠基作用。
 
  其次,通過每一次的互測,我看到了許多風格迥異的程式碼。一方面,這些程式碼就像一面鏡子,通過讀其他人的程式碼,我可以從中學習到許多優點和長處,同時也能在對比之下發現自身在編寫程式碼時存在許多問題和不良習慣;另一方面,我也充分認識到擁有一個良好的程式碼風格的重要性,我們今後所寫的程式碼註定要由許多其他人來閱讀和維護,所以決不能寫出只有自己才能讀的懂的程式碼。
 
  最後,我認為我們的面向物件這門課程,不僅僅是訓練我們的程式設計能力,更重要的還是要訓練我們分析各種需求的能力。儘管每一次的指導書都存在許多不夠明確和完善的地方,但是一味的抱怨解決不了任何問題,如何在指導書的字裡行間提煉真正的需求,才是我們每個人應該學習和提高的地方。