[特殊字符]C 语言一维数组

一、一维数组

1. 定义方式

一维数组是相同类型元素的有序集合。在 C 语言里,有多种定义一维数组的方式。

方式一:指定数组长度并初始化
#include 

int main() {
    // 定义一个包含 5 个整数的数组,并初始化
    int arr[5] = {1, 2, 3, 4, 5};
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

  • 解释int arr[5] 表明定义了一个名为 arr 的数组,它能容纳 5 个整数。{1, 2, 3, 4, 5} 是初始化列表,按顺序给数组元素赋值。
方式二:部分初始化,剩余元素默认初始化为 0

#include 

int main() {
    // 定义一个包含 5 个整数的数组,只初始化前 3 个元素
    int arr[5] = {1, 2, 3};
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

  • 解释:这里只给数组的前 3 个元素赋了值,剩下的 2 个元素会自动初始化为 0。这种方式在你只需要对部分元素赋值时非常方便,但要注意未赋值元素的值为 0。
方式三:省略数组长度,由初始化列表确定长度

#include 

int main() {
    // 定义一个数组,长度由初始化列表确定
    int arr[] = {1, 2, 3, 4, 5};
    int len = sizeof(arr) / sizeof(arr[0]);
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

  • 解释:当省略数组长度时,编译器会根据初始化列表中元素的个数来确定数组的长度。sizeof(arr) / sizeof(arr[0]) 可用于计算数组的长度。这种方式适用于你不确定数组长度,但知道要初始化哪些元素的情况。

2. 数组元素的访问与遍历

数组元素通过下标访问,下标从 0 开始。可以使用循环来遍历数组的所有元素。

#include 

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    // 使用 for 循环遍历数组
    for (int i = 0; i < 5; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }
    return 0;
}

  • 解释for 循环从 0 开始,到数组长度减 1 结束,依次访问数组的每个元素并打印出来。

3. 注意事项与易出错点

  • 数组越界:数组下标从 0 开始,对于长度为 n 的数组,有效下标范围是 0 到 n - 1。若访问超出这个范围的元素,就会引发数组越界错误。

#include 

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    // 错误示例:访问越界
    printf("%d", arr[5]); 
    return 0;
}

  • 未初始化数组:若数组未初始化,其元素的值是不确定的,可能包含垃圾数据。在使用数组前,最好进行初始化。

#include 

int main() {
    int arr[5];
    // 未初始化数组,元素值不确定
    printf("%d", arr[0]); 
    return 0;
}

  • 内存分配问题:数组在定义时需要分配连续的内存空间,如果数组长度过大,可能会导致内存不足的问题。在实际应用中,要根据需要合理分配数组的长度。

4. 数组作为实参传递方式

在 C 语言中,数组作为实参传递时,传递的是数组首元素的地址,也就是数组名代表数组首元素的地址。

#include 

// 函数接收数组作为参数
void printArray(int arr[], int len) {
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
}

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int len = sizeof(arr) / sizeof(arr[0]);
    // 传递数组名作为实参
    printArray(arr, len); 
    return 0;
}

  • 解释printArray 函数接收一个整型数组和数组的长度作为参数。在 main 函数中,将数组名 arr 传递给 printArray 函数,实际上传递的是数组首元素的地址。需要注意的是,在函数内部无法通过 sizeof 运算符获取数组的长度,因为 sizeof(arr) 此时返回的是指针的大小,而不是数组的实际大小,所以需要额外传递数组的长度作为参数。

5. 一维数组作为形参

形式一:指定数组大小

#include 

// 函数定义,指定数组大小为5
void printArray(int arr[5]) {
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    printArray(arr);
    return 0;
}

解释:在函数定义中明确指定了数组的大小为 5。不过,在 C 和 C++ 里,这个指定的大小仅作参考,并不会对传入的数组大小进行严格检查。实际上,数组名传递的是数组首元素的地址,函数内部无法直接获取数组的真实大小。

形式二:不指定数组大小

#include 

// 函数定义,不指定数组大小
void printArray(int arr[]) {
    // 这里无法直接获取数组大小,需要额外传入
    int size = 5;
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    printArray(arr);
    return 0;
}

解释:这种形式更为常见,函数定义时不指定数组大小。在函数内部,若要遍历数组,就需要额外传入数组的大小。

形式三:使用指针形式

#include 

// 函数定义,使用指针形式
void printArray(int *arr, int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int size = sizeof(arr) / sizeof(arr[0]);
    printArray(arr, size);
    return 0;
}

解释:本质上,数组名就是数组首元素的地址,所以可以用指针来接收数组。这种形式和不指定数组大小的形式是等价的,并且同样需要额外传入数组的大小。

