1. 程式人生 > 其它 >題目集1-3的總結

題目集1-3的總結

前言:總結三次題目集的知識點、題目量、難度等情況

(1)知識點:1、題目01-7-1 if else的使用;2、題目01-7-2 對於輸出格式的控制;3、題目01-7-3  對於輸入格式的控制;4、題目01-7-4 資料型別強制轉換的使用; 5、題目01-7-5 多層if else 的使用;6、題 目01-7-6 對於函式String.charAt(0)的使用;7、題目01-7-7對於資料存在誤差的控制;8、題目01-7-9 從字串中提取內容;9、題目01-7-9從判斷三角形中瞭解對於一些邊界值的測定;10、題目 02-7- 1將字母轉換為數字;11、題目02-7-2 從二進位制資料流中提取有效資料;12、題目02-7-3 String的格式判斷與內容提取;13、題目03-7-1 用類解決一元二次方程;14、題目03-7-2 設計設  置私有屬性,編寫方法;15、題目03-7-03設計聚合類;16題目03-7-4設計聚合類;

題量:題目集1:9題;題目集2:3題;題目集3:4;

難度:題目集1:容易;題目集2:容易;題目集3:中難;

(2)設計與分析

<1>強制轉換隻需要在資料前面所需要轉換的方式例:a = (float )weight;

輸出的方式與c語言不同,c中使用printf("        ");可以實現將空格插入的內容一同輸出,在JAVA需要使用“+”,輸出所需要的格式

bang=(float) (weight/0.45359237);
yingcun=(float) (high/0.0254);
System.out.println(bang+" "+yingcun);

<2>定義陣列:存在與c語言不同的方式,在c中,使用 int a[10];JAVA中的定義方式存在區別

int num[] = new int [10];

<3>提取字串中的單個字元

在JAVA中可以提取單獨的字元,以下的例子中,定義了一個學生的學號,通過String.charAt(1),就可以提取出第二個字元

String StudentNumber ="18201123";
char a = StudentNumber.charAt(1);

<4>題目字母-數字轉換

題目要求:實現輸入一個由英文字母組成的字串(大小寫均可),將所有英文字母轉換成它們在字母表中的序號,例如:“AbbcD”轉換為“12234”

輸入格式:由英文字母組成的字串(大小寫均可)。例如:“AbbcD”
     若包含非英文字母,視為非法輸入。

輸出格式:由英文字母組成的字串(大小寫均可)。例如:“AbbcD”
     若包含非英文字母,視為非法輸入。

設計思路:拒絕複雜的思路,將一個個的賦值(使用if將A和a轉變成需要的數字)轉換成使用ASCII表,可以達到按順序實現值的轉換;使用a.length();函式可以測試出字串的長度

踩坑心得:使用in.nextLine()好過於in.next(); in.next無法輸入空格,所以對於非法輸入的判斷的測試點會無法通過

import java.util.Scanner;
public class Main {
public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int a,i,j,num;
        num=0;
//        int num[]=new int[26];
        String s = new String();
        s = in.nextLine();
        a=s.length();
        for(i=0;i<a;i++) {
            if((s.charAt(i)>='a'&&s.charAt(i)<='z')||(s.charAt(i)>='A'&&s.charAt(i)<='Z')) {
                num++;
            }
            else {
                System.out.println("Wrong Format");
                break;
            }
        }
        if(i==a) {
            for(j=0;j<a;j++) {
                if(s.charAt(j)>='a'&&s.charAt(j)<='z') {
                    num=s.charAt(j)-96;
                    System.out.print(num);
                }
                if(s.charAt(j)>='A'&&s.charAt(j)<='Z') {
                    num=s.charAt(j)-64;
                    System.out.print(num);
                }
            }
        }
    }
}

<5>題目-串列埠字元解析

