109 專技高考高等考試 資訊技師 程式設計 考古題詳解
第 一 題25 分
請依據下列 C++ 程式碼執行後,試問輸出結果為何?
#include <stdio.h>
int F(int x, int y) { int c = 7; int d = c % 3; for (int i = 1; i <= y; i++) { d = c * (x - i + 1) / i; } return d; }
int main() { int h = 8; for (int a = h % 5 + 2; a > 3; a--) { for (int n = 0; n <= a; n++) { printf("%d", F(a, n)); } printf("\n"); } return 0; }
登入後即可作答並保存紀錄。
核心觀念
本題為典型的「程式追蹤題(Code Tracing)」,評量考生對 C/C++ 基礎語法與控制流程的掌握度,核心考點包含:
- 模數運算與運算子優先權:運算子
%(取餘數)與整數算術運算。 - 巢狀迴圈(Nested Loops)控制流程:外層與內層
for迴圈的初始條件、終止條件與計數遞增/遞減。 - 區域變數賦值與迴圈覆蓋陷阱:在函式中,迴圈內每次迭代皆直接對變數
d重新賦值(非累乘運算),前次計算結果會被覆蓋。 - 整數除法(Integer Division)特性:C/C++ 中兩整數相除採向零捨去(Truncation toward zero),小數部分直接捨棄。
解題方法
解題切入點分為「主程式外層流程分析」與「自訂函式 F(x, y) 運算化簡」兩大步驟。
步驟一:分析主程式 main 的迴圈範圍
- 外層迴圈變數 的範圍:
- 初始值:,故 。
- 終止條件:;更新步進:
a--。 - 因此外層迴圈共執行 2 次,其值依序為:
- 第一輪:
- 第二輪:
- 當 時不滿足 ,迴圈終止。
- 內層迴圈變數 的範圍:
- 條件為
for (int n = 0; n <= a; n++)。 - 當 時: 依序為 (共 6 次呼叫)。
- 當 時: 依序為 (共 5 次呼叫)。
- 輸出格式:
- 內層呼叫
printf("%d", F(a, n));,數值之間沒有空格。 - 外層每輪結束印出換行字元
\n。
步驟二:分析自訂函式 F(x, y) 的運算通式
函式定義如下:
int F(int x, int y) {
int c = 7;
int d = c % 3;
for (int i = 1; i <= y; i++) {
d = c * (x - i + 1) / i;
}
return d;
}
- 初始值:,。
- 關鍵觀察:
- 迴圈內部算式為
d = c * (x - i + 1) / i;。 - 注意右式使用常數 ,而非累計變數 。因此每次迭代都在重新計算並直接覆蓋 的值。
- 當 時:迴圈條件
i <= 0不成立,迴圈不執行,直接回傳初始值 。 - 當 時:迴圈執行 至 ,最終回傳的數值僅取決於最後一次迭代(即 時):
步驟三:逐項代入推導輸出結果
1. 第一行輸出(,):
- :迴圈未執行,回傳初始值 。
- :。
- :。
- :。
第 二 題25 分
請依據下列 C++ 程式碼執行後,若輸入如下所示,試問輸出結果為何?
輸入:
1 3 5 7 2 4 6 8
#include <stdio.h>
void getMatrixElements(int matrix[][10], int row, int column) { int i, j;
printf("\nEnter elements: \n");
for (i = 0; i < row; ++i) {
for (j = 0; j < column; ++j) {
printf("Enter a%d%d: ", i + 1, j + 1);
scanf("%d", &matrix[i][j]);
}
}
}
void calMatrices( int first[][10], int second[][10], int result[][10], int r1, int c1, int r2, int c2 ) { int i, j, k;
for (i = 0; i < r1; ++i) {
for (j = 0; j < c2; ++j) {
result[i][j] = 0;
}
}
for (i = 0; i < r1; ++i) {
for (j = 0; j < c2; ++j) {
for (k = 0; k < c1; ++k) {
result[i][j] += first[i][k] * second[k][j];
}
}
}
}
void display(int result[][10], int row, int column) { int i, j;
printf("\nOutput Matrix:\n");
for (i = 0; i < row; ++i) {
for (j = 0; j < column; ++j) {
printf("%d ", result[i][j]);
if (j == column - 1) {
printf("\n");
}
}
}
}
int main() { int first[5][5], second[5][5], result[5][5]; int r1 = 2, c1 = 2, r2 = 2, c2 = 2;
getMatrixElements(first, r1, c1);
getMatrixElements(second, r2, c2);
calMatrices(first, second, result, r1, c1, r2, c2);
display(result, r1, c2);
return 0;
}
登入後即可作答並保存紀錄。
核心觀念
- 二維陣列(Two-Dimensional Array)的函式傳遞與配置:
在 C/C++ 中,將多維陣列傳遞給函式時,除了第一維(列數)可省略外,第二維(行數,Column)的大小必須明確給定(例如
int matrix[][10]),編譯器才能依據列優先(Row-major order)計算位址位移量(Stride),其定址公式為: - 巢狀迴圈(Nested Loops)與矩陣相乘演算法: 若矩陣 維度為 、矩陣 維度為 (必須滿足 ),相乘後的結果矩陣 維度為 。三層巢狀迴圈的計算核心為: 時間複雜度為 。
- 格式化輸出與流程控制:
printf與scanf的格式控制符,包含空白字元(%d後方具兩個空白)及換行字元(\n)的印出時機。
解題方法
步驟一:分析主程式變數初始化
main 函式中宣告了三個二維陣列 first、second、result,並設定維度參數:
- (代表第一個矩陣為 )
- (代表第二個矩陣為 )
步驟二:追蹤資料輸入函式 getMatrixElements
依據雙層迴圈順序(先列後行:i = 0, 1,j = 0, 1),輸入串流依序讀入數值:
- 讀入第一個矩陣
first(共 4 個數值:1, 3, 5, 7):
即第一個矩陣為:
- 讀入第二個矩陣
second(後續 4 個數值:2, 4, 6, 8):
即第二個矩陣為:
步驟三:計算矩陣相乘 calMatrices
- 先將
result陣列前 元素清為 0。 - 透過三層迴圈進行矩陣乘法 :
第 三 題25 分
請依據下列 C++ 程式碼執行後,回答輸出結果為何?
#include <stdio.h>
struct EmpAddress { char *ename; char stname[20]; int pincode; } employee1 = {"John Alter", "Court Street", 654134}, *pt1 = &employee1;
int main() { struct EmpAddress employee2 = {"Bob Hard", "First Street", 462524}, employee3 = {"Draven Green", "Darkest Street", 883126}; struct EmpAddress *pt2, *pt3;
pt2 = &employee2;
pt3 = &employee3;
pt2->ename = pt1->ename;
pt2->pincode = 315948;
pt1 = pt2;
strcpy(pt3->stname, "Love Street");
pt1->ename = pt3->ename;
printf(" %s from %s, pincode:%d \n\n",
pt1->ename, (*pt1).stname, pt1->pincode);
printf(" %s from %s, pincode:%d \n\n",
pt2->ename, (*pt2).stname, pt2->pincode);
printf(" %s from %s, pincode:%d \n\n",
pt3->ename, (*pt3).stname, pt3->pincode);
return 0;
}
登入後即可作答並保存紀錄。
核心觀念
本題評量 C/C++ 程式設計中結構體(struct)、指標操作(Pointers)與字串處理的綜合追蹤能力,涉及以下四大核心觀念:
- 結構體成員存取運算子:
- 箭號運算子
->:透過結構體指標存取成員,語法等價於(*ptr).member。 - 點運算子
.:直接透過結構體實體變數存取成員。
- 指標賦值(Pointer Aliasing)與對象重導向:
- 當執行指標變數之間的賦值(如 )時,改變的是「指標所儲存的記憶體位址」,而非複製結構體內容。此後 與 指向同一個結構體實體,修改 所指內容等同於修改 所指內容。
- 字串指標與字元陣列之賦值差異:
char *ename為字元指標,執行ename = ...僅改變指標指向的字串常值(String Literal)記憶體位址(Shallow Copy)。char stname[20]為字元陣列,不可直接用等號賦值,須使用strcpy將字串內容逐字複製進陣列記憶體空間(Deep Copy)。
printf格式化輸出控制:
- 格式字串
" %s from %s, pincode:%d \n\n"最前方包含一個半形空格,結尾包含兩個換行符號(\n\n),輸出行之間會產生空行。
解題方法
採用「記憶體狀態追蹤法(Memory Tracing)」,先確立初始狀態,再逐行追蹤變數數值的變動。
1. 初始狀態分析
程式配置了三個結構體變數與三個結構體指標:
| 變數名稱 | 實體類型 | ename 指向 | stname 內容 | pincode 數值 | 指標變數指向 |
|---|---|---|---|---|---|
employee1 | 全域變數 | "John Alter" | "Court Street" | ||
employee2 | 區域變數 | "Bob Hard" | "First Street" | ||
employee3 | 區域變數 | "Draven Green" | "Darkest Street" |
2. 逐行執行推導
pt2->ename = pt1->ename;
- 指向
employee2, 指向employee1。 - 將
employee1.ename的位址複製給employee2.ename。 - 此時
employee2.ename改指向"John Alter"。
pt2->pincode = 315948;
- 將
employee2.pincode修改為 。
pt1 = pt2;(關鍵步驟)
- 指標重新賦值:將 儲存的位址賦予 。
- 不再指向
employee1,改為與 同時指向employee2。
第 四 題25 分
請依據下列 C++ 程式碼執行後,若輸入如下所示,試問輸出結果為何?
輸入:
136631
#include <stdio.h>
int main() { int n, rN = 0, remainder, originalN, flag = 0, num = 0, i;
printf("Enter an integer: ");
scanf("%d", &n);
originalN = n;
while (n != 0) {
remainder = n % 10;
rN = rN * 10 + remainder;
n /= 10;
num++;
}
if (originalN == rN) {
printf("True\n");
flag = 1;
} else {
printf("False\n");
flag = 0;
}
n = originalN;
rN = 0;
num = num * 2;
if (flag == 1) {
while (n != 0) {
remainder = n % 10;
rN = rN + remainder;
printf("%d\n", rN);
n /= 10;
}
} else {
printf("%d\n", rN);
}
return 0;
}
登入後即可作答並保存紀錄。
核心觀念
本題為典型的「程式追蹤題(Code Tracing)」,主要測驗考生對 C/C++ 語言基礎語法、控制結構與常見演算法模板的掌握程度,核心觀念包含:
- 數值拆解運算:利用模除運算子
% 10依序取得最低有效位數(LSD, Least Significant Digit),搭配整數除法運算子/ 10去除已處理位數,達到由右至左遍歷十進位數字每一位的效果。 - 數字反轉與迴文數(Palindrome Number)檢驗:透過公式 重構反轉數值,並藉由比對原始數值 與反轉值 是否相等,判定是否為迴文數。
- 流程控制與狀態旗標:利用變數
flag記錄判斷結果,並引導後續的分支走向。 - 位數前綴累加(Prefix Sum)與迴圈輸出:在第二個迴圈中,利用 由低位向高位逐步累加各個位數的數值,且在每次迭代過程中即時輸出累加值。
解題方法
本程式可分為三大階段進行追蹤:
- 階段一:提示輸入與反轉迴文判定
- 階段二:變數重設與分支轉移
- 階段三:各數位累加與逐行輸出
輸入值為:136631
階段一:反轉迴文判定追蹤
程式起始先印出提示訊息,讀入整數並備份:
- 執行
printf("Enter an integer: ");,輸出提示字串(結尾無換行符號\n)。 - 讀入 ,設定 ,,。
進入第一個 while (n != 0) 迴圈,每次擷取個位數進行反轉重組:
| 迭代次數 | 進入時 | remainder = n % 10 | rN = rN * 10 + remainder | 離開時 | num++ |
|---|---|---|---|---|---|
| 第 1 次 | |||||
| 第 2 次 | |||||
| 第 3 次 | |||||
| 第 4 次 | |||||
| 第 5 次 | |||||
| 第 6 次 |
迴圈結束時:,,。
執行條件判斷:
if (originalN == rN):比對 ,條件成立。- 印出
True\n,並將flag設為 。
階段二:變數重設
接續執行:
n = originalN;rN = 0;歸零,作為後續累加器使用。num = num * 2;(此處為干擾運算,後續未再使用num)。
階段三:各數位累加輸出追蹤
因為 flag == 1,程式進入 if (flag == 1) 內部之 while (n != 0) 迴圈: