• C语言提高 (4) 第四天 数组与数组作为参数时的数组指针


    1昨日回顾

    const int

    和 int const是一样的

    const char *p;值不变

    char * const p; 指针不能变

    编译器对参数的退化:

    第三种模型:

    三级指针

    三级指针局部变量接收二级指针,并改变其内容

    2拆分字符串第一种API

    #define  _CRT_SECURE_NO_WARNINGS

    #include <stdio.h>

    #include <string.h>

     

     

    int splitString(char *str,char ch,char array[][30],int *count)

    {

        char *p = str;

        char *q = p;

        int temp_count = 0;

        int len = 0;

     

        if (str == NULL || array == NULL || count == NULL) {

            fprintf(stderr, "str == NULL || array == NULL || count == NULL");

            return -1;

        }

     

        // 在一个字符串中找到一个字符 找到了 返回第一个字符的地址 失败返回NULL

        //strchr(母串,字符)

        while (  (p = strchr(p, ch))!= NULL) {

            // 找到了

            strncpy(array[temp_count], q, p - q);

            array[temp_count][p - q] = '';

            temp_count++;

            p++;

            q = p;

            if (*p == '')

            {

                break;

            }

        }

       

        if (*q != '') {

            len = (str + strlen(str)) - q;

            strncpy(array[temp_count], q, len);

            array[temp_count][len] = '';

            temp_count++;

        }

        *count = temp_count;

        return 0;

    }

     

    int main(void)

    {

        char *str = "abcdef.acccd.eeee.aaaa.e3eeee.ssss";

        char array[10][30];

        int count = 0;

        int retn = 0;

        int i = 0;

     

        retn = splitString(str, ',', array, &count);

        if (retn < 0)

        {

            fprintf(stderr, "splitString er ");

            return -1;

        }

     

        for (i = 0; i < count; i++)

        {

            printf("array[%d]:%s ", i,array[i]);

        }

        return 0;

    }

    3拆分字符串第二种API

    #define _CRT_SECURE_NO_WARNINGS

    #include <stdio.h>

    #include <string.h>

     

     

    int spitString(char *str, char ch,char ***array_p,int *count)

    {

        // P,q指向str

        char *p= str;

        char *q = p;

        // 计数

        int temp_count = 0;

        // 二级指针

        char **array = NULL;

       

        int str_len = 0;

     

     

        if (str == NULL || array_p == NULL || count == NULL)

        {

            fprintf(stderr, "str == NULL || array_p == NULL || count == NULL ");

            return -1;

        }

     

     

        // 1 求出 字符串中 拆分的个数

        while ((p = strchr(p, ch)) != NULL) {

            temp_count++;

            p++;

            q = p;

            if (*p == '') {

            // 如果最后一位恰巧是ch那么+1就会是''

            break;}

        }

        // 如果有多余的

        if (*q != '') {

            temp_count++;

        }

        // 此时temp_count就是子字符串的个数

     

     

        // 2 根据个数开辟指针数组 在堆上

        // 在堆上开辟数组空间

        array = (char**)malloc((sizeof(char*) * temp_count));

     

        if (array == NULL)

        {

            fprintf(stderr, "malloc char **array error ");

            return -1;

        }

       

        // 清0

        memset(array, 0, sizeof(char *)*temp_count);

     

        // 3 拆分字符串,为每一个指针开辟堆空间 拷贝字符串

        p = str;

        q = p;

        temp_count = 0;

     

        while((p = strchr(p,ch))!= NULL){

            // 找到了

            str_len = p - q;

            // 数组的某个元素指向新分配的堆空间 堆空间大小是 sizeof(char) * str_len +1,+1是为了''

            array[temp_count] = (char*)malloc(sizeof(char)*str_len+1);

            if (array[temp_count] == NULL)

            {

                fprintf(stderr, "malloc array[%d] error ",temp_count);

                return -1;

            }

     

            // 将值拷贝到堆空间中

            strncpy(array[temp_count], q, str_len);

            // 最后要增添''

            array[temp_count][str_len] = '';

     

            // 重复这个过程

            temp_count++;

            p++;

            q = p;

            // 如果字符串最后一位恰好是要被替换的ch 那么+1后就会遇到

            if (*p == '')

            {

                break;

            }

        }

     

        // 如果字符串最后一位不是ch的情况,q指向不是''

        if (*q != '') {

            str_len = (str + strlen(str)) - q;

     

            array[temp_count] = (char *)malloc(sizeof(char)*(str_len + 1));

           

            // 任何分配空间都要做NULL值错误处理

            if (array[temp_count] == NULL) {

                fprintf(stderr, "malloc array[%d]error ", temp_count);

                return -1;

            }

     

            // 把最后一段复制到array中

            strncpy(array[temp_count], q, str_len);

            // 结尾补上''

            array[temp_count][str_len] = '';

       

            // 计数增加

            temp_count++;

        }

     

       

     

        if (array != NULL) {

            // 三级指针接数组地址

            *array_p = array;

            *count = temp_count;

        }

     

        return 0;

    }

     

    int main(void)

    {

        char *str = "abcdef,acccd,eeee,aaaa,e3eeee,ssss";

        char **array = NULL;

     

        int count = 0;

        int retn = 0;

        int i = 0;

     

        retn = spitString(str, ',', &array, &count);

     

        for (i = 0; i < count; i++)

        {

            printf("array[%d]:%s ", i, array[i]);

        }

     

        return 0;

    }

    3拆分字符串第二种API

    #define _CRT_SECURE_NO_WARNINGS

    #include <stdio.h>

    #include <string.h>

     

     

    void free_mem(char ***array_p,int count) {

     

        char **array = *array_p;

        int i = 0;

     

        if (array_p == NULL) {

            return;

        }

     

        if (array != NULL) {

            for (i = 0; i < count; i++) {

                if (array[i] != NULL) {

                    free(array[i]);

                    array[i] = NULL;

                }

            }

     

        free(array);

        *array_p = NULL;

     

        }

     

    }

     

    int spitString(char *str, char ch,char ***array_p,int *count)

    {

        // P,q指向str

        char *p= str;

        char *q = p;

        // 计数

        int temp_count = 0;

        // 二级指针

        char **array = NULL;

       

        int str_len = 0;

     

        int retn = 0;

     

     

        if (str == NULL || array_p == NULL || count == NULL)

        {

            fprintf(stderr, "str == NULL || array_p == NULL || count == NULL ");

            return -1;

        }

     

     

        // 1 求出 字符串中 拆分的个数

        while ((p = strchr(p, ch)) != NULL) {

            temp_count++;

            p++;

            q = p;

            if (*p == '') {

            // 如果最后一位恰巧是ch那么+1就会是''

            break;}

        }

        // 如果有多余的

        if (*q != '') {

            temp_count++;

        }

        // 此时temp_count就是子字符串的个数

     

     

        // 2 根据个数开辟指针数组 在堆上

        // 在堆上开辟数组空间

        array = (char**)malloc((sizeof(char*) * temp_count));

     

        if (array == NULL)

        {

            fprintf(stderr, "malloc char **array error ");

     

            retn = -1;

     

            goto END;

        }

       

        // 清0

        memset(array, 0, sizeof(char *)*temp_count);

     

        // 3 拆分字符串,为每一个指针开辟堆空间 拷贝字符串

        p = str;

        q = p;

        temp_count = 0;

     

        while((p = strchr(p,ch))!= NULL){

            // 找到了

            str_len = p - q;

            // 数组的某个元素指向新分配的堆空间 堆空间大小是 sizeof(char) * str_len +1,+1是为了''

            array[temp_count] = (char*)malloc(sizeof(char)*str_len+1);

            if (array[temp_count] == NULL)

            {

                fprintf(stderr, "malloc array[%d] error ",temp_count);

                retn = -1;

                goto END;

            }

     

            // 将值拷贝到堆空间中

            strncpy(array[temp_count], q, str_len);

            // 最后要增添''

            array[temp_count][str_len] = '';

     

            // 重复这个过程

            temp_count++;

            p++;

            q = p;

            // 如果字符串最后一位恰好是要被替换的ch 那么+1后就会遇到

            if (*p == '')

            {

                break;

            }

        }

     

        // 如果字符串最后一位不是ch的情况,q指向不是''

        if (*q != '') {

            str_len = (str + strlen(str)) - q;

     

            array[temp_count] = (char *)malloc(sizeof(char)*(str_len + 1));

           

            // 任何分配空间都要做NULL值错误处理

            if (array[temp_count] == NULL) {

                fprintf(stderr, "malloc array[%d]error ", temp_count);

                retn = -1;

                goto END;

            }

     

            // 把最后一段复制到array中

            strncpy(array[temp_count], q, str_len);

            // 结尾补上''

            array[temp_count][str_len] = '';

       

            // 计数增加

            temp_count++;

        }

     

       

     

        if (array != NULL) {

            // 三级指针接数组地址

            *array_p = array;

            *count = temp_count;

        }

     

        // 释放内存的步骤

    END:

        if (retn != 0) {

            // 已经出现错误了

            free_mem(&array, temp_count);

        }

     

        return 0;

    }

     

    int main(void)

    {

        char *str = "abcdef,acccd,eeee,aaaa,e3eeee,ssss";

        char **array = NULL;

     

        int count = 0;

        int retn = 0;

        int i = 0;

     

        retn = spitString(str, ',', &array, &count);

     

        for (i = 0; i < count; i++)

        {

            printf("array[%d]:%s ", i, array[i]);

        }

     

        free_mem(&array, count);

     

        if (array == NULL) {

            printf("arraykong");

        }

     

        return 0;

    }

    4 数组的概念

    数组:1. 连续的一大片内存空间

             2. 每个元素数据类型相同 (否则不知道该偏移多少

     

     

    #define _CRT_SECURE_NO_WARNINGS

    #include <stdio.h>

    #include <string.h>

     

    int main(void)

    {

        int a[10] = { 0 };

        int i = 0;

        int j = 0;

     

        /*  a是数组名 不能a++,,,,a=a+1;只能a[1]; *(a+i) //数组名是一个常量,是一个常指针,不能够被修改

                  数组名a本质是指向首元素地址 即&a[0]

            a+1 a是int *const p; a+1  4个字节的偏移

            &a+1 &a是int[10] *p    &a+1 4*10 = 40个字节的偏移

        */

       

        int aa[3][4] = {

            {3,5,4,3},

            {2,3,4,5}

        };

        // 初始化一个数组 不管是几维,如果初始化不完全,剩下的就全部填充0

     

        for (i = 0;i<3;i++)

        {

            for (j = 0; j < 4; j++)

            {

                printf("%d", aa[i][j]);

            }

            printf(" ");

        }

        printf(" ");

     

        int size = sizeof(aa); //再求一个二维数组的 数据类型大小 int[3][4]

       

        printf("size = %d ", size);

     

        // 如何定义指针?

        // 比较好理解的方法 (int[3][4]) *p = NULL;

        // 但是C语言中不能这么写,要把p放在数组前面 下面这样:

        int(*p)[3][4] = NULL; // 指向二维数组int[3][4]的指针

     

        printf("p: 0x%p, p+1:0x%p ", p, p + 1);

        // 0x0000 0030 (30是十进制的48)

     

        // 数组也是有数据类型的

        return 0;

    }

    5指针数组和数组指针的概念

    typedef unsigned int u32;

     

    int main(void)

    {

        //unsigned int a;

        //u32 b;

     

        //int a[3][4];

        int a[10];

     

        //typedef int[10] ARRAY_INT_10; 语法不能这么写,要用下面的写法:

        typedef int ARRAY_INT_10 [10]; //为 int[10]这种数组 起一个别名 ARRAY_INT_10

        ARRAY_INT_10 b_array; //int b_array[10]

        int i = 0;

     

        for (i = 0;i<10;i++)

        {

            b_array[i] = i;

        }

        for (i = 0;i<10;i++)

        {

            printf("%d ", b_array[i]);

        }

        ARRAY_INT_10 *p = &b_array;

        printf("p:%d,p+1:%d", p, p + 1);

     

        return 0;

    }

    指针数组:

    数组指针:

     数组指针的两种定义方式:

     

    6如何定义一个数组指针

    void test(){

        int aa; //0维数组 一级指针

        int aaa[10]; //一维数组,二级指针

        int aaaa[10][20]; //二维数组,三级指针

        int a[3][4];

        // a是一个指针 指向此二维数组首元素int[4]地址  int (*p)[4] == 二级指针 指向一维数组

        // &a也是一个指针 指向此二维数组int[3][4]的地址 int(*p)[3][4] == 三级指针 指向一个二维数组

     

        // 推论:一个数组指针,如果是几级指针,就是指向比他低一个维度的数组。

    }

     

    int main(void)

    {

        // 定义一个指针数组

        // 在栈上  用char* 还是void*都是一样的四个长度

        char *pinter_array[4] = { "asd",NULL,NULL,NULL };

        // 在堆上:

        char *heap_array =  malloc( 4 * sizeof(char*));

        for(int i = 0;i<4;i++)

        {

            heap_array[i] = NULL;

        }

     

     

        int i = 0;

     

        // 定义一个数组指针

        // 方法一

        // 直接定义一个数组类型

        typedef int (ARRAY_CHAR_4) [4];

        ARRAY_CHAR_4 array = { 1,2,3,4 }; 

        ARRAY_CHAR_4 *p = NULL

        p = &array;

     

        //方法二

        typedef int (*ARRAY_CHAR_4_POINTER) [4];

        ARRAY_CHAR_4_POINTER array_pointer = &array;

     

     

        // 方法三

        int(*array_p)[4] = NULL; // 直接定义一个数组指针

        array_p = &array;

     

     

        return 0;

    }

    7中午回顾

    1这个算法: 用两个指针

    2.养成好习惯:

    free之后一定要 null

    如果是NULL就return

    free函数的返回值是void 所以不知道有没有成功,

    自己接收的时候一定要用null来判断一下

     

    8多维数组做为函数参数

    (编译器并不是在栈中拷贝一份数组)

    (并不是这样,否则太浪费空间了)

    结论:当数组作为函数参数的时候,会退化成指针

    形参用了数组的元素的指针来接收数组

    (因为用了数组元素指针,就可以任意索引遍历数组

    (数组作为形参被编译器退化)

    。。。

    补充:

    总结:

    9指针数组的练习

    // 数组无论是几维数组 都是一块连续的内存空间

    10main函数的命令行参数

    判断数组长度了 除了 sizeof(p)/sizeof(*p) 这种方法,

    还有一种方法:

    就是在数组最后加一个NULL

    然后for循环,

    for(i = 0; arr[i] !=NULL;i++)

    {

            // 遍历

    }

    main函数入口的第三个参数是char *env[]

    (前两个是int argc,char* argv

    env指针数组就是这样实现的,最后一项默认是NULL

    所以可以打印出来:

    (环境变量:进程共享的变量

    在windows运行桌面上的应用程序时候其实就是相当于在cmd里输入….exe 可执行程序可以拿到环境变量,环境变量是key value值的形式,value值是一段字符串

     

  • 相关阅读:
    牛客OI周赛13-提高组 比赛总结
    CF1260C Infinite Fence 题解(扩欧)
    Comet OJ
    CF1151F Sonya and Informatics (计数dp+矩阵优化)
    矩阵 总结
    Educational Codeforces Round 77 比赛总结
    Codeforces 矩阵题 题单
    01欢迎进入软件构建的世界
    02用隐喻来充分地理解软件开发
    02Vs2013常用路径配置
  • 原文地址:https://www.cnblogs.com/eret9616/p/10368581.html
Copyright © 2020-2023  润新知