題目要求:RS232是串列埠常用的通訊協議,在非同步通訊模式下,串列埠可以一次傳送5~8位資料,收發雙方之間沒有資料傳送時線路維持高電平,相當於接收方持續收到資料“1”(稱為空閒位),傳送方有資料傳送時,會在有效資料(5~8位,具體位數由通訊雙方提前設定)前加上1位起始位“0”,在有效資料之後加上1位可選的奇偶校驗位和1位結束位“1”。請編寫程式,模擬串列埠接收處理程式,注:假定有效資料是8位,奇偶校驗位採用奇校驗。

輸入格式:由0、1組成的二進位制資料流。例如:11110111010111111001001101111111011111111101111、

輸出格式:所有英文字母轉換成它們在字母表中的序號,例如:“12234”。
     非法輸入輸出"Wrong Format".

設計思路:1:控制字元數量,實現多個字元一組,排除一個一個容錯複雜的判斷,本題需要判斷的資料可以設計成11位為一組

if(a<11)
    System.out.println("null data");
else if(a>=11) {//進行正確內容所需要的判斷
}

       2:當字串的長度超過11位時,採用迴圈的方式實現每個字元的判斷,首先需要找到0,所在的位置

for(i=0;i<a;i++) {
    if(s.charAt(i)=='0'&&a-i<11) {
        System.out.println("null data");
        break;
       }
    if(s.charAt(i)=='0'&&a-i>=11)
        break;
    if(s.charAt(i)!='0'&&i==a-1) {
        System.out.println("null data");
        break;
    }
}    

    3:在0的後面分部查詢:第一步:計算1的個數(以便最後進行奇偶校驗);第二步:判斷最後的一個是否為1(判斷是否為有效資料);第三步:判斷奇偶校驗;第四步:對於前面最後一位和奇偶校                        驗可以進行計數,這樣在最後的一步進行判斷內容是不是為有效資料的時候,存在巨大作用;

踩坑心得:判斷結束符的時候,沒有計數,導致最後判斷不正確

if(s.charAt(j+1)!='1')//結束符號不是1//這裡是錯誤程式碼,沒有計數導致的錯誤
    System.out.println("validate error");
if((odd%2==0&&s.charAt(j)=='0'&&s.charAt(j+1)=='1')||odd%2!=0&&s.charAt(j)=='1'&&s.charAt(j+1)=='1'))
    System.out.println("parity check error"); 
if(s.charAt(j+1)!='1')//結束符號不是1{//這裡是正確程式碼
    pos++;
    System.out.println(pos+":validate error");
}
if((odd%2==0&&s.charAt(j)=='0'&&s.charAt(j+1)=='1')||(odd%2 !=0&&s.charAt(j)=='1'&&s.charAt(j+1)=='1'){
    pos++;
    System.out.println(pos+":parity check error");
}

但是這並沒有正確,這裡出現了一個難以察覺的問題,對於,所用的開頭沒有重新賦值為0,導致長時間無法正確所以在結尾需要將odd變數重新賦值為0;以下是原始碼,寫的不好僅供瀏覽一下,剛開始還不會使用Debug,所以在裡面用使用了以下輸出一個 i 的值,這樣就達到了當前值檢視(新手使用),但是,推薦去上網查閱以下Debug的使用方法,Debug特別好用,可以一步一步的走,很快的判斷出你的錯誤點

import java.util.Scanner;



public class Main {
public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        int a,i,pos=0,j,odd=0;
        String s = new String();
        s=in.nextLine();
        a=s.length();
        if(a<11)
            System.out.println("null data");
        if(a>=11) {
            for(i=0;i<a;i++) {
                if(s.charAt(i)=='0'&&a-i<11) {
                    System.out.println("null data");
                    break;
                }
                if(s.charAt(i)=='0'&&a-i>=11)
                    break;
                if(s.charAt(i)!='0'&&i==a-1) {
                    System.out.println("null data");
                    break;
                }
            }
            for(i=0;i<a;i++) {
                if(s.charAt(i)=='0'&&a-i>=11) 
                {
        //            System.out.print(i);
                        for(j=i+1;j<i+9;j++) {//尋找1的個數
                            if(s.charAt(j)=='1')
                                odd++;
                        }
            //            System.out.print(j);
                        
                        if((odd%2==0&&s.charAt(j)=='1'&&s.charAt(j+1)=='1')||(odd%2!=0&&s.charAt(j)=='0'&&s.charAt(j+1)=='1')) {//正確的情況
                            pos++;
                            System.out.print(pos+":");
                            for(i=i+1;i<j;i++)
                            System.out.print(s.charAt(i));
                            System.out.printf("\n");
                        }
                //        System.out.print(i);
                        i=j+1;
                        if(s.charAt(j+1)!='1')//結束符號不是1
                        {
                            pos++;
                            System.out.println(pos+":validate error");
                        }
                            
                        if((odd%2==0&&s.charAt(j)=='0'&&s.charAt(j+1)=='1')||(odd%2!=0&&s.charAt(j)=='1'&&s.charAt(j+1)=='1'))
                        {
                            pos++;
                            System.out.println(pos+":parity check error");
                        }
                    odd=0;
                }
            }        
        }
    }
}
View Code

 

