[C语言]将字符串分割并且输出给二级指针内存模型(char **p模型)

题目

//有一个字符串符合以下特征(”abcdef,acccd,eeee,aaaa,e3eeeee,sssss,";),用逗号分割
赋值给char **p

main函数可以这样输出:
p[0] : “abcdef”
p[1] : “acccd”
p[2] : “eeee”
p[3] : “aaaa”
p[4] : “e3eeeee”
p[5] : “sssss”


题外话:二级指针三种内存模型

tips : 看到这就动笔画一下三种模型的内存四区示意图

1、指针数组模型

char *p[] = {"123", "456", "789"};

2、二维数组模型

char p[3][4] = {"123", "456", "789"};

3、手工二维内存(堆区开辟)

char **p = NULL;
p = (char **)malloc(sizeof(char *) * 3);	//相当于char arr[3];
if(int i = 0; i < 3; i++)
{
	p[i] = (char *)malloc(sizeof(char) * 4);	//相当于char buf[4];
}
p[0] = "123";
p[1] = "456";
p[2] = "789";

//用完还需要释放
if(int i = 0; i < 3; i++)
{
	free(p[i]);
}
free(p);
p = NULL;	//假如在函数中,这句话也可以不要,不会出现野指针的情况,函数结束系统自动出栈了

回到题目

0、函数调用模型的建立

int splitString(char *buf, char item, char ***arr, int rows)

依次为:输入字符串、输入分割参数、输入&输出二级指针模型的地址,二级指针的行

1、main函数调用

void main()
{
	int ret = 0, i = 0;
	char* p1 = "abcdef, acccd, eeee, aaaa, e3eeeee, sssss,  ";
	char cTem = ',';
	int nCount;

	char** p = NULL;  //char buf[][]    char *p[]

	ret = splitString(p1, cTem, &p, &nCount);
	if (ret != 0)
	{
		printf("fucn spitString() err: %d \n", ret);
		return;
	}

	//输出测试
	for (i = 0; i < nCount; i++)
	{
		printf("%s \n", p[i]);
	}

	system("pause");
	return;
}

2、分割函数

int splitString(char* buf, char item, char*** arr, int* rows)
{
	int ret = 0;
	//判断输入是否为空
	if (buf == NULL)
	{
		ret = -1;
		printf("func splitString err:%d buf == NULL", ret);
		return ret;
	}

	//二级指针,用于代替*arr操作,最后赋值*arr = tmpArr即可
	char** tmpArr = NULL;
	
	//两个指针变量
	char* p = NULL;
	char* pTmp = NULL;
	//同时指向buf的首地址
	p = buf;
	pTmp = buf;
	int tmpCount = 0;	//逗号的个数

	//找到有多少逗号
	do
	{
		p = strchr(p, item);	//找到item在字符串中第一次出现的索引,没有返回NULL
		if (p != NULL)
		{
			if ((p - pTmp) > 0)
			{
				tmpCount++;
				pTmp = p = p + 1;
			}
		}
		else
		{
			break;
		}
	} while (*p != '\0');

	
	tmpArr = (char**)malloc(sizeof(char*) * (tmpCount+1));	//多给一维,万一最后没有逗号,逗号就会比输出的字符串个数少一个
	if (tmpArr == NULL)
	{
		ret = -2;
		printf("fun splitString err: %d  tmpArr == NULL", ret);
		goto END;
	}
	/*************************************/

	tmpCount = 0;
	p = buf;
	pTmp = buf;

	//接下来分配堆区的内存给二维数组
	do
	{
		p = strchr(p, item);	
		if (p != NULL)
		{
			if ((p - pTmp) > 0)
			{
				int len = p - pTmp + 1;
				tmpArr[tmpCount] = (char*)malloc(sizeof(char) * len);
				if (tmpArr[tmpCount] == NULL)
				{
					ret = -3;
					printf("fun splitString err: %d  tmpArr[tmpCount] == NULL", ret);
					goto END;
				}
				strncpy(tmpArr[tmpCount], pTmp, p - pTmp);
				tmpArr[tmpCount][p - pTmp] = '\0';

				pTmp = p = p + 1;
				tmpCount++;
			}
		}
		else
		{
			break;
		}
	} while (*p != '\0');

END:
	//释放内存
	if (ret != 0)
	{
		FreeMem(&tmpArr, tmpCount);
	}
	else
	{
		*arr = tmpArr;
		*rows = tmpCount;	//输出二维数组的行数是逗号个数加一
	}

	return ret;
}

3、释放内存函数

void FreeMem(char*** p, int cnt)
{
	char** tmp = NULL;
	
	if (p == NULL)
	{
		return;
	}
	tmp = *p;
	if (tmp == NULL)
	{
		return;
	}
	else
	{
		for (int i = 0; i < cnt; i++)
		{
			if (tmp[i] != NULL)
			{
				free(tmp[i]);
			}
		}
		if (tmp != NULL)
		{
			free(tmp);
		}
	}
	*p = NULL;

}

总结

二维指针模型比较复杂

  1. 首先了解C风格字符串其实就是字符数组末尾为'\0'
  2. 接下来掌握三种内存模型的内存四区图画法
  3. 指针的精髓在于间接赋值,例如我想对int p;赋值,我用int *pp = &p;然后*pp做一系列balabala的操作,就是对p所代表的空间在操作;
  4. 堆区开辟内存要释放,不然占用内存,而且容易出现野指针的情况
  5. 野指针就是指,内存空间已经释放了,但是我的指针p的值还是指向的释放的内存空间,那里面已经没有值了,所以在free(p)操作后再加p = NULL;的操作
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值