c语言实现动态数组

前言

最近研究二级指针,发现了二级指针配合realloc函数其实可以用来实现动态数组

这篇博文我只实现动态数组的push_back操作,就是在数组的末端增加一个元素

修正一个思想

c语言的函数参数,是不能在函数内部被修改的!!!因为传进来的参数,是拷贝构造
我们平时说"传指针就可以在函数内修改参数",实际上是误导学生的说法,
因为这个时候,函数的参数是指针,而这时候你会发现,你函数返回以后,这个指针变量没有被修改,也就是说,函数的参数还是没有被修改!!!
一旦学生遇到一个"需要操作指针变量"的函数时会不知所措被水淹没,这种思想荼毒很深!!!

应该这么记忆(三点)

1.函数函数参数,是不能在函数内部被修改的
2.但是,在函数内部仍然使用可以用某个变量的指针,直接指向函数外部,修改这个外部变量的值
3.函数的参数,可以是你需要修改的那个变量的指针

套用上面的新思想,我来设计这个动态数组的push函数

我们所希望的push函数的使用方法(函数my_push_back3)

int main()
{
    char *line = (char *)malloc(6); 
    //strcpy(line, "CHINA");//注意"\0"的问题,CHINA有5个字符,但是c语言自带的strcpy会给最后一个字符加上\0,原本我malloc写的是5,但是发现如果写5,strcpy不会出错,但是realloc会报错!!!!不知道这是为什么
    line = (char *)realloc(line, 7);
    

    char *arr = (char *)malloc(4); 
	arr[0] = 'a';
    arr[1] = 'b';
    arr[2] = 'c';
    arr[3] = '\0';
    printf("%s\n",arr);
	int num = my_strlen(arr);
    printf("array length %d\n",num);

	my_push_back3(&arr, 'e');
    printf("%s\n",arr);

    return(0);
    
}

push函数设计

功能:

已知char数组的首地址array(char*类型)
使用realloc为这个char数组重新分配空间(让他的size + 1)
在数组的倒数第2位写入要"push"的字符(char类型)
在数组的倒数第1位写入字符串结束符’\0’

出现问题:

realloc在某些情况下,会重新分配内存空间的首地址,并不是原来的那个地址
建议详细阅读realloc的性质
https://www.runoob.com/cprogramming/c-function-realloc.html
所以array的值需要被更新

解决问题思路:

利用"新思想",既然我们希望在函数内修改变量array的值,
我们可以把函数参数用于接收变量arr的指针(char**类型)

于是我写出了以下函数

char* my_push_back3(char** array, char c){
    size_t size = my_strlen(*array);
    size += 1;//这个size是不包含"\0"的size,所以,在分配内存空间realloc时,还需要再加1
    *array = (char*)realloc(*array, size+1);
	*(*array+(size+1-2)) = c;//思考为什么不是**(array+(size+1-2)) (同样是char类型)
    *(*array+(size+1-1)) = '\0';
    return *array;
}

分析*(*array+(size+1-1))

这个表达式想达到的目标:

用char** 类型指针(也就是array),访问char数组中任意元素的值

所需知识点:

1.使用*(char*类型 + num)这个公式
可以访问char数组的任意下标的元素

思想:

我们需要凑成如上这个"用指针访问数组的形式"
已知条件array,是char**类型,我们先把他变为 char*类型,于是加个"*"号就变成 *array

有了char* 进一步凑公式
*(*array + num),这就能访问char数组的任意一个值了

知识点解析:

为什么*(char*类型 + num)可以访问数组元素???
推荐大家系统学习这个博客的知识
https://blog.csdn.net/daiyutage/article/details/8604720

完整代码

#include
#include 
#include 

