【C学习】13-数组使用与运算

"知道做不到就是不知道"

一、初始数组

思考一个问题,之前我们声明的变量都是一个一个的,那思考一下,如果要存储一个班级30个人的成绩该怎么办?难道要单独设置30个变量吗?

bash 复制代码
float mark1 = 90;
float mark2 = 90;
float mark3 = 90;

......

float mark29 = 90;
float mark30 = 90;

这样既浪费时间又浪费空间,于是这里提到另一种变量类型------**数组,**方便的同时存储多个同类型数据。

其使用过程如下:

(1)定义数组:类型名 变量名[数字],如 int a[10];

(2)遍历数组:打印或者继续使用

(3)对数组中的元素赋值:要用到循环

(4)使用数组中的元素:可以做判断、做运算等

二、数组使用方法

(一)基本定义

数组是C语言中一种重要的构造数据类型,它允许我们将多个相同类型的变量组织在一起,形成一个有序的集合。通过使用一个统一的名称(数组名)和下标(索引)来管理这些数据。

cs 复制代码
//<类型> 变量名称[元素数量];


// 完全初始化
int arr1[5] = {1, 2, 3, 4, 5};

// 部分初始化(未初始化的元素自动设为0)
int arr2[5] = {1, 2}; // 结果为:1, 2, 0, 0, 0

// 自动确定数组大小
int arr3[] = {1, 2, 3}; // 编译器自动确定数组长度为3

// C99指定的初始化器
int arr4[10] = {[2] = 5, [5] = 10}; // 只初始化特定位置的元素

定义一个整型数组:int arr[10];这就创建了一个名为arr的数组,它可以存储10个整数。

关于元素数量的说明:在C99标准之前,数组的大小必须是常量表达式。但从C99标准开始,支持使用变量来定义数组的大小,这就是​​变长数组(Variable-Length Array, VLA)​,如:int n = 10; int arr[n];

需要注意的是,变长数组的长度在数组创建后就是固定的,并非可以随时改变。

(二)核心特点

数组可以理解为一个​​容器​​,具有以下重要特性:

  1. 元素类型统一:数组中所有元素必须具有相同的数据类型
  2. 大小固定:数组一旦创建,其大小就不能改变
  3. 内存连续:数组中的元素在内存中是连续依次排列的

对于int a[10]这样的整型数组:

  • 数组元素可以出现在赋值的左边(作为左值,被赋值)和右边(作为右值,参与表达式计算)
  • 十个数组单元分别是a[0], a[1], a[2], ..., a[9],每个单元都是一个int类型的变量
  • 下标(也称为"索引")从0开始,这是C语言数组的一个重要特点

(三)数组下标的有效范围与越界问题

​​有效的下标范围​​是编程中需要特别注意的问题。关于长度为零的数组:C语言允许定义长度为0的数组,如int a[0],但这种数组实际上没有什么实用价值。

对于int a[10]这样的数组:

  • 有效下标范围是[0, 9],即从0到数组大小减1
  • 数组中不存在a[10]这个元素,最后一个有效元素是a[9]
  • 编译器和运行环境都不会检查数组下标是否越界,无论是对数组单元进行读还是写操作
  • 程序员需要自己保证只使用有效的下标值,否则可能导致未定义行为
  • 使用sizeof(arr) / sizeof(arr[0])来计算数组长度,提高代码的可维护性

(四)例子:统计个数

1. 写一个程序输入[0,9]范围内的整数,统计每一种数字出现的次数,输入-1表示结束。

2. 包括的部分:

a) 定义数组,数组的大小用const类型声明;

b) 利用for循环,初始化数组为0;

c) 数组参与运算;

d) 遍历数组并输出。

cs 复制代码
#include <stdio.h>

int main() {
    // a) 定义数组,数组的大小用const类型声明
    const int ARRAY_SIZE = 10;
    int count[ARRAY_SIZE];
    
    // b) 利用for循环,初始化数组为0
    for(int i = 0; i < ARRAY_SIZE; i++) {
        count[i] = 0;
    }
    
    int input;
    printf("请输入[0,9]范围内的整数(输入-1结束):");
    scanf("%d", &input);
    
    // c) 数组参与运算 - 统计每个数字出现的次数
    while(input != -1) {
        if(input >= 0 && input <= 9) {
            count[input]++;  // 对应数字的计数加1
        } else {
            printf("输入超出范围,请重新输入[0,9]的整数或-1结束:");
        }
        scanf("%d", &input);
    }
    
    // d) 遍历数组并输出结果
    printf("\n统计结果:\n");
    for(int i = 0; i < ARRAY_SIZE; i++) {
        printf("数字 %d 出现了 %d 次\n", i, count[i]);
    }
    
    return 0;
}



/*
请输入[0,9]范围内的整数(输入-1结束):
3
5
2
3
5
5
7
-1

统计结果:
数字 0 出现了 0 次
数字 1 出现了 0 次
数字 2 出现了 1 次
数字 3 出现了 2 次
数字 4 出现了 0 次
数字 5 出现了 3 次
数字 6 出现了 0 次
数字 7 出现了 1 次
数字 8 出现了 0 次
数字 9 出现了 0 次
*/

