第二章 基本程序設計


@

課本筆記 第二章

算法描述的是:如果要解決一個問題,所需要執行的動作以及這些動作的執行順序。算法可以幫助程序員在使用程序設計語言編寫程序之前進行規划。算法可以用自然語言或者偽代碼(即自然語言和程序設計代碼混在一起使用)描述。

  • 編寫程序涉及如何設計解決問題的策略,以及如何應用編程語言實現這個策略。
  • 在編寫代碼之前,以算法的形式來勾勒你的程序(或者潛在的問題),是一個很好的做法。
  • 每個 Java 程序都是一個類的聲明開始
  • 在程序中需要聲明一個稱作變量的符號。變量代表存儲在計算機內存中的一個值
  • 變量名應該盡量選擇描述性的名字(descriptive name)
  • 為了讓編譯器知道radius 和area是什么,需要指明它們的數據類型(Data Type),即存儲在變量中的數據的類型是整數、實數或者其他。這稱之為聲明變量

程序清單 2-1 ComputeArea.java

public class ComputeArea {
    public static void main(String[] args) {
        double radius, area;//Declare variable  聲明變量
        //Assign a radius  分配一個半徑值
        radius = 20;
        //Compute area  計算面積
        area = radius * radius * 3.14159;
        //Display results  顯示結果
        System.out.println("The area for the circle of radius " + radius
                + " is " + area);
    }
}

加號(+)的用途:

  • 是做加法
  • 稱為字符串連接符,將兩個字符串合並為一個

在源代碼中,字符串常量不能跨行

從控制台讀取輸入

  • 使用Scanner類從控制台輸入
  • Java使用System.out來表示標准輸出設備,用System.in來表示標准輸入設備
Scanner input = new Scanner(System.in)

語法new Scanner(System.in) 表明創建了一個 Scanner 類型的對象。語法 Scanner input 聲明 input 是一個Scanner 類型的變量。整行的 Scanner input = new Scanner(System.in) 表明創建了一個Scanner 對象,並且將它的引用值賦給變量 input 。對象可以調用其方法。調用對象的方法就是讓這個對象執行某個任務。可以調用nextDouble()方法來讀取一個double值,如下所示:

double radius = input.nextDouble();

程序清單 2-2 ComputeArea.java

import java.util.Scanner;

public class ComputeAreaWithConsoleInput {
    public static void main(String[] args) {
        //Create a Scanner object  創建Scanner類對象
        Scanner input = new Scanner(System.in);
        //Prompt the user to enter a radius  提示用戶輸入
        System.out.print("Enter a number for radius: ");
        double radius = input.nextDouble();
        //Compute area  計算面積
        double area = radius * radius * 3.14159;
        //Display results  顯示結果
        System.out.println("The area for the circle of radius "
                + radius + " is " + area);
    }
}

Scanner類位於java.util包中,在第1行導入。第6行創建了一個Scanner對象。注意,如果第6行用java.util.Scanner 代替Scanner 的話,import 語句可以省略。

第9行的語句在控制台顯示字符串“Enter a number for radius: ”這稱之為提示,因為它指導用戶鍵入輸入。程序應該在希望得到鍵盤輸入的時候,告訴用戶輸入什么

println會將光標移到下一行,而print不會將光標移到下一行。

第6行創建了一個Scanner對象。第10行的語句從鍵盤讀入一個輸入。

double radius = input.nextDouble( );

在用戶鍵入一個數值然后按回車鍵之后,該數值就被讀入並賦值給radius。

Scanner類在包 java.util 里。它在第1行被導入。由兩種類型的 import 語句:明確導入(specific import )和通配符導入(wildcard import)。明確導入是在import語句中指定單個類。例如,下面的語句就是從包 java.util 中導入Scanner。

通配符導入是指通過使用*號作為通配符,導入一個包中所有的類。例如,下面的語句導入包java.util 中所有的類。

import java.util.*;

