使用指针进行数组遍历

C 语言Beginner
立即练习

介绍

指针算术是 C 语言中的一项强大功能,它允许你通过加或减数值来操作内存地址。指针算术最常见的应用之一是数组遍历。使用指针,我们可以高效地在数组中向前和向后移动。

在这个实验中,你将学习如何创建和初始化数组、设置指针来访问数组元素,以及使用指针算术来遍历数组。这项技术是 C 语言编程的基础,也是许多高级数据操作的基础。

创建一个基本的 C 程序

让我们先在 VSCode 编辑器中创建一个新的 C 文件。这个文件将包含我们使用指针进行数组遍历的主程序。

  1. 在 WebIDE 中,找到左侧的资源管理器面板,然后导航到 ~/project 目录。

  2. 右键单击 project 文件夹,选择“新建文件”。将文件命名为 main.c

  3. 将以下基本的 C 程序结构复制到文件中:

#include <stdio.h>

int main() {
    printf("Array Traversal using Pointers\n");

    return 0;
}
  1. 按 Ctrl+S 或通过菜单选择“文件”>“保存”来保存文件。

  2. 让我们编译并运行这个程序,以确保一切设置正确。通过菜单选择“终端”>“新建终端”在 WebIDE 中打开一个终端,然后运行:

cd ~/project
gcc main.c -o main
./main

你应该会看到以下输出:

Array Traversal using Pointers

这确认了你的 C 开发环境正在正常工作。在接下来的步骤中,我们将修改这个程序以处理数组和指针。

声明和初始化数组与指针

在这一步中,我们将学习如何声明数组和指针,它们是使用指针进行数组遍历的基本组成部分。

理解数组和指针

C 语言中的数组是存储在连续内存位置的相同类型元素的集合。例如,一个包含 5 个元素的整数数组将在内存中依次为 5 个整数预留空间。

指针是一个存储另一个变量内存地址的变量。我们可以使用指针间接访问存储在特定内存地址的值。

让我们修改 main.c 文件,使其包含一个数组和一个指针:

#include <stdio.h>

int main() {
    printf("Array Traversal using Pointers\n\n");

    // Declare and initialize an array of 5 integers
    int arr[5] = {10, 20, 30, 40, 50};

    // Declare a pointer of integer type
    int *ptr;

    // Print the array elements using array notation
    printf("Array elements using array notation:\n");
    for(int i = 0; i < 5; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }

    return 0;
}

在这段代码中:

  • 我们声明了一个包含 5 个元素的整数数组 arr,并将其初始化为 10、20、30、40 和 50。
  • 我们声明了一个整数指针 ptr,稍后将用它来指向数组元素。
  • 我们使用传统的数组表示法打印了数组元素。

编译并运行程序以查看数组元素:

gcc main.c -o main
./main

你应该会看到以下输出:

Array Traversal using Pointers

Array elements using array notation:
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40
arr[4] = 50

在下一步中,我们将把指针与数组关联起来,并使用指针访问数组元素。

将指针与数组关联并进行正向遍历

在这一步中,我们将建立指针与数组之间的联系,然后使用指针正向遍历数组。

将指针与数组连接

在 C 语言中,不带下标的数组名代表数组第一个元素的地址。这意味着我们可以直接将这个地址赋值给指针变量。

让我们修改 main.c 文件,将指针与数组关联起来并进行遍历:

#include <stdio.h>

int main() {
    printf("Array Traversal using Pointers\n\n");

    // Declare and initialize an array of 5 integers
    int arr[5] = {10, 20, 30, 40, 50};

    // Declare a pointer of integer type
    int *ptr;

    // Assign the address of the first element of the array to the pointer
    ptr = arr;  // This is equivalent to ptr = &arr[0]

    // Print the array elements using array notation
    printf("Array elements using array notation:\n");
    for(int i = 0; i < 5; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }

    // Print the array elements using pointer notation
    printf("\nArray elements using pointer notation (forward traversal):\n");
    for(int i = 0; i < 5; i++) {
        printf("*(ptr + %d) = %d\n", i, *(ptr + i));
    }

    return 0;
}

在这段更新后的代码中:

  • 我们将数组 arr 第一个元素的地址赋值给了指针 ptr
  • 我们添加了一个新的循环,使用指针算术来遍历数组。
  • 表达式 *(ptr + i) 访问的是内存位置 ptr + i 处的值。当 i 为 0 时,访问的是数组的第一个元素;当 i 为 1 时,访问的是第二个元素,依此类推。

编译并运行程序以查看结果:

gcc main.c -o main
./main

你应该会看到以下输出:

Array Traversal using Pointers

Array elements using array notation:
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40
arr[4] = 50

Array elements using pointer notation (forward traversal):
*(ptr + 0) = 10
*(ptr + 1) = 20
*(ptr + 2) = 30
*(ptr + 3) = 40
*(ptr + 4) = 50

注意,这两种方法产生的输出是相同的。这表明指针算术可以像传统的数组索引一样用于访问数组元素。

实现用于数组遍历的指针递增

在上一步中,我们使用表达式 *(ptr + i) 来访问数组元素。虽然这种方法完全可行,但 C 语言提供了一种更简洁的方式来使用指针遍历数组:自增运算符 (++)。

当我们对指针进行自增操作时,它会根据所指向的数据类型的大小移动到下一个内存位置。对于整数指针,对其进行自增操作会使其移动到内存中的下一个整数位置。