<6>String的格式判斷與內容提取

題目要求:學校學生學號格式定義如下:
2位年級號+2位學院號+2位班級號+2位序號,如19041103,
編寫程式處理用全院學生學號連線起來的長字串,學院編號為20,包括17、18、19、20四個年級,請從字串中提取特定兩個班級202017班、202061班同學的學號後四位輸出,輸出編號之間用空格分隔,不換行。
注意:需要排除非法輸入。

輸入格式院學生學號組成的長字串(學號之間無分隔)
學號格式定義如下:
2位年級號+2位學院號+2位班級號+2位序號,如19041103

輸出格式:

特定兩個班級202017班、202061班同學的學號後四位
如:1701 6103 1704

設計思路:第一步:對於字元長度的判定,字元長度的界限是8;第二步:尋找需要的學號;以下是原始碼:

View Code

踩坑心得:剛開始沒有對格式進行控制,結尾存在空格,需要刪除,改進措施:如果是第一個就先輸出數字,後面每一個都輸出“ +數字”這樣是一個控制輸出格式的方法

if(pos==1)                            
    System.out.print("61"+s.charAt(i+6)+s.charAt(i+7));
else {
    System.out.print(" ");
    System.out.print("61"+s.charAt(i+6)+s.charAt(i+7)); 
}

開始的時候,認為迴圈時一組學號一組學號進行的,導致,自己誤以為是i= i+8;導致存在一個錯誤:合法輸入,且其中兩個連續學號錯位組合成一個合乎條件的學號。

,經過更改後,將原來的i = i+8;更改成i= i+1;就可以按照順尋,一個一個的判斷,實現錯位連續學號的排除

<7>題目-7-1 用類解一元二次方程式 

題目要求:定義一個代表一元二次方程ax2+bx+c=0的類QuadraticEquation,其屬性為三個係數a、b、c(均為私有屬性),類中定義的方法參考main方法中的程式碼。main方法原始碼:

注意:須提交完整原始碼,包括Main類。

輸入格式:在一行中輸入a、b、c的值,可以用一個或多個空格或回車符分開。

輸出格式:當輸入非法時,輸出“Wrong Format”

     當有一個實根時,輸出(2行):

     a=值,b=值,c=值:

     The root is 值(保留兩位小數)

     當有兩個實根時,輸出(2行):

     a=值,b=值,c=值:

     The roots are 值1 and 值2(均保留兩位小數)

設計思路:使用get和set函式以及構造方法即可;再使用正常的求根公式即可;