程序清單 2-3 ComputeAverage.java

import java.util.Scanner;

public class ComputeAverage {
    public static void main(String[] args) {
        //Create a Scanner object  創建Scanner類對象
        Scanner input = new Scanner(System.in);
        //Prompt the user to enter three numbers  提示用戶輸入三個數
        System.out.print("Enter three numbers: ");
        double number1 = input.nextDouble();
        double number2 = input.nextDouble();
        double number3 = input.nextDouble();
        //Compute average  計算平均值
        double average = (number1 + number2 + number3);
        //Display results  顯示結果
        System.out.println("The average of " + number1 + " " + number2
                + " " + number3 + " is " + average);
    }
}
  • 本書前面章節中的大多數程序分三個步驟執行,即輸入、處理和輸出,這被稱為IPO。輸入是從用戶獲得輸入,處理是使用輸入產生結果,而輸出是顯示結果。
  • 如果使用諸如Eclipse 或者NetBean之類的 IDE ,會提示你關閉輸入以防止可能的資源泄漏。現在先忽略警告,因為程序結束時輸入將自動關閉。這種情況下不會有資源泄漏

標識符(Identifier)的命名規則

  • 標識符由數字、字母、下划線和美元符號$構成的字符序列
  • 標識符必須以字母、下划線或美元符號$開頭,不能以數字開頭
  • 標識符不能是保留字
  • 標識符不能是true、false或null
  • 標識符可以為任意長度

注意:由於 Java 是區分大小寫的,所以area、Area、AREA是不同的標識符

  • 提示:標識符用於命名程序中的變量、方法、類和其他項。具有描述性的標識符可提高程序的可讀性。避免采用縮寫作為標識符,使用完整的詞匯會更具有描述性。比如,numberOfStudents比numStuds、numOfStuds或者numOfStudents要好。本教材中我們在完整的程序采用描述性的命名。然而,為了簡明起見,我們也會偶爾在一些代碼片段中采用諸如 i,j,k,x和y之類的變量名。這樣的命名在代碼片段中也是具有一定普遍性的做法。
  • 不要用字符 $ 命名標識符。習慣上,字符 $ 只用在機器自動產生的源代碼中。(內部類)

變量

  • 變量用於表示在程序中可能被改變的值
  • 變量聲明通知編譯器根據數據類型為變量分配合適的內存空間
  • 在賦值給變量之前,必須聲明變量。方法中聲明的變量在使用之前必須被賦值。盡量一步完成變量的聲明和賦初值。這會使得程序易讀,同時避免程序設計錯誤
  • 一個變量在可以使用前,必須被聲明和初始化

賦值語句和賦值表達式

  • 變量在聲明之后,可以使用賦值語句(assignment statement)給它賦一個值。在 Java 中,將等號(=)作為賦值操作符(assignment operator )
variable = expression; (變量 = 表達式;)

表達式(expression)表示包含值、變量和操作符的一次計算,它們組合在一起得出一個新值。

變量名必須在賦值操作符的左邊。

  • 在數學運算中,x = 2 * x + 1表示一個等式。但是,在 Java 中, x = 2 *x +1 是一個賦值語句,它計算表達式 2 *x +1的值,並且將結果賦給 x。

在 Java 中,賦值語句本質上就是一個表達式,該表達式的值是賦給賦值操作符左邊變量的值。由於這個原因,賦值語句也稱為賦值表達式(assignment expression )

  • 在賦值語句中,左邊變量的數據類型必須與右邊值的數據類型兼容。例如,int x = 1.0 是非法的,因為x 的數據類型是整型int。在不使用類型轉換的情況下,是不能把double 值(1.0)賦給int 變量的。

命名常量

  • 命名常量(named constant)是一個代表不變值的標識符
final datatype CONSTANTNAME = value;

程序清單 2-4 ComputeAreaWithCOnstant.java

import java.util.Scanner;