三、数组运算

1. 初始化数组

参照"二、(四)"。

2. 确定数组元素数量

在处理数组时,经常需要知道数组包含多少元素。​​sizeof运算符​​可以计算整个数组占用的字节数。用数组总字节数除以单个元素的字节数,就能得到元素个数:

cs 复制代码
int arr[] = {1, 2, 3, 4, 5};
int length = sizeof(arr) / sizeof(arr[0]); // 计算数组元素个数

需要注意的是,​​sizeof是编译时运算符​​,不会执行括号内的表达式。例如:

cs 复制代码
int a = 6;
sizeof(a++); // 执行后a的值仍是6,不是7

当表达式中包含不同类型时,sizeof会按类型提升规则计算大小:

cs 复制代码
int a = 6;
sizeof(a + 1.0); // 结果为8,因为a转换为double类型(占4个字节)

3. 数组的赋值与遍历

数组不能直接使用赋值运算符​​进行整体赋值,必须通过循环逐个元素处理:

cs 复制代码
int source[] = {1, 2, 3, 4, 5};
int dest[5];

// 正确的赋值方法:使用for循环
for(int i = 0; i < 5; i++) {
    dest[i] = source[i];
}

遍历数组时的注意事项​:确保循环变量在退出循环后不会被误用为数组下标,这可能导致数组越界访问。

4. 数组元素的运算

数组元素可以参与各种算术和逻辑运算,这是数组计算的核心。

(1)基本算术运算​​:可以对数组元素进行加、减、乘、除等操作

cs 复制代码
int arr[5] = {1, 2, 3, 4, 5};

// 对每个元素进行算术运算
for(int i = 0; i < 5; i++) {
    arr[i] = arr[i] * 2 + 1; // 先乘2再加1
}

(2)​​逻辑运算​​:数组元素也可以用于条件判断

cs 复制代码
if(arr[0] > 0 && arr[1] > 0) {
    // 执行操作
}

(3)边界条件处理​​:特别是进行除法运算时,需要检查除数是否为零

cs 复制代码
for(int i = 0; i < size; i++) {
    if(arr[i] != 0) {
        result[i] = 100 / arr[i];
    } else {
        printf("除零错误发生在索引%d\n", i);
    }
}

5. 数组作为函数参数

将数组传递给函数时,需要特别注意:

  • 函数参数中的数组声明不需要指定大小
  • 必须额外传递一个参数表示数组大小
  • 函数内部无法使用sizeof计算数组元素个数
cs 复制代码
// 正确的函数声明方式
int sumArray(int arr[], int size) {
    int sum = 0;
    for(int i = 0; i < size; i++) {
        sum += arr[i];
    }
    return sum;
}

// 调用函数
int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int total = sumArray(numbers, 5); // 必须传入数组大小
    return 0;
}

6. 在数组中查找元素

查找是数组最常见的操作之一,主要有以下几种方法:

**(1)线性查找:**最简单直接的查找方法,适用于未排序数组。

cs 复制代码
int linearSearch(int arr[], int size, int target) {
    for(int i = 0; i < size; i++) {
        if(arr[i] == target) {
            return i; // 返回找到的索引
        }
    }
    return -1; // 未找到
}

(2)二分查找​​:针对已排序数组的高效查找算法

cs 复制代码
int binarySearch(int arr[], int size, int target) {
    int left = 0, right = size - 1;
    while(left <= right) {
        int mid = left + (right - left) / 2;
        if(arr[mid] == target) return mid;
        else if(arr[mid] < target) left = mid + 1;
        else right = mid - 1;
    }
    return -1;
}

写在最后:

更新C语言学习笔记

如有错误,烦请多多批评指正!

相关推荐
张人玉20 分钟前
c#串口读写威盟士五插针
开发语言·c#·通讯
Thexhy37 分钟前
在 CentOS 7 的 Linux 系统中配置 NFS
linux·运维·学习·centos
睡前要喝豆奶粉1 小时前
在.NET Core Web Api中使用redis
redis·c#·.netcore
CodeLongBear2 小时前
计算机网络学习笔记 | 传输层核心知识点总结(DAY03,匠心制作)
笔记·学习·计算机网络
晓北斗NorSnow2 小时前
机器学习核心算法与学习资源解析
学习·算法·机器学习
偶尔的鼠标人2 小时前
SqlSugar查询字符串转成Int的问题
c#·sqlsugar
我不是程序猿儿2 小时前
【C#】WinForms 控件句柄与 UI 刷新时机
开发语言·ui·c#
wdfk_prog3 小时前
[Linux]学习笔记系列 -- [kernel][time]tick
linux·笔记·学习
我命由我123454 小时前
Photoshop - Photoshop 工具栏(22)单行选框工具
学习·ui·职场和发展·求职招聘·职场发展·学习方法·photoshop
User_芊芊君子5 小时前
【成长纪实】我的鸿蒙成长之路:从“小白”到独立开发,带你走进鸿蒙的世界
学习·华为·harmonyos·鸿蒙开发