跳轉到

練習題目

Problem. 值、位址與反參考

  1. main() 宣告 int number = 50;
  2. 宣告 int* ptr,並讓它指向 number
  3. 依序輸出以下 5 項資料,每項各占一行:
  4. number 的值。
  5. number 的位址。
  6. ptr 儲存的位址。
  7. *ptr 的值。
  8. ptr 自己的位址。

輸入格式: 本題沒有輸入。

輸出格式:

number 的值:50
number 的位址:實際位址
ptr 儲存的位址:實際位址
ptr 指向的值:50
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. 透過指標修改

  1. 宣告整數變數 score 並讀入分數。
  2. 宣告指標 scorePtr 指向 score
  3. 只能透過 *scorePtr 將分數加 10。
  4. 加分後若超過 100,將它設為 100。
  5. 輸出加分後的 score

輸入格式: 一個介於 0 到 100 的整數。

輸出格式:

加分後:結果

範例輸入 1:

75

範例輸出 1:

加分後:85

範例輸入 2:

96

範例輸出 2:

加分後:100

限制: 修改分數時不可直接寫 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. 安全空指標

任務說明: 完成下列函式:

void printValue(const int* ptr);
  • ptr == nullptr,輸出 沒有資料
  • 否則輸出 資料:*ptr

main() 中必須:

  1. 宣告 int number = 10;
  2. 呼叫 printValue(nullptr);
  3. 呼叫 printValue(&number);

輸入格式: 本題沒有輸入。

預期輸出:

沒有資料
資料:10

限制: 不可在檢查空指標之前執行 *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. 指標交換

任務說明: 完成函式:

void swapValues(int* left, int* right);
  • 兩個指標都有效時,交換它們指向的整數。
  • 任一指標為 nullptr 時,函式直接返回,不修改任何資料。
  • 不可呼叫 swap()

main() 讀入兩個整數,呼叫 swapValues(&first, &second) 後輸出結果。

輸入格式: 同一行兩個整數。

範例輸入:

3 8

範例輸出:

交換後:8 3

額外測試: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. 找較大值

任務說明: 完成函式:

const int* larger(const int* first, const int* second);

規則:

  1. 兩者皆有效時,回傳較大整數的地址。
  2. 數值相同時,回傳 first
  3. 只有一者有效時,回傳有效的那一者。
  4. 兩者皆為空時,回傳 nullptr

main() 讀入兩個整數,以函式找出較大值並輸出。

範例輸入:

12 30

範例輸出:

較大值:30

指定測試: 除了一般輸入,還要在程式內測試 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. 指標走訪

任務說明:

  1. 宣告 int values[8]{};
  2. 使用指標從輸入讀取 8 個整數。
  3. 再使用指標依原順序輸出全部元素。

輸入格式: 8 個整數。

範例輸入:

5 8 2 9 1 6 3 7

範例輸出:

5 8 2 9 1 6 3 7

限制:

  • 讀取與輸出階段都不可使用 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. 陣列總和函式

任務說明: 完成函式:

int sum(const int* data, size_t size);
  • 加總 data[0]data[size - 1]
  • data == nullptrsize == 0 時回傳 0。
  • 函式不可修改陣列。

main() 輸入 5 個整數並呼叫函式。

範例輸入:

10 -3 7 6 2

範例輸出:

總和:22

指定測試: 另輸出 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. 最大值地址

任務說明: 完成函式:

const int* findMaximum(const int* data, size_t size);
  • 回傳最大元素第一次出現的位置。
  • data == nullptrsize == 0 時回傳 nullptr
  • 不可建立第二個陣列。

main() 輸入 6 個整數,輸出最大值及索引。索引可利用 result - values 求得。

範例輸入:

-5 12 7 12 3 -1

範例輸出:

最大值:12
索引:1
#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. 反轉陣列

任務說明:

  1. 輸入 10 個整數至陣列。
  2. 建立 left 指向第一個元素,right 指向最後一個元素。
  3. left < right 時交換兩者的值,再令 left 前進、right 後退。
  4. 輸出反轉後的陣列。

範例輸入:

1 2 3 4 5 6 7 8 9 10

範例輸出:

10 9 8 7 6 5 4 3 2 1

限制: 不可建立第二個陣列;反轉過程不可用索引。

#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. 二維陣列

任務說明:

  1. 宣告 3×4 整數矩陣。
  2. 宣告 int (*ptr)[4] = matrix;
  3. 讀入 12 個整數。
  4. 使用 *(*(ptr + row) + col) 取得元素。
  5. 輸出三列各自的總和。

輸入格式: 3 列,每列 4 個整數。

範例輸入:

1 2 3 4
5 6 7 8
9 10 11 12

範例輸出:

第 1 列:10
第 2 列:26
第 3 列:42

限制: 計算總和時不可使用 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. 字串長度

任務說明: 完成函式:

size_t stringLength(const char* text);
  • text == nullptr 時回傳 0。
  • text 開始移動指標,遇到 '\0' 停止。
  • 回傳字元數,不包含 '\0'

main() 使用 char word[100] 讀入一個不含空白的英文單字。

範例輸入:

Pointer

範例輸出:

長度:7

限制: 不可使用 strlenstring 或陣列索引。

#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. 複製字串

任務說明: 完成函式:

bool copyString(char* destination, size_t capacity, const char* source);

規則:

  1. 任一指標為空時回傳 false
  2. 先計算 source 長度。
  3. capacity 必須至少是「來源長度+1」。
  4. 容量不足時回傳 false,而且不得修改 destination
  5. 容量足夠時完整複製字元與最後的 '\0',回傳 true

main() 必須測試:

char large[20] = "unchanged";
char small[4] = "old";
copyString(large, 20, "Pointer");
copyString(small, 4, "Pointer");

預期輸出:

large:Pointer
small:old

第二次複製失敗,因此 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. 動態平均

任務說明:

  1. 讀入學生人數 n
  2. n == 0,輸出 人數必須大於 0 並結束。
  3. 使用 new int[n]{} 建立成績陣列。
  4. 讀入 n 個 0~100 的整數成績。
  5. 輸出平均,保留小數點後兩位。
  6. 使用 delete[] 釋放,再將指標設為 nullptr

輸入限制: 0 <= n <= 1000

範例輸入:

4
80 75 90 65

範例輸出:

平均:77.50

限制: 本題為理解底層配置,不能使用 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. 動態陣列複製

任務說明: 完成函式:

int* cloneArray(const int* source, size_t size);
  • source == nullptrsize == 0 時回傳 nullptr
  • 否則配置一個含 size 個元素的新陣列。
  • 將來源內容逐一複製並回傳新陣列起點。

main() 必須:

  1. 建立 {3, 1, 4, 1, 5}
  2. 呼叫 cloneArray
  3. 將複本的第一個元素改為 99。
  4. 分別輸出來源與複本,證明來源仍以 3 開頭。
  5. delete[] 釋放複本。

預期輸出:

來源:3 1 4 1 5
複本:99 1 4 1 5

所有權契約: 函式回傳的記憶體由呼叫端負責釋放。

#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.