public class ComputeAreaWithConstant {
    public static void main(String[] args) {
        final double PI = 3.14159;//Declare a constant  聲明常量
        //Create a Scanner object  創建Scanner類對象
        Scanner input = new Scanner(System.in);
        //Prompt the user to enter a radius  提示用戶鍵入半徑值
        System.out.print("Enter a number for radius: ");
        double radius = input.nextDouble();
        //Compute area  計算面積
        double area = radius * radius * PI;
        //Display result  顯示結果
        System.out.println("The area for the circle of radius "
                + radius + " is " + area);
    }
}

命名習慣

  • 嚴格遵循 Java 的命名習慣可以讓你的程序易於理解,並且能避免錯誤
  • 使用小寫字母命名變量和方法,例如,變量radius和area以及方法print。如果一個命名包含多個單詞,就將它們連在一起,第一個單詞的字母小寫,而后面每個單詞的首字母大寫。例如,變量numberOfStudents。這種命名風格稱為駝峰命名法,因為名字中的大寫字符類似於駱駝的駝峰
  • 類名中的每個單詞的首字母大寫,例如,類名ComputeArea和System
  • 常量中的所有字母大寫,兩個單詞間用下划線連接,例如,常量PI和常量MAX_VALUE
  • 命名類時不要選擇Java庫中已經使用的名稱。例如,因為Java已定義了System類,就不要用System來命名自己的類

數值數據類型和操作

  • Java針對整數和浮點數由六種數值類型,以及+、-、*、/和%等操作符

    表 2-1 數值數據類型
類型名 范圍 存儲空間
byte -27 (-128) ~ 27-1 (127) 8位帶符號數
short -215 (-32768) ~ 215-1 (32767) 16位帶符號數
int -231 (-2 147 483 648) ~ 231-1 (2 147 483 647) 32位帶符號數
long -263 (-9 223 372 036 854 775 808) ~ 263-1 (9 223 372 036 854 775 807) 64位帶符號數
float 負數范圍:-3.4028235E+38 ~ -1.4E-45 正數范圍:1.4E-45 ~ 3.4028235E+38 32位,標准IEEE 754
double 負數范圍:-1.7976931348623157E+308 ~ -4.9E-324 正數范圍:4.9E-324 ~ 1.7976931348623157E+308 64位,標准IEEE 754
  • IEEE 754 是美國電氣電子工程師協會通過的標准,用於在計算機上表示浮點數。該標准已被廣泛采用。Java采用32位IEEE 754 表示float型。64位IEEE 754 表示double型。IEEE 754 標准還定義了一些特殊浮點值。

  • double又稱為雙精度(double precision),而float稱為單精度(single precision)

    表 2-2 Scanner對象的方法
方法 描述 方法 描述
nextByte() 讀取一個byte類型的整數 nextLong() 讀取一個long型的整數
nextShort() 讀取一個short類型的整數 nextFloat() 讀取一個float類型的數
nextInt() 讀取一個int類型的整數 nextDouble() 讀取一個double類型的數
表 2-3 數值操作符
運算符 名字 示例 運算結果 運算符 名字 示例 運算結果
+ 34 + 1 35 / 1.0 / 2.0 0.5
- 34.0 -0.1 33.9 % 求余 20 % 3 2
* 300 * 30 9000
  • 操作符%被稱為求余或者取模操作符,可以求得除法的余數
  • 操作符%通常用在正整數上,實際上,它也可用於負整數和浮點值。只有當被除數是負數時,負數才是負的

程序清單 2-5 DisplayTime.java

import java.util.Scanner;

public class DisplayTime {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        //Prompt the user for input  提示用戶輸入
        System.out.print("Enter an integer for seconds: ");
        int seconds = input.nextInt();

        int minutes = seconds / 60;//Find minutes in seconds  以秒計算分
        int remainingSeconds = seconds % 60;//Seconds remaining  剩余的秒數
        System.out.println(seconds + " seconds is " + minutes +
                " minutes and " + remainingSeconds + " seconds");
    }
}

