C语言第四章之数组

 数组

数组是一种构造类型, 是由基本类型构造而成, 当我们想用一群变量来描述同一类相同的东西的时候, 比如100个年龄变量, 我们可以这样, int age 1; int age 2; int age 3......int age 100; 这样极不方便书写, 也不方便管理, 此时神奇的数组就出现了, int age[100], 轻轻松松搞定。

        构造类型带来了书写和管理的方便, 我们将从定义, 大小, 初始化,访问内容进行展开...

1. 基本语法

#include <stdio.h>

int main()
{
    // 数组类型统一

    // 定义格式: 类型 数组名 [大小]
    int arr[10];
    // 数组也是有长度的
    printf("len = %d\n", sizeof(arr));
    // 数组的长度 = 总占用字节数 / 类型的字节数
    printf("%d\n", sizeof(arr[0]));
    printf("%d\n", sizeof(arr) / sizeof(arr[0]));
    

    return 0;
}

2.  数组的初始化和赋值

  • 在定义数组的同时进行赋值,称为初始化

  • 全局数组若不初始化,编译器将其初始化为零

  • 局部数组若不初始化,内容为随机值

凡是构造类型,要么在初始化的时候初始化, 要么对集合中的每个元素单独初始化。定义以后,不可以再以初始化的方式初始化。凡是基础数据类型,既可以在定义的时候初始化,也可以先定义后初始化。

#include <stdio.h>

int arr8[10];

int main()
{

    // char str[100] = '123456';
    // printf("%d\n",sizeof(str));

    int arr[10];
    // 获取数组长度
    int len = sizeof(arr) / sizeof(arr[0]);

    for (int i = 0; i < len; i++)
    {
        // 给数组赋值
        arr[i] = i + 5;

        printf("%d = %d\n", i, arr[i]); // 5-14
    }

    // 满初始化(注意C语言不进行越界检查)
    // int arr3[3] = {1, 2, 3};

    // 部分初始化后面默认0
    // int arr[10] = {2,3,4,5};

    // 只定义 不初始化
    int arr5[10]; // 默认随机的数

    int arr2[] = {2, 3, 4, -1, 23, 6};
    int len2 = sizeof(arr2) / sizeof(arr2[0]);
    for (int i = 0; i < len2; i++)
    {
        printf("%d", arr2[i]);
    }

    printf("\n");

    int len8 = sizeof(arr8) / sizeof(arr8[0]);
    for (int i = 0; i < len8; i++)
    {
        printf("%d", arr8[i]);  // 0
    }

    return 0;
}

3. 数组在内存中

  • 数组名是一个地址的常量,代表数组中首元素的地址

  • 一维数组在内存中是一组连续的存储空间

#include <stdio.h>

int main()
{

    // 数据在内存中是一段连续的存储空间

    // 查看数组的地址
    // 整型数组
    int arr[5] = {1, 2, 3, 4, 5};

    int len = sizeof(arr) / sizeof(arr[0]);

    printf("\n");

    for (int i = 0; i < len; i++)
    {
        printf("%p\n", &arr[i]);
    }

    // 数组的地址 = 数组的首个元素的地址
    // printf("arr = %p\n", &arr);
    // printf("arr[0] = %p\n", &arr[0]);

    return 0;
}

4. 数组的案例

4.1 一维数组的最值

#include <stdio.h>

int main()
{
    int arr[] = {1, 2, 4, 34, 12, 88, -2};

    int tempMax = arr[0];

    int tempMin = arr[0];

    int len = sizeof(arr) / sizeof(arr[0]);

    for (int i = 0; i < len; i++)
    {
        if (arr[i] > tempMax)
        {
            tempMax = arr[i];
        }

        if (arr[i] < tempMin)
        {
            tempMin = arr[i];
        }
    }

    printf("max = %d\n", tempMax);
    printf("min = %d\n", tempMin);

    return 0;
}

4.2 一维数组的逆置

#include <stdio.h>

int main()
{

    char arr[] = {'a', 'b', 'c', 'd'};

    // 数组的首元素下标
    int i = 0;
    int j = sizeof(arr) / sizeof(arr[0]) - 1;
    int temp;

    while (i < j)
    {
        // 元素交换
        temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;

        // 下标移动
        i++;
        j--;
    }

    int len = sizeof(arr) / sizeof(arr[0]);
    for (int i = 0; i < len; i++)
    {
        printf("%c", arr[i]);
    }

    return 0;
}