6. 一维数组的应用场景

  • 数据存储:可以用来存储一组相关的数据,如学生的成绩、员工的工资等。

#include 

int main() {
    int scores[5] = {80, 90, 75, 85, 95};
    for (int i = 0; i < 5; i++) {
        printf("学生 %d 的成绩是: %d\n", i + 1, scores[i]);
    }
    return 0;
}

  • 算法实现:在排序算法(如冒泡排序、选择排序)中,一维数组是常用的数据结构。

#include 

// 冒泡排序函数
void bubbleSort(int arr[], int len) {
    for (int i = 0; i < len - 1; i++) {
        for (int j = 0; j < len - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

int main() {
    int arr[5] = {5, 3, 8, 4, 2};
    int len = sizeof(arr) / sizeof(arr[0]);
    bubbleSort(arr, len);
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

二、字符数组

1. 定义与初始化

字符数组用于存储字符序列,通常用来表示字符串。以下是几种常见的定义和初始化方式:

方式一:逐个字符初始化
#include 

int main() {
    // 定义一个字符数组,逐个字符初始化
    char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
    printf("%s\n", str);
    return 0;
}

  • 解释:这里定义了一个长度为 6 的字符数组,存储了字符串 "Hello"。注意,字符串以 '\0'(空字符)结尾,它标志着字符串的结束。
方式二:用字符串字面量初始化
#include 

int main() {
    // 用字符串字面量初始化字符数组
    char str[] = "Hello";
    printf("%s\n", str);
    return 0;
}

  • 解释:使用字符串字面量初始化字符数组时,编译器会自动在字符串末尾添加 '\0'。数组的长度会根据字符串的长度自动确定。

2. 字符数组的输入与输出

输出

可以使用 printf 函数和 %s 格式说明符输出字符数组表示的字符串。

#include 

int main() {
    char str[] = "Hello";
    printf("%s\n", str);
    return 0;
}
输入

可以使用 scanf 函数或 gets(不推荐,存在缓冲区溢出风险)、fgets 函数来输入字符串。

#include 

int main() {
    char str[100];
    // 使用 fgets 函数输入字符串
    fgets(str, sizeof(str), stdin);
    printf("你输入的字符串是: %s", str);
    return 0;
}

  • 解释fgets 函数会读取最多 sizeof(str) - 1 个字符,并在末尾添加 '\0'。如果读取到换行符,也会将其包含在字符串中。

3. 注意事项与易出错点 

核心要点11

  1. 定义方式

    • int arr[5] = {1,2,3,4,5};
    • int arr[5] = {1,2}; 剩余元素自动补 0
    • int arr[] = {1,2,3}; 长度由初始化列表决定
  2. 访问与遍历

    • 下标从 0 开始:arr[0]为第一个元素
    • 遍历常用:

      c

      for(int i=0; i
  3. 数组传参

    • 传递首地址:void func(int arr[])
    • 需额外传递长度:func(arr, sizeof(arr)/sizeof(arr[0]))

高危陷阱

  1. 越界访问
    ❌ int arr[5]; arr[5] = 10;(下标最大为 4)

  2. 未初始化数组
    ❌ int arr[5]; printf("%d", arr[0]);(值随机)

  3. 内存分配超限
    ❌ int arr[10000000];(可能导致栈溢出)

核心要点22

  1. 字符串特性

    • 必须以\0结尾:char str[] = "Hello";(自动补\0
    • 长度计算:strlen(str)(不包含\0
  2. 输入输出

    • 安全输入:fgets(str, sizeof(str), stdin);
    • 输出:printf("%s", str);

高危陷阱

  1. 缺失结束符
    ❌ char str[5] = {'H','e','l','l','o'};(输出乱码)

  2. 缓冲区溢出
    ❌ char str[5]; scanf("%s", str);(输入超过 4 字符会溢出)

  3. 字符串函数误用
    ❌ strcpy(dest, src);(需确保src\0结尾且dest空间足够)

对比速查表

特性 一维数组 字符数组
初始化 int arr[5] = {1,2,3}; char str[] = "Hello";
结束符 必须\0
长度计算 sizeof(arr)/sizeof(arr[0]) strlen(str)
输入函数 直接赋值 fgets()推荐,scanf()危险

学习建议

  1. 数组越界:始终检查下标范围,避免 “差一错误”
  2. 字符数组:所有字符串操作必须以\0为终点
  3. 传参规范:数组传参必带长度,避免 “野指针” 风险

现在你已掌握

你可能感兴趣的:(C语言基础,算法,数据结构,排序算法,c语言,c++,visual,studio)