让我们修改 main.c 文件,使用指针自增来遍历数组:

#include <stdio.h>

int main() {
    printf("Array Traversal using Pointers\n\n");

    // Declare and initialize an array of 5 integers
    int arr[5] = {10, 20, 30, 40, 50};

    // Declare and initialize a pointer to the first element of the array
    int *ptr = arr;  // Same as ptr = &arr[0]

    // Print the array elements using pointer incrementation
    printf("Array elements using pointer incrementation:\n");
    for(int i = 0; i < 5; i++) {
        printf("*ptr = %d\n", *ptr);
        ptr++;  // Move the pointer to the next element
    }

    // Reset the pointer to the beginning of the array
    ptr = arr;

    // Print all elements in a single line using pointer incrementation
    printf("\nAll elements in a single line: ");
    for(int i = 0; i < 5; i++) {
        printf("%d ", *ptr++);  // Print and then increment
    }
    printf("\n");

    return 0;
}

在这段更新后的代码中:

  • 我们在声明指针 ptr 时直接对其进行初始化。
  • 在第一个循环中,我们使用 *ptr 来访问当前元素,然后使用 ptr++ 移动到下一个元素。
  • 第一个循环结束后,我们将 ptr 重置为指向数组的起始位置。
  • 在第二个循环中,我们使用后置自增运算符 *ptr++,它会先使用 ptr 的当前值,然后再对其进行自增操作。

编译并运行程序以查看结果:

gcc main.c -o main
./main

你应该会看到以下输出:

Array Traversal using Pointers

Array elements using pointer incrementation:
*ptr = 10
*ptr = 20
*ptr = 30
*ptr = 40
*ptr = 50

All elements in a single line: 10 20 30 40 50

这展示了如何使用指针自增来遍历数组。关键在于 ptr++ 在移动到下一个元素时会自动考虑数据类型的大小。

使用指针递减实现反向遍历

在前面的步骤中,我们已经学习了如何正向遍历数组。现在,让我们来学习如何使用指针递减来反向遍历数组。

要进行反向遍历,你需要:

  1. 初始化指针,使其指向数组的最后一个元素。
  2. 递减指针,从而反向遍历数组。

让我们修改 main.c 文件来实现反向遍历:

#include <stdio.h>

int main() {
    printf("Array Traversal using Pointers\n\n");

    // Declare and initialize an array of 5 integers
    int arr[5] = {10, 20, 30, 40, 50};

    // Forward traversal using pointer increment
    int *ptr = arr;
    printf("Forward traversal using pointer increment:\n");
    for(int i = 0; i < 5; i++) {
        printf("%d ", *ptr);
        ptr++;
    }
    printf("\n\n");

    // Backward traversal using pointer decrement
    // Point to the last element of the array
    ptr = &arr[4];  // or ptr = arr + 4

    printf("Backward traversal using pointer decrement:\n");
    for(int i = 0; i < 5; i++) {
        printf("%d ", *ptr);
        ptr--;  // Move the pointer to the previous element
    }
    printf("\n\n");

    // Alternative approach: Start from the last element and decrement in the loop condition
    printf("Alternative backward traversal approach:\n");
    for(ptr = &arr[4]; ptr >= arr; ptr--) {
        printf("%d ", *ptr);
    }
    printf("\n");

    return 0;
}

在这段更新后的代码中:

  • 首先,我们使用指针递增进行正向遍历。
  • 对于反向遍历,我们使用 ptr = &arr[4] 将指针设置为指向数组的最后一个元素。
  • 在循环内部,我们打印当前元素,然后使用 ptr-- 递减指针。
  • 我们还展示了另一种方法,即将递减操作作为 for 循环更新语句的一部分。

编译并运行程序以查看结果:

gcc main.c -o main
./main

你应该会看到以下输出:

Array Traversal using Pointers

Forward traversal using pointer increment:
10 20 30 40 50

Backward traversal using pointer decrement:
50 40 30 20 10

Alternative backward traversal approach:
50 40 30 20 10

这展示了如何使用指针算术来正向和反向遍历数组。通过递增和递减指针,你可以轻松地在数组中向任意方向移动。

总结

在本次实验中,你学习了如何在 C 语言编程中使用指针来遍历数组。以下是我们涵盖的关键概念:

  1. 数组和指针基础

    • C 语言中的数组将元素存储在连续的内存位置中。
    • 指针存储内存地址,并可用于访问这些位置。
  2. 指针与数组的关系

    • 数组名(不带索引)代表数组第一个元素的地址。
    • 我们可以将这个地址赋值给指针,从而建立与数组的连接。
  3. 正向遍历技术

    • 使用指针算术:*(ptr + i)
    • 使用指针递增:先使用 *ptr,再使用 ptr++
    • 结合解引用和递增操作:*ptr++
  4. 反向遍历技术

    • 将指针初始化为指向数组的最后一个元素:ptr = &arr[size-1]
    • 使用指针递减:ptr-- 以反向移动指针
    • 循环条件可以检查指针何时到达数组的起始位置

指针算术是 C 语言中的一项强大功能,它能够实现高效的内存操作,并在处理数组和其他数据结构时提供灵活性。这种技术是更高级编程概念(如动态内存分配、链表和其他复杂数据结构)的基础。