4.3 

5. 数组和指针

5.1 通过指针操作数组元素(重点)

  • 数组名字是数组的首元素地址,但它是一个常量

  • * 和 [] 效果一样,都是操作指针所指向的内存

#include <stdio.h>

int main()
{

    int arr[] = {1, 2, 3, 4, 44, 55, 13, 5};

    printf(" arr = %p\n", &arr[0]);
    int *p = arr;
    printf("p = %p\n", p);

    int len = sizeof(arr) / sizeof(arr[0]);

    for (int i = 0; i < len; i++)
    {
        // printf("arr[%d] = %d", i, arr[i]);
        printf("arr[%d] = %d\n", i, *(arr + i));
    }

    return 0;
}

 1.数组名是一个常量,不允许重新赋值。
 2.指针变量是一个变量,可以重新赋值。
 3.p+i 和 array+i 均表示数组元素 array[i]的地址,均指向 array[i]
 4.*(p+i)和*(array+i)均表示 p+i 和 array+i 所指对象的内容 array[i]。
 5.*p++:等价于*(p++)。其作用:先得到*p,再使 p=p+1。

5.2 数组指针访问

#include <stdio.h>

int main()
{

    int arr[] = {66, 2, 3, 4, 44, 55, 13, 5};

    printf(" arr = %p\n", &arr[0]);
    int *p = arr;
    printf("p = %p\n", p);

    // printf("%d\n", *(arr));  // 第一个值
    // printf("%d\n", *(p));  // 第一个值

    int len = sizeof(arr) / sizeof(arr[0]);

    for (int i = 0; i < len; i++)
    {

        // arr + i 和 p + i 都是指向arr[i]的地址
        // *(arr + i) 和 *(p + i) 都是指向arr[i]
        // *(p++)  == *p ++ 先获取*p, p = p + 1(步长)

        // printf("arr[%d] = %d", i, arr[i]);
        // printf("arr[%d] = %d\n", i, *(arr + i));

        // printf("arrr[%d] = %d\n", i, *(p + i));
        printf("arrr[%d] = %d\n", i, *p++);
    }

    return 0;
}

5.3 指针数组

  • 指针数组,它是数组,数组的每个元素都是指针类型

#include <stdio.h>

int main()
{

    // 指针数组, 是数组, 每个元素都是指针类型

    int *arr[3];
    int a = 10;
    int b = 20;
    int c = 30;

    arr[0] = &a;
    arr[1] = &b;
    arr[2] = &c;

    int len = sizeof(arr) / sizeof(arr[0]);

    for (int i = 0; i < len; i++)
    {
        // 数组的形式
        // printf("%d\n", *(arr[i]));

        // 指针的形式
        // *(arr + i)是地址,再*(解引用操作符)就是值
        // printf("%p\n", *(arr + i));  // 指针
        printf("%d\n", *(*(arr + i)));
    }

    return 0;
}

5.4 数组名做函数参数

  • 数组名做函数参数,函数的形参本质上就是指针

#include <stdio.h>

void show_arr(int *array, int length)
{
    for (int i = 0; i < length; i++)
    {
        // printf("%d\n",array[i]);
        // printf("%d\n", *array++);
        printf("%d\n", *(array + i));
    }
}

int main()
{

    int arr[] = {2, 3, 4, 12, 34, 67, 45};

    int len = sizeof(arr) / sizeof(arr[0]);

    // 数组当成参数传递,可以使用指针的形式访问, 也可以使用原数组的方式访问

    // 传递数组参数时,可以&arr,也可以直接arr
    // 因为我们获取的数组地址,地址常量 = 地址首元素地址
    // 打印数组
    show_arr(arr, len);

    return 0;
}

6. 字符数组与字符串

6.1 字符数组与字符串区别(重点)

  • C语言中没有字符串这种数据类型,可以通过char的数组来替代

  • 数字0(和字符 '\0' 等价)结尾的char数组就是一个字符串,字符串是一种特殊的char的数组

  • 如果char数组没有以数字0结尾,那么就不是一个字符串,只是普通字符数组