數值型字面值

  • 字面值(literal)是程序中直接出現的常量值

整型字面值

  • 默認情況下,整形字面值是一個十進制整數。要表示一個二進制整數字面值,在數字前使用0b 或者 0B(零B);要表示一個八進制整數字面值,在數字前使用0(零);而要表示一個十六進制整數字面值,在數字前使用0x或0X(零x).
  • 為了提高可讀性,Java允許在一個數值型字面值的兩個數字間使用下划線。

科學計數法

  • float型和double型都是用來表示帶有小數點的數。為什么把它們稱為浮點數呢?因為這些數在計算機內部都是以科學計數法的形式進行存儲的。當一個像50.534的數被轉換成科學記數法的形式時,它就是5.0534E+1,它的小數點移到(即浮動到)一個新的位置。

表達式求值以及操作符優先級

  • Java表達式的求值和數學表達式求值是一樣的
  • 圓括號可以嵌套,嵌套時先計算內層括號
  • 操作符的優先級規則
    • 首先計算乘法、除法和求余運算。如果表達式中包含若干個乘法、除法和求余操作符,可按照從左到右的順序執行
    • 最后執行加法和減法運算。如果表達式中包含若干個加法和減法操作符,則按照從左到右的順序執行

程序清單 2-6 FahrenheitToCelsius.java

import java.util.Scanner;

public class FahrenheitToCelsius {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Enter a degree in Fahrenheit: ");
        double fahrenheit = input.nextDouble();
        //Convert Fahrenheit to Celsius
        double celsius = (5.0 / 9) * (fahrenheit - 32);
        System.out.println("Fahrenheit " + fahrenheit + " is " +
                celsius + " in Celsius");
    }
}

顯示當前時間

  • 可以通過調用System.currentTimeMillis()返回當前時間
  • GMT(格林尼治標准時間)1970年1月1日00:00:00開始到當前時刻的毫秒數

程序清單 2-7 ShowCurrentTime.java

public class ShowCurrentTime {
    public static void main(String[] args) {
        //Obtain the total milliseconds since midnight, Jan 1, 1970
        //獲取自1970年1月1日午夜以來的總毫秒數(格林尼治時間)
        long totalMillliseconds = System.currentTimeMillis();
        //Obtain the total seconds since midnight, Jan 1, 1970
        //獲取自1970年1月1日午夜以來的總秒數
        long totalSeconds = totalMillliseconds / 1000;
        //Compute the current second in the minute in the hour
        //計算-小時中-分鍾中-的當前秒數
        long currentSecond = totalSeconds % 60;
        //Obtain the total minutes  獲取總分鍾數
        long totalMinutes = totalSeconds / 60;
        //Compute the current minute in the hour
        //計算小時中的當前分鍾
        long currentMinute = totalMinutes % 60;
        //Obtain the total hours  獲取總小時數
        long totalHours = totalMinutes / 60;
        //Compute the current hour  計算當前小時
        long currentHour = (totalHours % 24) + 8;
        //中國是東八區,加8表示中國當地時間,% 做取整處理。這里不顯示具體的年月日
        //Display results  顯示結果
        System.out.println("Current time is " + currentHour + ":"
                + currentMinute + ":" + currentSecond + " GMT");
    }
}

增強賦值操作符

  • 操作符+、-、*、/、%可以結合賦值操作符形成增強操作符

    表 2-4 簡捷賦值操作符
操作符 名稱 示例 等價於
+= 加法賦值操作符 i+=8 i = i + 8
-= 減法賦值操作符 i-=8 i = i - 8
*= 乘法賦值操作符 i*=8 i = i * 8
/= 除法賦值操作符 i/=8 i = i / 8
%= 求余賦值操作符 i%=8 i = i % 8
  • 在增強操作符中是沒有空格的
  • 就像賦值操作符(=)一樣,操作符(+=、-=、*=、/=、%=)既可以構成賦值語句也可以構成賦值表達式。例如,在下面的代碼中,第1行的x += 2是一條語句,而在第2行中它就是一個表達式

