練習題目¶
Problem. 值、位址與反參考¶
- 在
main()宣告int number = 50;。 - 宣告
int* ptr,並讓它指向number。 - 依序輸出以下 5 項資料,每項各占一行:
number的值。number的位址。ptr儲存的位址。*ptr的值。ptr自己的位址。
輸入格式: 本題沒有輸入。
輸出格式:
#include <iostream>
using namespace std;
int main() {
int number = 50;
int* ptr = &number;
// 分別觀察物件、物件位址、指標內容與指標位址。
cout << number << '\n';
cout << &number << '\n';
cout << ptr << '\n';
cout << *ptr << '\n';
cout << &ptr << '\n';
}
Problem. 透過指標修改¶
- 宣告整數變數
score並讀入分數。 - 宣告指標
scorePtr指向score。 - 只能透過
*scorePtr將分數加 10。 - 加分後若超過 100,將它設為 100。
- 輸出加分後的
score。
輸入格式: 一個介於 0 到 100 的整數。
輸出格式:
範例輸入 1:
範例輸出 1:
範例輸入 2:
範例輸出 2:
限制: 修改分數時不可直接寫 score = ...。
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
int score;
cin >> score;
int* ptr = &score;
// 透過 ptr 修改原本的 score。
*ptr = min(*ptr + 10, 100);
cout << score << '\n';
}
Problem. 安全空指標¶
任務說明: 完成下列函式:
- 若
ptr == nullptr,輸出沒有資料。 - 否則輸出
資料:與*ptr。
在 main() 中必須:
- 宣告
int number = 10;。 - 呼叫
printValue(nullptr);。 - 呼叫
printValue(&number);。
輸入格式: 本題沒有輸入。
預期輸出:
限制: 不可在檢查空指標之前執行 *ptr。
#include <iostream>
using namespace std;
void printValue(const int* ptr) {
if (ptr == nullptr) {
cout << "沒有資料\n";
return;
}
cout << *ptr << '\n';
}
int main() {
int number = 10;
printValue(nullptr);
printValue(&number);
}
Problem. 指標交換¶
任務說明: 完成函式:
- 兩個指標都有效時,交換它們指向的整數。
- 任一指標為
nullptr時,函式直接返回,不修改任何資料。 - 不可呼叫
swap()。
main() 讀入兩個整數,呼叫 swapValues(&first, &second) 後輸出結果。
輸入格式: 同一行兩個整數。
範例輸入:
範例輸出:
額外測試: 在 main() 額外呼叫一次 swapValues(&first, nullptr),確認程式不會崩潰。
#include <iostream>
using namespace std;
void swapValues(int* left, int* right) {
if (left == nullptr || right == nullptr) {
return;
}
int temporary = *left;
*left = *right;
*right = temporary;
}
int main() {
int first = 3;
int second = 8;
swapValues(&first, &second);
cout << first << ' ' << second << '\n';
}
Problem. 找較大值¶
任務說明: 完成函式:
規則:
- 兩者皆有效時,回傳較大整數的地址。
- 數值相同時,回傳
first。 - 只有一者有效時,回傳有效的那一者。
- 兩者皆為空時,回傳
nullptr。
main() 讀入兩個整數,以函式找出較大值並輸出。
範例輸入:
範例輸出:
指定測試: 除了一般輸入,還要在程式內測試 larger(&a, nullptr) 與 larger(nullptr, nullptr)。
#include <iostream>
using namespace std;
const int* larger(const int* first, const int* second) {
if (first == nullptr) return second;
if (second == nullptr) return first;
return *first >= *second ? first : second;
}
int main() {
int a = 10;
int b = 30;
const int* answer = larger(&a, &b);
if (answer) cout << *answer << '\n';
}
Problem. 指標走訪¶
任務說明:
- 宣告
int values[8]{};。 - 使用指標從輸入讀取 8 個整數。
- 再使用指標依原順序輸出全部元素。
輸入格式: 8 個整數。
範例輸入:
範例輸出:
限制:
- 讀取與輸出階段都不可使用
values[i]。 - 必須使用
int* current、++current與*current。 - 結束條件應為
current != values + 8。
#include <iostream>
using namespace std;
int main() {
int values[8]{};
// current 從起點移到尾端下一格。
for (int* current = values; current != values + 8; ++current) {
cin >> *current;
}
for (const int* current = values; current != values + 8; ++current) {
cout << *current << ' ';
}
cout << '\n';
}
Problem. 陣列總和函式¶
任務說明: 完成函式:
- 加總
data[0]到data[size - 1]。 - 當
data == nullptr或size == 0時回傳 0。 - 函式不可修改陣列。
main() 輸入 5 個整數並呼叫函式。
範例輸入:
範例輸出:
指定測試: 另輸出 sum(nullptr, 0) 的結果,應為 0。
#include <cstddef>
#include <iostream>
using namespace std;
int sum(const int* data, size_t size) {
int result = 0;
for (size_t i = 0; i < size; ++i) {
result += data[i];
}
return result;
}
int main() {
int values[5]{};
for (int& value : values) {
cin >> value;
}
cout << "總和:" << sum(values, 5) << '\n';
cout << "空陣列:" << sum(nullptr, 0) << '\n';
}
Problem. 最大值地址¶
任務說明: 完成函式:
- 回傳最大元素第一次出現的位置。
data == nullptr或size == 0時回傳nullptr。- 不可建立第二個陣列。
main() 輸入 6 個整數,輸出最大值及索引。索引可利用 result - values 求得。
範例輸入:
範例輸出:
#include <cstddef>
#include <iostream>
using namespace std;
const int* findMaximum(const int* data, size_t size) {
if (data == nullptr || size == 0) return nullptr;
const int* maximum = data;
for (const int* current = data + 1; current != data + size; ++current) {
if (*current > *maximum) maximum = current;
}
return maximum;
}
int main() {
int values[6]{};
for (int& value : values) {
cin >> value;
}
const int* result = findMaximum(values, 6);
if (result) {
cout << "最大值:" << *result << '\n'
<< "索引:" << result - values << '\n';
}
}
Problem. 反轉陣列¶
任務說明:
- 輸入 10 個整數至陣列。
- 建立
left指向第一個元素,right指向最後一個元素。 - 當
left < right時交換兩者的值,再令left前進、right後退。 - 輸出反轉後的陣列。
範例輸入:
範例輸出:
限制: 不可建立第二個陣列;反轉過程不可用索引。
#include <iostream>
#include <utility>
using namespace std;
int main() {
int values[10]{};
for (int& value : values) cin >> value;
int* left = values;
int* right = values + 9;
// 左右指標尚未相遇時交換。
while (left < right) {
swap(*left, *right);
++left;
--right;
}
for (int value : values) cout << value << ' ';
cout << '\n';
}
Problem. 二維陣列¶
任務說明:
- 宣告 3×4 整數矩陣。
- 宣告
int (*ptr)[4] = matrix;。 - 讀入 12 個整數。
- 使用
*(*(ptr + row) + col)取得元素。 - 輸出三列各自的總和。
輸入格式: 3 列,每列 4 個整數。
範例輸入:
範例輸出:
限制: 計算總和時不可使用 matrix[row][col]。
#include <iostream>
using namespace std;
int main() {
int matrix[3][4]{};
int (*ptr)[4] = matrix;
for (int row = 0; row < 3; ++row)
for (int col = 0; col < 4; ++col)
cin >> *(*(ptr + row) + col);
for (int row = 0; row < 3; ++row) {
int sum = 0;
for (int col = 0; col < 4; ++col) {
sum += *(*(ptr + row) + col);
}
cout << "第 " << row + 1 << " 列:" << sum << '\n';
}
}
Problem. 字串長度¶
任務說明: 完成函式:
text == nullptr時回傳 0。- 從
text開始移動指標,遇到'\0'停止。 - 回傳字元數,不包含
'\0'。
main() 使用 char word[100] 讀入一個不含空白的英文單字。
範例輸入:
範例輸出:
限制: 不可使用 strlen、string 或陣列索引。
#include <cstddef>
#include <iostream>
using namespace std;
size_t stringLength(const char* text) {
if (!text) return 0;
const char* end = text;
while (*end != '\0') ++end;
return static_cast<size_t>(end - text);
}
int main() {
char word[100]{};
cin >> word;
cout << stringLength(word) << '\n';
}
Problem. 複製字串¶
任務說明: 完成函式:
規則:
- 任一指標為空時回傳
false。 - 先計算
source長度。 capacity必須至少是「來源長度+1」。- 容量不足時回傳
false,而且不得修改destination。 - 容量足夠時完整複製字元與最後的
'\0',回傳true。
main() 必須測試:
char large[20] = "unchanged";
char small[4] = "old";
copyString(large, 20, "Pointer");
copyString(small, 4, "Pointer");
預期輸出:
第二次複製失敗,因此 small 必須維持原內容。
#include <cstddef>
#include <iostream>
using namespace std;
bool copyString(char* destination, size_t capacity, const char* source) {
if (!destination || !source) return false;
size_t length = 0;
while (source[length] != '\0') ++length;
if (length + 1 > capacity) return false;
// 包含最後的 '\0' 一起複製。
for (size_t i = 0; i <= length; ++i) {
destination[i] = source[i];
}
return true;
}
int main() {
char destination[20]{};
cout << boolalpha
<< copyString(destination, 20, "Pointer") << '\n'
<< destination << '\n';
}
Problem. 動態平均¶
任務說明:
- 讀入學生人數
n。 - 若
n == 0,輸出人數必須大於 0並結束。 - 使用
new int[n]{}建立成績陣列。 - 讀入
n個 0~100 的整數成績。 - 輸出平均,保留小數點後兩位。
- 使用
delete[]釋放,再將指標設為nullptr。
輸入限制: 0 <= n <= 1000。
範例輸入:
範例輸出:
限制: 本題為理解底層配置,不能使用 vector。
#include <cstddef>
#include <iomanip>
#include <iostream>
using namespace std;
int main() {
size_t size;
cin >> size;
if (size == 0) {
cerr << "筆數必須大於 0\n";
return 1;
}
int* scores = new int[size]{};
int sum = 0;
for (size_t i = 0; i < size; ++i) {
cin >> scores[i];
sum += scores[i];
}
cout << "平均:" << fixed << setprecision(2)
<< static_cast<double>(sum) / size << '\n';
delete[] scores;
scores = nullptr;
}
Problem. 動態陣列複製¶
任務說明: 完成函式:
source == nullptr或size == 0時回傳nullptr。- 否則配置一個含
size個元素的新陣列。 - 將來源內容逐一複製並回傳新陣列起點。
main() 必須:
- 建立
{3, 1, 4, 1, 5}。 - 呼叫
cloneArray。 - 將複本的第一個元素改為 99。
- 分別輸出來源與複本,證明來源仍以 3 開頭。
- 以
delete[]釋放複本。
預期輸出:
所有權契約: 函式回傳的記憶體由呼叫端負責釋放。
#include <cstddef>
#include <iostream>
using namespace std;
int* cloneArray(const int* source, size_t size) {
if (source == nullptr || size == 0) return nullptr;
int* copy = new int[size];
for (size_t i = 0; i < size; ++i) copy[i] = source[i];
return copy;
}
int main() {
int source[] = {3, 1, 4, 1, 5};
int* copy = cloneArray(source, 5);
copy[0] = 99;
cout << "來源:";
for (int value : source) cout << value << ' ';
cout << "\n複本:";
for (size_t i = 0; i < 5; ++i) cout << copy[i] << ' ';
cout << '\n';
delete[] copy;
}
0.