110 高普考高考三級 資訊處理 程式語言 考古題詳解

110 年・高普考・高考三級・資訊處理
試題代碼 程式語言

第 一 題25 分

一、語意分析(Semantics Analysis)對於程式語言的正確執行非常重要。

(一)以下是 Java 和 C++ 程式,請說明程式編譯、執行結果與其原因,以及程式指令之意義或影響。(18 分)

(1) Java 程式

static void test1(){ int n; int[] x = new int[n]; }

(2) Java 程式

static void test2(){ int n=0; int[] x = new int[n]; }

(3) Java 程式

static void test3(){ int n=0; int[] x = new int[n]; x[0]=0; }

(4) C++ 程式

void test4(){ int n; int x[n]; }

(5) C++ 程式

void test5(){ int n=0; int x[n]; x[0]=0; }

(6) C++ 程式

void test6(){ int n=0; int *x = new int[n]; x[0]=0; }

(二)請說明 Java 與 C++ 語言在陣列宣告上的語意分析的方法,與其優缺點。(7 分)

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查陣列長度如何判定,以及陣列宣告與陣列元素存取分別在何時接受語意檢查。

  • 編譯期檢查:編譯器依語言規則判斷宣告是否合法,例如陣列長度是否為常數運算式、變數是否已初始化。
  • 執行期檢查:程式執行時才計算陣列長度,或檢查索引是否超出範圍。
  • Java 陣列:陣列是物件,使用 new int[n] 在執行期建立;元素會初始化為 0,索引越界會拋出例外。
  • C++ 內建陣列:標準 C++ 的一般陣列宣告需要編譯期可決定的長度。GNU 等編譯器可能支援標準以外的變動長度陣列(VLA)擴充。new int[n] 則可在執行期配置陣列,長度為 0 也合法;但透過指標存取元素時不會自動檢查索引。

以下依標準 Java 與標準 C++ 判定;C++ 編譯器若另行支援 VLA 或零長度陣列,會在相應小題補充說明。

解題方法

逐段依序檢查:

  1. 長度變數是否已初始化,能否合法取得其值。
  2. 陣列宣告是否符合該語言對陣列長度的規定。
  3. 若成功建立陣列,陣列長度是否為零。
  4. 若有 x[0],判斷索引 0 是否落在有效索引範圍內。

對長度為 nn 的陣列,有效索引為 00 到 n−1n-1。當 n=0n=0 時,沒有任何有效索引。

(一)各程式的編譯與執行結果

(1)Java test1

static void test1{
 int n;
 int[] x = new int[n];
}

編譯失敗。 n 是區域變數,宣告後未初始化;Java 不會替區域變數自動指定預設值。new int[n] 必須讀取 n 的值,但此時 n 尚未確定,違反 Java 的明確指派規則,因此在編譯期就被拒絕。

這不是執行期的 NegativeArraySizeException,因為程式根本無法編譯、尚未進入執行期。

(2)Java test2

static void test2{
 int n=0;
 int[] x = new int[n];
}

編譯成功,執行正常完成。 n 已初始化為 0,所以建立長度為零的 int 陣列。Java 允許零長度陣列;此處沒有存取任何元素,因此不會發生索引越界。

(3)Java test3

static void test3{
 int n=0;
 int[] x = new int[n];
 x[0]=0;
}

編譯成功,但執行時拋出 ArrayIndexOutOfBoundsException。

new int[0] 合法地建立零長度陣列,但這個陣列沒有有效索引。接著執行 x[0] = 0,索引 0 不在有效範圍內,因此 Java 在執行期檢查到越界並拋出例外。例外發生後,後續程式不會繼續執行。

(4)C++ test4

void test4{
 int n;
 int x[n];
}

依標準 C++,編譯不合法。 區域內建陣列 x 的長度須為編譯期可決定的常數運算式;n 是一般區域變數,不符合此條件。

部分編譯器以 VLA 擴充接受這種宣告,但 n 沒有初始化,讀取其不確定值作為陣列長度會造成未定義行為。因此即使在支援 VLA 的編譯器上,這段程式也沒有可依賴的執行結果。

(5)C++ test5

void test5{
 int n=0;
 int x[n];
 x[0]=0;
}

依標準 C++,編譯不合法。 雖然 n 已初始化為 0,但它仍是一般區域變數,不是編譯期常數運算式,因此不能作為內建陣列的標準陣列長度。

🔒

後續完整解題步驟與【答案】

免費註冊,享 3 天全站完整詳解閱覽。

免費註冊

第 二 題25 分

二、程式驗證的應用。

(一)請說明「測試驅動發展方法(Test Driven Development, TDD)」的概念及優點。(7 分)

(二)有一 MySort 類別的方法 int[] binarySort(int data[]),將陣列 data 內的資料由小到大排序後回傳,請依據 TDD 的概念設計測試案例。(10 分)

(三)請以 Java/JUnit 語言完成以下測試程式(I)~(II)。(8 分)

@Test public void testBinarySort(MySort ____){ int[] source = {2, 3, 5, 9, 12, 7}; int[] target = obj.binarySort(source); for(int i=0; i<source.length-1; i++){ assertTrue(target[i] < ____); } }

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查程式驗證中的測試驅動發展方法(Test Driven Development, TDD),以及如何依測試需求撰寫 JUnit 測試。

TDD 是一種先寫測試、再寫程式的開發方法。常見流程是:

  1. 新增測試:先根據需求撰寫一個尚未通過的測試。
  2. 讓測試通過:撰寫足以通過該測試的最少程式碼。
  3. 重構:在測試仍通過的前提下,改善程式結構與可讀性。

這個流程常簡稱為 紅燈、綠燈、重構:測試先失敗,再讓測試通過,最後整理程式碼。

解題方法

(一)TDD 的概念及優點

TDD 的核心是以可執行的測試案例明確表達需求,並在實作功能之前建立測試。每完成一小段功能,就執行測試確認結果符合預期。

其優點如下:

  • 及早發現錯誤:功能開發時即可確認結果,縮短錯誤定位時間。
  • 釐清需求:測試案例具體呈現輸入與預期輸出,降低需求理解落差。
  • 提升程式品質:重構時可反覆執行測試,確認既有功能沒有被破壞。
  • 方便回歸測試:累積的測試可在修改程式後再次執行,檢查原有功能。
  • 促進模組化設計:程式需能被測試呼叫,通常有助於降低耦合並建立清楚介面。

(二)依 TDD 設計 binarySort 測試案例

binarySort 的需求是將整數陣列由小到大排序並回傳。測試應涵蓋一般輸入、邊界情況,以及容易出錯的資料型態。每項測試都要比較「實際回傳值」與「預期排序結果」。

測試情境輸入 data預期結果
一般未排序資料{2, 3, 5, 9, 12, 7}{2, 3, 5, 7, 9, 12}
已排序資料{1, 2, 3}{1, 2, 3}
反向排序資料{3, 2, 1}{1, 2, 3}
含重複值{4, 1, 4, 2}{1, 2, 4, 4}
空陣列{}{}
單一元素{8}{8}
含負數{0, -3, 2, -1}{-3, -1, 0, 2}
🔒

後續完整解題步驟與【答案】

免費註冊,享 3 天全站完整詳解閱覽。

免費註冊

第 三 題25 分

三、建構股票交易資料庫(Stock),請寫出 SQL 指令。

客戶表格(Customer):

欄位資料型態與限制
客戶編號(cid)整數、主鍵、自動增加
客戶姓名(cname)少於 10 字元可變字串
客戶帳戶餘額(balance)整數、非空值
客戶融資餘額(margin)整數、非空值

證券交易表格(StockTrade):

欄位資料型態與限制
交易編號(id)整數、主鍵、自動增加
證券編號(sid)整數、非空值
證券每股購入價格(price)整數、非空值
證券購入股數(share)整數、非空值
客戶編號(cid)整數、非空值

(一)造出 Customer、StockTrade 表格。(10 分)

CREATE TABLE Customer ( ____________________ );

CREATE TABLE StockTrade ( ____________________ );

(二)查詢客戶姓名為 "Tom" 所有購買股票編號與購入總股數。(5 分)

(三)撰寫 Store Procedure,造出一個暫時的資料表 Report,含兩個整數資料欄位(證券編號 sid、證券價格 price);加入 10 筆資料,再根據證券價格由小到大排序,查詢列出此 10 筆資料。(10 分)

delimiter $$

CREATE PROCEDURE x() BEGIN DECLARE i INT DEFAULT 1; ____________________ END$$

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查資料定義語言(DDL)、資料查詢語言(DQL),以及 MySQL 儲存程序中的變數、暫存資料表與迴圈操作。

  • PRIMARY KEY 定義主鍵;AUTO_INCREMENT 讓整數鍵值自動增加。
  • NOT NULL 限制欄位不得為空值;可變字串使用 VARCHAR(n)。
  • 以 JOIN 連結客戶與交易資料,以 SUM 彙總股數,並以 GROUP BY 依股票編號分組。
  • 儲存程序使用 WHILE 迴圈新增資料,再以 ORDER BY 排序查詢結果。

解題方法

(一)建立資料表

依題目逐欄轉換型態與限制。cname 少於 10 字元,採 VARCHAR(9);兩個自動增加欄位均設為主鍵。StockTrade.cid 是客戶編號,但題目未明確要求設定外鍵,因此依題意設定為非空整數欄位即可。

CREATE TABLE Customer (
 cid INT AUTO_INCREMENT PRIMARY KEY,
 cname VARCHAR(9),
 balance INT NOT NULL,
 margin INT NOT NULL
);