#include <stdio.h>

// C语言中没有字符串这种类型, 看到都是char类型的数组
// 字符串是一种特殊的char的数组

int main()
{
    char arr[] = {'a', 'b', 'c', 'd', 'e', '\0'};
    printf("%s\n", arr);

    // int len = sizeof(arr) / sizeof(arr[0]);

    // for (int i = 0; i < len; i++)
    // {
    //     printf("%c\n",arr[i]);
    // }

    char arr2[] = "hello word";
    printf("%s\n", arr2);

    // \0之后的数据不可见, 表示结束
    char arr3[] = "hello我 \0 word \0 123";
    printf("%s\n", arr3);

    return 0;
}

6.2 字符指针(重点)

  • 字符指针可直接赋值为字符串,保存的实际上是字符串的首地址

  • 这时候,字符串指针所指向的内存不能修改,指针变量本身可以修改

#include <stdio.h>

int main()
{

    // 定义一个字符指针变量
    // 保存的是字符串的首地址(常量)
    // 把p当作一个变量就行
    char *p = "Hello, World!";
    // Bus error :10 内存指向未知空间 或者已经销毁的空间 或者越界
    //*p = "aaabbb"; // 不可以改变,因为*p是一个地址常量
    // char * p = const char * p

    // 而p是指针变量
    p = "aabbcc";

    printf("%s\n", p);

    return 0;
}

7. 字符的输入和输出

#include <stdio.h>

int main()
{
    char str[6] = {};
    // 不需要加 &,因为这是一个字符数组
    // 直接使用scanf不安全,越界问题(就算超过6个也可以输出)
    printf("请输入字符串: ");
    // 1. scanf("%s", str);
    // 2. gets也是不安全的
    // gets(str);

    // 3. fgets安全的,保障数据的准确性
    // stdin标准输入流
    // sizeof(str)判断的大小
    // 如果输入超过6个字符,只会显示5个字符,最后一个是\0
    fgets(str, sizeof(str), stdin);
    printf("str = %s\n", str);

    return 0;
}

8. 字符串常用库函数(string.h)

strlen(长度)

#include <stdio.h>
#include <string.h>

int main()
{

    // char *p = "abc d";
    char *p = "abc d\0";
    // 获取字符串长度
    // /0不算长度,/0后面的也不算长度
    printf("%s\n", p);
    int len = strlen(p);
    printf("%d\n", len);

    return 0;
}

strcpy(拷贝覆盖)

#include <stdio.h>
#include <string.h>

int main()
{

    char src[10] = "hello";
    char src2[10] = "world";

    // 拷贝 覆盖原来内容
    // 拷贝保留足够大的空间,否则溢出
    strcpy(src2, src);

    printf("%s\n", src2);  //hello

    return 0;
}

strcmp(比较)

#include <stdio.h>
#include <string.h>

int main()
{

    char str1[20] = "Worle";
    char str2[100] = "World";

    // 比较运算符:字符串中的字符逐个比较
    // 按照ASCII码进行比较的结果
    // 相等 0
    // s1 > s2 大于0
    // s1 < s2 小于0
    if (strcmp(str1, str2) == 0)
    {
        printf("相等\n");
    }
    else if (strcmp(str1, str2) > 0)
    {
        printf("s1 > s2\n");
    }
    else
    {
        printf("s1 < s2\n");
    }


    return 0;
}

strcat(拼接)

#include <stdio.h>
#include <string.h>

int main()
{

    char str1[] = "hello";
    char str2[] = "word";

    // 将str1内容拼接到str2的内容
    // 保证空间是足够的
    strcat(str2, str1);  // wordhello

    printf("%s\n", str2);

    return 0;
}

自实现 strlen

#include <stdio.h>

// 获取字符长度
// 字符数组形式/指针形式
int my_strlen(char *p)
{
    // 初始变量接收长度
    int len = 0;
    // 判断字符已经到最后 \0
    while (p[len] != '\0')
    {
        len++;
    }

    return len;
}

int main()
{

    char *p = "hello";
    printf("%d\n", my_strlen(p));

    return 0;
}
  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值