踩坑心得:對於公式差不多,只有一些個別的資料沒有改變的,複製貼上的時候,很容造成符號的錯誤,導致隱藏的錯誤難以被發現,推薦,在使用相同的格式的時候注意對個別內容的修改。注意這裡的root1和root2的式公相同,會導致錯誤,所以,需要將內容以下就可以得到正確結果

public double getRoot1() {
        root1 = (-b+Math.pow(deita, 0.5))/2*a;
        return root1;
} public double getRoot2() { root2 = (-b+Math.pow(deita, 0.5))/2*a;//注意這裡的root2和root1的內容相同,導致了錯誤 return root2; }

以下是正確原始碼:

import java.util.Scanner;

public class Main {
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);

        double a = Double.parseDouble(input.next());
        double b = Double.parseDouble(input.next());
        double c = Double.parseDouble(input.next());
        //------------------輸入三個值-----------
        if(a == 0){
            System.out.println("Wrong Format");
            System.exit(0);
        }
        
        //create a QuadraticEquation object
        QuadraticEquation equation = new QuadraticEquation(a, b, c);//順便將值傳輸下去
        
        double discriminant = equation.getDiscriminant();//get value of b * b - 4 * a * c
        //存在返回值
        System.out.println("a=" + equation.getA() +
                ",b=" + equation.getB() + 
                ",c=" + equation.getC()+":");

        if (discriminant < 0) {
          System.out.println("The equation has no roots.");
        }
        else if (discriminant == 0)
        {
          System.out.println("The root is " + 
                  String.format("%.2f", equation.getRoot1()));
        }
        else // (discriminant >= 0)
        {
          System.out.println("The roots are " + 
                  String.format("%.2f", equation.getRoot1()) 
            + " and " +  String.format("%.2f", equation.getRoot2()));
        }
    }
}
//有getDiscriminant()--   b * b - 4 * a * c          
//getB() --返回a,b,c的值
//getRoot1()--返回根的值        getRoot2()
class QuadraticEquation{
        //your code
    private double a = 0;
    private double b = 0;
    private double c = 0;
    private double deita = 0;
    private double root1 = 0;
    private double root2 = 0;

    public QuadraticEquation() {
        super();
        // TODO 自動生成的建構函式存根
    }
    
    public QuadraticEquation(double a, double b, double c) {
        super();
        this.a = a;
        this.b = b;
        this.c = c;
    }

    
    public double getA() {
        return a;
    }

    public void setA(double a) {
        this.a = a;
    }

    public double getB() {
        return b;
    }

    public void setB(double b) {
        this.b = b;
    }

    public double getC() {
        return c;
    }

    public void setC(double c) {
        this.c = c;
    }
    public double getDiscriminant() {
        deita = b * b - 4 * a * c;
        return deita;
    }
    public double getRoot1() {
        root1 = (-b+Math.pow(deita, 0.5))/2*a;
        return root1;
    }
    public double getRoot2() {
        root2 = (-b-Math.pow(deita, 0.5))/2*a;
        return root2;
    }
}
View Code

<8> 日期類設計 

題目要求:參考題目集二中和日期相關的程式,設計一個類DateUtil,該類有三個私有屬性year、month、day(均為整型數),其中,year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] , 除了建立該類的構造方法、屬性的getter及setter方法外,需要編寫如下方法:

public boolean checkInputValidity();//檢測輸入的年、月、日是否合法
public boolean isLeapYear(int year);//判斷year是否為閏年
public DateUtil getNextNDays(int n);//取得year-month-day的下n天日期
public DateUtil getPreviousNDays(int n);//取得year-month-day的前n天日期
public boolean compareDates(DateUtil date);//比較當前日期與date的大小(先後)
public boolean equalTwoDates(DateUtil date);//判斷兩個日期是否相等
public int getDaysofDates(DateUtil date);//求當前日期與date之間相差的天數
public String showDate();//以“year-month-day”格式返回日期值

應用程式共測試三個功能:

求下n天

求前n天

求兩個日期相差的天數 

