学习笔记 | C语言中的数组

数组的概念

数组是一组相同类型元素的集合;

  • 数组中存放的是1个或多个数据,但是数组元素个数不能为 0 。
  • 数组中存放的多个数据,类型是相同的。

数组可以分为一维数组,多维数组;常见的是二维数组。

一维数组

创建和初始化

ini 复制代码
type arr_name[常量值];
​
数组类型 数组名称[元素个数];

存放在数组的值被称为数组的元素,数组在创建的时候可以指定数组的大小和数组的元素类型。

数组的创建

ini 复制代码
int math[20];

数组的初始化

csharp 复制代码
int main()
{
    int num[5] = {1,2,3,4,5};//完全初始化:创建数组,并且初始化1,2,3,4,5
    
    int num2[5] = {1,2,3};//不完全初始化,剩余的元素初始化为 0
    
    int num3[] = {1,2,3};//如果数组初始化了,是可以省略数组大小
    //数组的大小,编译器根据初始化的内容确定
    
    int num4[5] = {1,2,3,4,5,6};//报错
    return 0;
}

数组的类型

数组属于自定义类型。

csharp 复制代码
int main()
{
    int num[5] = {1,2,3,4,5}; //num1的类型是 int [5]
    
    int num2[10] = {1,2,3}; //num2的类型是 int [10]
    
    int num3[] = {1,2,3};
    
    return 0;
}

一维数组的使用

数组下标

arduino 复制代码
int arr[10] = {1,2,3,4,5,6,7,8,9,10};//对应的下标是 0 ~ 9
  • 下标是从0开始,最后一个元素的下标是n-1
  • C 语言中使用下标访问数组中的数据
  • 为下标访问操作符
ini 复制代码
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
    //打印 7
    printf("%d\n", arr[6]);
​
    int i = 0;
    //循环打印所有数组
    for (i = 0; i < 10;i++)
    {
        printf("%d ", arr1[i]);
    }
​
​
    return 0;
}

执行结果

C99标准之前,数组的大小只能是常量指定

数组在内存中的存储

观察数字在内存中的地址

ini 复制代码
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int i = 0;
    //循环打印所有数组
    for (i = 0; i < 10;i++)
    {
        printf("arr[%d] = %pn",i &arr1[i]);// %p 用来打印地址
    }
​
    return 0;
}

执行结果

  • 一维数组在内存中是连续存放的
  • 随着下标的增长,地址也是增长

sizeof计算数组的长度

c 复制代码
int main()
{
    int arr[10] = { 1,2,3 };//10 * 4
    printf("%d\n", sizeof(arr));//sizeof(数组)计算的是数组所占内存空间的大小,单位是字节
    printf("%d\n", sizeof(arr[0]));
    printf("%d\n", sizeof(arr) / sizeof(arr[0]));
    int sz = sizeof(arr) / sizeof(arr[0]);
    int i = 0;
    //循环打印所有数组
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
​
​
    }
    return 0;
}

执行结果

此时,数组元素个数的变化并不会影响代码的运行。

二维数组的创建初始化

如果把一维数组作为数组的元素,那就是二维数组。

二维数组的创建

ini 复制代码
type arr_name[常量值1][常量值2];
//例如
int arr [3][5];
  • 3 表示数组有 3 行
  • 5 表示每一行有 5 个元素
csharp 复制代码
int main()
{
    double score[20][5];
    
    return 0;
}

全初始化

ini 复制代码
int main()
{
    //不完全初始化
    int score1[3][5] = {1,2};
    int score2[3][5] = {0};
    int score3[3][5] = {1,2,3,4,5,6,7};
    int score3[3][5] = {{1,2},{3,4},{5,6}};//指定1,2放入第一行,3,4放入第二行;以此类推
    //完全初始化
    int score4[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
    return 0;
}

二维数组初始化时,行可以省略,但是列不能省略

csharp 复制代码
int main()
{
    int score1[][5] = {1,2}; //初始化了一行
    int score3[][5] = {1,2,3,4,5,6,7};//初始化了两行
    int score3[][5] = {{1,2},{3,4},{5,6}};//初始化了三行
    return 0;
}

打印指定数组和所有数组

三行五列的数组:[3][5]

下标 0 1 2 3 4
0 1 2 3 4 5
1 2 3 4 5 6
2 3 4 5 6 7
ini 复制代码
int main()
{
    int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
    printf("%d\n", arr[1][3]);//打印第二行第四个数字 5
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        int j = 0;
        for (j = 0; j < 5; j++)
        {
            printf("%d", arr[i][j]);
        }
        printf("\n");
​
    }
​
    return 0;
}

执行结果

二维数组在内存中也是连续存放的。

arr1[]

arr2[][]

C99中的变长数组

在C99标准之前,C语言在创建数组的时候,数组大小的指定只能使用常量、常量表达式,或者如果我们初始化数据的话,可以省略数组大小。