size_t my_strlen(const char* pSrc)//通过字符指针可以测出字符数组大小
{
	size_t ret = 0;
	if (NULL == pSrc)
	{
		return ret;
	}

	while (*pSrc++)//注意,*pSrc++返回的是自加之前的值,"++"优先级高于"*",所以while中是" *(pSrc++) ",也就是指针自加后,再取值,自加的仍然是"指针",也就是指针向后移动一格
	{//本质上,这个函数是利用了char数组作为字符串时,约定最后一位是"\0"而生效的
		ret++;
	}//看来,确实不存在任何一种方法能测出c语言数组的大小,只能再分配内存空间时记住这个大小
	return ret;
}

char* my_push_back2(char* array, char c){
    size_t size = my_strlen(array);
    size += 1;//这个size是不包含"\0"的size,所以,在分配内存空间realloc时,还需要再加1
    array = (char*)realloc(array, size+1);
	array[(size+1)-2] = c;
    array[(size+1)-1] = '\0';
    return array;
}

char* my_push_back3(char** array, char c){
    size_t size = my_strlen(*array);
    size += 1;//这个size是不包含"\0"的size,所以,在分配内存空间realloc时,还需要再加1
    *array = (char*)realloc(*array, size+1);
	*(*array+(size+1-2)) = c;//思考为什么不是**(array+(size+1-2)) (同样是char类型)
    *(*array+(size+1-1)) = '\0';
    return *array;
}
/*
修正一个思想
c语言的函数参数,是不能在函数内部被修改的!!!因为传进来的参数,是拷贝构造
我们平时说"传指针就可以在函数内修改参数",实际上是误导学生的说法,
因为这个时候,函数的参数是指针,而这时候你会发现,你函数返回以后,这个指针变量没有被修改,也就是说,函数的参数还是没有被修改!!!!
一旦学生遇到一个"需要操作指针变量"的函数时,这种思想荼毒很深!!!!!

应该这么记忆(三点)
1.函数函数参数,是不能在函数内部被修改的
2.但是,在函数内部仍然使用可以用某个变量的指针,直接指向函数外部,修改这个外部变量的值
3.函数的参数,可以是你需要修改的那个变量的指针

套用上面的新思想,我来设计这个动态数组的push函数
push函数设计:
功能:
已知char数组的首地址array(char*类型)
使用realloc为这个char数组重新分配空间(让他的size + 1)
在数组的倒数第2位写入要"push"的字符(char类型)
在数组的倒数第1位写入字符串结束符'\0'

出现问题:
realloc在某些情况下,重新分配内存空间的首地址,并不是原来的那个地址
所以array的值需要被更新

解决问题思路:
利用"新思想",既然我们希望在函数内修改变量array的值,
我们可以把函数参数用于接收变量arr的指针(char**类型)


分析*(*array+(size+1-1))
这个表达式想达到的目标:
用char**类型指针(也就是array),访问char数组中任意元素的值
所需知识点:
1.*(char*类型 + num)可以访问char数组的任意下标
思想:
我们需要凑成如上这个"用指针访问数组的形式"
已知条件array,是char**类型,我们先把他变为 char*类型,于是加个"*"号变成 "*array"
有了char* 进一步凑公式
*(*array + num),这就是能访问char数组的任意一个值了

知识点解析:
为什么*(char*类型 + num)可以访问数组元素??
推荐大家系统学习这个博客的知识
https://blog.csdn.net/daiyutage/article/details/8604720
*/


int main()
{
    char *line = (char *)malloc(6); 
    //strcpy(line, "CHINA");//注意"\0"的问题,CHINA有5个字符,但是c语言自带的strcpy会给最后一个字符加上\0,原本我malloc写的是5,但是发现如果写5,strcpy不会出错,但是realloc会报错!!!!不知道这是为什么
    line = (char *)realloc(line, 7);
    

    char *arr = (char *)malloc(4); 
	arr[0] = 'a';
    arr[1] = 'b';
    arr[2] = 'c';
    arr[3] = '\0';
    printf("%s\n",arr);
	int num = my_strlen(arr);
    printf("array length %d\n",num);

    arr = my_push_back2(arr, 'd');
    printf("%s\n",arr);
	my_push_back3(&arr, 'e');
    printf("%s\n",arr);

    return(0);
    
}

你可能感兴趣的:(c语言)