CREATE TABLE StockTrade (
 id INT AUTO_INCREMENT PRIMARY KEY,
 sid INT NOT NULL,
 price INT NOT NULL,
 `share` INT NOT NULL,
 cid INT NOT NULL
);

share 在 MySQL 中可能與關鍵字或函數名稱衝突,使用反引號括住欄位名稱可避免解析問題。

(二)查詢 Tom 購買各股票編號與購入總股數

先用 Customer.cid = StockTrade.cid 連結兩表,再篩選姓名為 Tom 的客戶。相同股票編號的多筆交易須合併,因此依 sid 分組並加總 share。

🔒

後續完整解題步驟與【答案】

免費註冊,享 3 天全站完整詳解閱覽。

免費註冊

第 四 題25 分

四、程式例外處理的設計對於資訊系統的可靠性非常重要。

(一)請完成以下 C++ 程式(I)~(V)指令,處理兩數相除的例外狀況,使輸出為:(15 分)

Exception:empty
Exception:not a number
Quotient:Exception:divided by zero
Quotient:2.4

#include <iostream> #include <exception> #include <string.h> #define N 10 using namespace std;

class EmptyException:public exception { public: virtual const char* what() const throw(){ ____________________; } };

class NotNumberException:public exception { public: virtual const char* what() const throw(){ ____________________; } };

class DividedByZeroException:public exception { public: virtual const char* what() const throw(){ ____________________; } };

int valid(const char x[N]){ int result=0; if(strlen(x)==0)throw EmptyException(); for(int i=0; i<strlen(x); i++){ if(!isdigit(x[i])) throw NotNumberException(); result = ____________________; } return result; }

double quotient(int n1, int n2){ if(____________________) throw DividedByZeroException(); return static_cast<double>(n1/n2); }

void test(const char x1[N], const char x2[N]){ int n1, n2; try { n1=valid(x1); n2=valid(x2); cout<<"Quotient:"<<quotient(n1, n2); } catch(EmptyException &e){ cout<<"Exception:"<< e.what(); } catch(NotNumberException &e){ cout<<"Exception:"<< e.what(); } catch(DividedByZeroException &e){ cout<<"Exception:"<< e.what(); } cout<<endl; }

int main(){ test("", ""); test("a", "12"); test("10", "0"); test("12", "5"); return 0; }

(二)請說明使用 try-catch 與 if-else,處理例外狀況的優缺點。(5 分)

(三)請說明 C++ 與 Java 在 try-catch 中 finally 設計的異同與其理由。(5 分)

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查 C++ 的例外處理、字串轉整數、整數除法與浮點數轉型,以及 try-catch 和 if-else 的適用時機。

  • throw 用來拋出例外;try 區塊中的例外會交由型別相符的 catch 處理。
  • 自訂例外類別可覆寫 what,回傳例外訊息。
  • 驗證輸入時,空字串與非數字字元分別拋出不同例外;除數為零則在執行除法前拋出例外。
  • 整數除法會先捨去小數部分。若要得到小數商,必須先將至少一個運算元轉成浮點數。

解題方法

依輸出要求逐一填入例外訊息、十進位數字累積式與除數檢查條件:

  1. what 分別回傳 "empty"、"not a number"、"divided by zero"。
  2. 數字字串逐字累積:每次將目前結果乘以 10,再加上當前數字的數值。
  3. 除法前檢查分母是否為 0。
  4. 將分子轉成 double 後再除法,避免整數除法截去小數。
class EmptyException:public exception {
public:
 virtual const char* what const throw{
 return "empty";
 }
};

class NotNumberException:public exception {
public:
 virtual const char* what const throw{
 return "not a number";
 }
};

class DividedByZeroException:public exception {
public:
 virtual const char* what const throw{
 return "divided by zero";
 }
};

int valid(const char x[N]){
 int result=0;
 if(strlen(x)==0)throw EmptyException;
 for(int i=0; i<strlen(x); i++){
 if(!isdigit(x[i]))
 throw NotNumberException;
 result = result * 10 + (x[i] - '0');
 }
 return result;
}

double quotient(int n1, int n2){
 if(n2 == 0)
 throw DividedByZeroException;
 return static_cast<double>(n1) / n2;
}

字元 '0' 到 '9' 在字元編碼中連續,因此 x[i] - '0' 可取得該位數值。以 "12" 為例,累積過程為 0×10+1=10 \times 10 + 1 = 1,接著 1×10+2=121 \times 10 + 2 = 12。

test("", "") 在第一個 valid 呼叫就遇到空字串,輸出 Exception:empty。test("a", "12") 的第一個字串含非數字字元,輸出 Exception:not a number。test("10", "0") 的分母為 0,quotient 拋出例外;

🔒

後續完整解題步驟與【答案】

免費註冊,享 3 天全站完整詳解閱覽。

免費註冊

其他考古題