自增和自減操作符

  • 自增操作符(++)和自減操作符(--)對變量進行加1和減1的操作

    表 2-5 自增和自減操作符
操作符 名稱 描述 示例(假設i=1)
++var 前置自增 將var加1,在語句中使用新的var值 int j = ++i;//j is 2,i is 2
var++ 后置自增 將var加1,但是在語句中使用原來的var值 int j = i++;//j is 1,i is 2
--var 前置自減 將var減1,在語句中使用新的var值 int j = --i;//j is 0,i is 0
var-- 后置自減 將var減1,但是在語句中使用原來的var值 int j = i--;//j is 1,i is 0
  • 使用自增操作符和自減操作符可以使表達式更加簡短,但也會使它們比較復雜且難以讀懂。應該避免在同一個表達式中使用這些操作符修改多個變量或多次修改同一個變量,如int k = ++i + i*3。

數值類型轉換

  • 通過顯示轉換,浮點數可以被轉換為整數

  • 總是可以將一個數值賦給支持更大數值范圍的類型的變量,例如,可以將long類型的值賦給float型變量。但是,如果不進行類型轉換,就不能將一個值賦給范圍較小的類型的變量。類型轉換是將一種數據類型的值轉換成另一種數據類型的值的操作。將范圍較小的類型轉換為范圍較大的類型稱為擴展類型(widening a type)。Java將自動擴展一個類型,但是縮小類型必須顯示完成

  • 如果要將一個值賦給一個范圍較小的類型的變量,例如將double型的值賦給int型變量,就必須進行類型轉換。如果在這種情況下沒有使用類型轉換,就會出現編譯錯誤。使用類型轉換時必須小心,丟失的信息也許會導致不精確的結果

  • 類型轉換不改變被轉換的變量。例如,下面代碼中的d在類型轉換之后值不變:

double d = 4.5
int i = (int)d
  • Java中,x1 op = x2 形式的增強賦值表達式實現為x1 = (T)(x1 op x2),這里T是x1的類型。因此,下面的代碼是正確的。
  • 將一個int型變量賦值給short型或byte型變量,必須顯式地使用類型轉換。例如,下述語句就會產生編譯錯誤:
int i= 1;
byte b = i;//Error because explicit casting is required
  • 然而,只要整型字面值是在目標變量允許的范圍內,那么將整型字面值賦給short型或byte型變量時,就不需要顯式的類型轉換

程序清單 2-8 SalesTax.java

import java.util.Scanner;

public class SalesTax {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Enter purchase amount: ");
        double purchaseAmount = input.nextDouble();
        double tax = purchaseAmount * 0.06;
        System.out.println("Sales tax is $"+(int)(tax * 100) / 100.0);
        //這里的int強制轉換的作用是向下取整,並保留小數點后兩位。
        //向上取整用(int)(x * 100+0.5),通過乘以10的N次方並除以10的N次方來保留N位小數
        //當purchase為10的N次方時,僅保留一位
        /**
         * 實例:Enter purchase amount: 10000000
         *      Sales tax is $600000.0
         */
    }
}