設計思路:第一步:先判斷年月日是否符合要求的範圍,年裡面有月,月裡面有日,迴圈判斷,對於閏年和平年,我們可以單獨建立一個方法,以便在判斷2月的天數的時候,通過判斷是閏年還是平年的方法返回一個boolean型別的值,進行結合判斷即可;第二步:上n天與下n天的計算方法類似(注意對於大資料的考慮,不能僅看一位數或者兩位數的天數,要考慮很大的天數),所以我們通過以年為一組迴圈的方式,最後剩餘的小於366天的時候,進行判斷。第三步:設定換月時要設定的最大天數和最小天數,例如:5月1日的上一天時4月30日,6月1日的上一天時5月31日,對於不同的天數,需要進行設定特殊值需要優先考慮,例如閏年的2月和平年的2月是不一樣的,還有存在跨年的現象,都需要考慮。第四步:設計相差的天數:可以採用引入第三點的方式來計算差值,這樣設計會方便很多

踩坑心得:執行容易超時;當設計為按照每一天來進行判斷當前執行時的天數時,如果資料很大,就會導致執行超時,需要修改演算法;這個屬於優化演算法,非常有必要。對於是否剩餘365天,還是366天,不用管,直接設定最大就可以實現,不用考慮太大

int i,count=0,max=0,newNum,max1=0;
        newNum=0;
        if(month==4||month==6||month==9||month==11)
            max=30;
        if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
            max=31;
        if(month==2&&isLeapYear(year)==false)
            max=28;
        if(month==2&&isLeapYear(year)==true)
            max=29;
        if(month==1||month==4||month==6||month==8||month==9||month==11||month==2)
            max1=31;
        if(month==5||month==7||month==10||month==12)
            max1=30;
        if(month==3&&isLeapYear(year)==false)
            max1=28;
        if(month==3&&isLeapYear(year)==true)
            max1=29;
            count=1;newNum=n;
            for(i=0;i<newNum;i++)
            {
                day=day+count;
                if(day>max)
                {    
                    if(month==4||month==6||month==9||month==11)
                        max=30;
                    if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
                        max=31;
                    if(month==2&&isLeapYear(year)==false)
                        max=28;
                    if(month==2&&isLeapYear(year)==true)
                        max=29;
                    if(month==1||month==4||month==6||month==8||month==9||month==11||month==2)
                        max1=31;
                    if(month==5||month==7||month==10||month==12)
                        max1=30;
                    if(month==3&&isLeapYear(year)==false)
                        max1=28;
                    if(month==3&&isLeapYear(year)==true)
                        max1=29;
                    day=1;month=month+1;
                    if(month==13)
                    {
                        month=1;year=year+1;
                    }        
                }
日迴圈

這裡執行一次需要4000ms,僅開啟,就需要很長時間,所以演算法就很複雜,進一步改進:可以提供兩種思路1、直接通過月迴圈就比驕快,也可以通過年迴圈,但是年迴圈需要分別討論再3月前,還是在3月後,這樣的考慮情況會多一點,但是執行的速度就會快很多

for(;n>=366;) {
            if((isLeapYear(year)==true)&&(month!=2&&day!=29)&&(month<3)) {
                n = n-366;
                year = year+1;
            }
            else if((isLeapYear(year)==true)&&(month>=3)){
                n = n-365;
                year = year+1;
            }
            else if((isLeapYear(year)==true)&&(month==2&&day==29)) {
                n = n-366;
                year = year+1;
                month = 3;day = 1;
            }
            else if((isLeapYear(year)==false&&isLeapYear(year+1)==true)&&(month!=2&&day!=28)&&(month<3)) {
                n = n-365;
                year = year+1;
            }
            else if((isLeapYear(year)==false&&isLeapYear(year+1)==true)&&month>=3) {
                n = n-366;
                year = year+1;
            }
            else if(isLeapYear(year)==false&&isLeapYear(year+1)==false) {
                n = n-365;
                year = year +1;
            }
        }
        if(n<=366) {
            int i,count=0,max=0,newNum,max1=0;
            newNum=0;
                count=1;newNum=n;
                for(i=0;i<newNum;i++)
                {
                    if(month==4||month==6||month==9||month==11)
                        max=30;
                    if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
                        max=31;
                    if(month==2&&isLeapYear(year)==false)
                        max=28;
                    if(month==2&&isLeapYear(year)==true)
                        max=29;
                    day=day+count;
                    if(day>max)
                    {    
                        day=1;month=month+1;
                        if(month==13)
                        {
                            month=1;year=year+1;
                        }        
                    }
                }
        }
年迴圈

如果實現了下n天的迴圈,那麼上n天的也可以採用同樣的方法來實現,類推一下就可以。

在這裡我們可以設計一個DateUtil的類,通過在這個類中,設計出多種方法,每種方法都存在不同的get 和set 的方法,就可以返回所需要的值。

<8>日期問題面向物件設計(聚合一)

參考題目7-2的要求,設計如下幾個類:DateUtil、Year、Month、Day,其中年、月、日的取值範圍依然為:year∈[1900,2050] ,month∈[1,12] ,day∈[1,31]、

設計思路:可以從末尾開始設計,先設計年的類,再從年開始到月再到日,返回到DateUtil 返回到main.每一個類中都設有value++ 和value -- ;這樣產生的資料就不會魚龍混雜,結果更加清晰

上一題中的DateUtil是包含了所有的方法,這次設計中,需要將判斷年月日的方法,放在Year類中.判斷日期是否合理的的方法也進行了更改,分別放在了不同的裡面,每一個都單獨進行判斷,各司其職,思路清晰,這是一種面向物件的寫法。

踩坑心得:對於剛接觸Java來說,建立這個類的時候,很多東西還是不明確,在這裡,建立了一個day的類,相當於存在了day中所有的東西,這樣實現環環相扣,大膽去下手,不要出現重複的使用程式碼,直接建構函式實現,這樣既不會導致公式錯誤,也容易檢查出你犯的錯誤

改進建議:對於這個程式來說,其中的耦合度還是很高,他存在了每一環與另外一環相扣的設計,這是不好的,我們需要存在一個控制類將每一個類都控制住,這樣就可以實現單一職責的原則,實現更加低的耦合度

總結:對於以上三次題集,讓我收穫很多,從一開始的對於JAVA的很多語法不熟悉,到現在已經掌握了不少,尤其是字串的應用,學會了很多,基本的定義陣列不同,輸入輸出不同,尤其是同時又printf和println讓我頭暈,對於字串JAVA有很多特別大函式,比如String.charAt(i)可以實現字串中單獨字元的提取,Character.isDigit()可以判斷輸入字串中單獨的一個內容是不是數字,再比如還有Double.valueof函式可以實現將字串中數字轉換成double1型別的數字,substring函式可以將字串中的一部分提取出來,他比charAt(i)強在可以提取多個內容。對於面向物件設計的內容,學習到了一些單一職責的原則,方法的設計與c語言中的函式很像,需要自己揣摩一下,以上便是我從中學到的內容。需要改進的方面,在這段時間的學習中,還有很多語法知識的空白,還需要從實踐中找到,奪取磨練,對於面向物件的設計,現在自己做的還是非常不好,寫的程式碼,還是和以前的c語言的寫法相似,導致程式碼內容不清晰,很拖拉,沒有實現單一職責的原則,需要很多的改進,還有一個很大問題就是程式碼書寫的格式規範程度還是很差,總是亂七八糟的,駝峰命名法,現在有些注意,還有很多的規範書寫沒有寫好,以後需要慢慢加油。對於這幾次題集,雖然最後一次的習題很難,很難受,但是效果還是很好的,慢慢堅持下去,哪怕一開始做的不好,但是經過磨練,會好起來的,加油!