如:

ini 复制代码
int arr1[10];
int arr2[3+5];
int arr3[] = {1,2,3};

C99标准之后,引入了变长数组的概念,允许数组的大小是变量。

arduino 复制代码
int main()
{
    int n = 0;
    scanf("%d",&n);
    int arr[n];
    return 0;
}
  • VS虽然支持了C99的语法,但是并不是完全支持。比如变长数组。
  • 变长数组不能初始化

变长数组中,变长的概念是数组的长度可以引用变量,而不仅仅使用常量。并不是说数组可以任意改变其大小。

数组练习

多个字符从两端移动,向中间汇聚

打印内容如下:welcome to C !!!!!!!!!!

markdown 复制代码
//***********************
//w*********************!
//we*******************!!
//以此类推,最终打印
//welcome to C !!!!!!!!!!

代码实现

ini 复制代码
#include <string.h>
int main()
{
    char arr1[] = "welcome to C !!!!!!!!!!";
    char arr2[] = "***********************";
    
    int left = 0;
    int right = strlen(arr1)-1;
    
    while(left<=right)
    {
        arr2[left] = arr1[left];
        arr2[right] = arr1[right];
        printf("%s\n",arr2);
        left++;
        right--;
    }
    return 0;
}

执行结果

添加动态效果

  • Sleep(1000); //休眠一秒。需要引入头文件,windows.h

在一行上像两端移动

  • system("cls");

最终代码

scss 复制代码
#include <string.h>
int main()
{
    char arr1[] = "welcome to C !!!!!!!!!!";
    char arr2[] = "***********************";
    
    int left = 0;
    int right = strlen(arr1)-1;
    
    while(left<=right)
    {
        arr2[left] = arr1[left];
        arr2[right] = arr1[right];
        printf("%s\n",arr2);
        Sleep(1000);
        system("cls");
        left++;
        right--;
    }
    printf("%s\n",arr2);
    return 0;
}

动态效果,自行验证。

二分查找

在一个指定的有序数组中查找指定的数字n,也叫折半查找。

例如:

int arr[] = {1,2,3,4,5,6,7,8,9,10};

int k = 7;

在arr数组中,找 7

遍历查找法

ini 复制代码
int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int k = 0;
    scanf("%d", &k);
    int i = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);
    int find = 0;//假设找不到
    for (i = 0; i < sz; i++)
    {
        if (k == arr[i])
        {
            printf("找到了,下标是%d\n", i);
            find = 1;
            break;
        }
    }
    if (find == 0)
    {
        printf("找不到\n");
    }
    return 0;
}

执行结果

二分查找算法

ini 复制代码
Mid = (L + R)/2;
  • Mid:中间位
  • L:最左下标
  • R:最右下标

代码

ini 复制代码
int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int k = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);
    scanf("%d", &k);
    //使用二分查找
    int left = 0;
    int right = sz - 1;
    int find = 0;//假设找不到
​
    
    while (left <= right)
    {
        //int mid = (left + right) / 2;//这种写法在left和right都非常大,接近int的最大值的时候会有问题.
        int mid = left + (right - left) / 2;
        if (arr[mid] < k)
        {
            left = mid + 1;
        }
        else if (arr[mid] > k)
        {
            right = mid - 1;
        }
        else
        {
            printf("找到了,下标是%d\n", mid);
            find = 1;
            break;
        }
    }
    if (find == 0)
    {
        printf("找不到了");
    }
    return 0;
}

执行结果

注意:

二分查找的前提条件是数组必须是有序的

时间复杂度为O(Log₂n)

相关推荐
charlie1145141912 天前
从0开始的构建的天气预报小时钟(基于STM32F407ZGT6,ESP8266 + SSD1309)——第2章——构建简单的ESP8266驱动
stm32·单片机·物联网·学习·c·esp8266
易保山6 天前
MIT6.S081 - Lab6 Copy-on-Write(写时复制)
linux·操作系统·c
Ronin-Lotus7 天前
嵌入式硬件篇---USB&UART串口
嵌入式硬件·c·uart·usb
易保山8 天前
MIT6.S081 - Lab5 Lazy(延迟分配)
linux·操作系统·c
郭源潮18 天前
《八大排序算法》
数据结构·算法·排序算法·c
努力努力再努力wz11 天前
【c++深入系列】:类与对象详解(上)
java·运维·服务器·开发语言·c++·c
易保山12 天前
MIT6.S081 - Lab4(Trap)实验笔记
linux·操作系统·c
易保山15 天前
MIT6.S081 - Lab3(页表)实验笔记
linux·操作系统·c
Ronin-Lotus15 天前
嵌入式硬件篇---蓝牙模块
网络·嵌入式硬件·c·蓝牙
大小胖虎15 天前
专业课笔记——(第一章:C、C++基础知识)
c++·笔记·算法·c·数据类型·操作类型