軟件開發過程

  • 軟件開發生命周期是一個多階段的過程,包括需求規范、分析、設計、實現、測試、部署和維護

  • 需求規范

    • 需求規范是一個規范化的過程,旨在理解軟件要處理的問題,以及將軟件系統的功能詳細記錄到文檔中
  • 系統分析

    • 系統分析旨在分析數據流,並且確定系統的輸入和輸出。當進行分析的時候,首先確定輸出,然后弄清楚需要什么樣的輸入來產生結果
  • 系統設計

    • 系統設計是設計一個從輸入獲得輸出的過程。這個階段涉及使用多層的抽象,將問題分解為可管理的組成部分,並且設計實現每個組成部分的策略。可以將每個組成部分看作一個執行系統特定功能的子系統。系統分析和設計的本質是輸入、處理和輸出(IPO
  • 實現

    • 實現是將系統設計翻譯成程序。為每個組成部分編寫獨立的程序,然后集成在一起工作。這個過程需要使用一門編程語言,比如Java,實現包括編碼、自我測試以及調試(在代碼中查找錯誤稱為調試)
  • 測試

    • 測試確保代碼符合需求規范,並且排除錯誤。通常由一個沒有參與產品設計和實現的獨立軟件工程團隊完成這樣的測試
  • 部署

    • 部署使得軟件可以被使用。按照類型的不同,軟件可能被安裝到每個用戶的機器上,或者安裝在一個Internet 可訪問的服務器上
  • 維護

    • 維護是對軟件產品進行更新和改進。軟件產品必須在一直演化的環境中連續運行和改進。這需要進行產品的周期性改進,以修正新發現的錯誤,並且整合改進部分

程序清單 2-9 ComputeLoan.java

import java.util.Scanner;

public class ComputeLoan {
    public static void main(String[] args) {
        //Create a Scanner  創建Scanner類
        Scanner input = new Scanner(System.in);
        //eEnter annual interest rate in percentage,.g.,7.25  鍵入年利率
        System.out.print("Enter annual interest rate,e.g.,7.25: ");
        double annualInterestRate = input.nextDouble();
        //Obtain monthly interest rate  獲取月利率
        double monthlyInterestRate = annualInterestRate / 1200;
        //Enter number of years  鍵入貸款年數
        System.out.print("Enter number of years as an interger,e.g.,5: ");
        int numberOfYears = input.nextInt();
        //Enter loan amount  鍵入貸款金額
        System.out.print("Enter loan amount,e.g.,120000.95: ");
        double loanAmount = input.nextDouble();
        //Calculate payment  計算支付金額
        double monthlyPayment = loanAmount * monthlyInterestRate /
                (1 - 1 / Math.pow(1 + monthlyInterestRate, numberOfYears * 12));
        double totalPayment = monthlyPayment * numberOfYears * 12;
        //Display results  顯示結果
        System.out.println("The monthly payment is $" +
                (int) (monthlyPayment * 100) / 100.0);
        System.out.println("The total payment is $" +
                (int) (totalPayment * 100) / 100.0);
    }
}

程序清單 2-10 ComputeChange.java

import java.util.Scanner;

public class ComputeChange {
    public static void main(String[] args) {
        //Create a Scanner
        Scanner input = new Scanner(System.in);
        //Receive the amount
        System.out.print("Enter an amount in double, for example 11.56: ");
        double amount = input.nextDouble();
        int remainingAmount = (int) (amount * 100);
        //Find the number of one dollars
        int numberOfOneDollars = remainingAmount / 100;
        remainingAmount = remainingAmount % 100;
        //Find the number of quarters in the remaining amount
        int numberOfQuarters = remainingAmount / 25;
        remainingAmount = remainingAmount % 25;
        //Find the number of dimes in the remaining amount
        int numberOfDimes = remainingAmount / 10;
        remainingAmount = remainingAmount % 10;
        //Find the number pf nickels in the remaining amount
        int numberOfNickels = remainingAmount / 5;
        remainingAmount = remainingAmount % 5;
        //Find the number of pennies in the remaining amount
        int numberOfPennies = remainingAmount;
        //Display results
        System.out.println("Your amount " + amount + " consists of+" +
                " " + numberOfOneDollars + " dollars" + " " + numberOfQuarters
                + " quarters " + " " + numberOfDimes + " dimes" + " "
                + numberOfNickels + " nickels" + " " + numberOfPennies + " pennies");
    }
}

常見錯誤和陷阱

  • 常見的基礎編程錯誤經常設計未聲明變量、未初始化變量、整數溢出、非預期的整數除法,以及數值取整錯誤


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM