Record15—项目开发中的字符串模型:两头堵模型

目录

两头堵模型

总体代码


两头堵模型

两个辅助指针变量,一个指向头部,一个指向尾部,然后左边的往右走,右边的往左走,做一些反转,逆序,按条件编程。直接举例,给出一个前后带空格的字符串,求不带空格的字符串长度。

那么,先来一个最基础的版本:

void main91()
{
	//求非空格的字符串长度
	char *p = "     abcdefg      ";
	int ncount = 0;

	int i, j = 0;
	i = 0;
	j = strlen(p)-1; //i作为指针指向头部;j作为指针要指向尾部,
	//而指向尾部的j是从0开始的,故须减1.

	while (isspace(p[i]) && p[i] != '\0')
	{
		i++;
	}

	while (isspace(p[j]) && p[j] != '\0')
	{
		j--;
	}

	ncount = j - i + 1;
	printf("ncount:%d\n", ncount);


	printf("hello...\n");
	system("pause");
	return;
}

思路就是前后两头堵,累计非空格字符的数量,这段代码一没用函数的思想封装,二没体现指针的作用,是非常low的写法,下面改进一下:

//求非空格的字符串长度
int getCount2(char *str, int *pCount)
{
	
	char *p = str;
	int ncount = 0;
	int i, j = 0; //所有的定义都必须写在一块儿。

	if (str == NULL || pCount == NULL)
	{
		return -1;
	}


	i = 0;
	j = strlen(p) - 1; //i作为指针指向头部;j作为指针要指向尾部,
	//而指向尾部的j是从0开始的,故须减1.

	while (isspace(p[i]) && p[i] != '\0')
	{
		i++;
	}

	while (isspace(p[j]) && p[j] != '\0')
	{
		j--;
	}

	ncount = j - i + 1;

	*pCount = ncount;
	return 0;
}

void main92()
{
	char *p = "     abcdefg      ";
	int num = 0;
	getCount2(p, &num);
	printf("num:%d\n", num);
	system("pause");

}

经过改进,思路上没有任何的区别,但将执行部分封装成函数,和测试部分分开,这就是很标准的解法了,需要注意的是主演是中:

	getCount2(p, &num);
	printf("num:%d\n", num);

而被调用函数中:

	*pCount = ncount;
	return 0;

并非return的是*pCount,而是“return 0”,这种写法要体会,如果在主函数中不以被调用函数的输出作为传值,如“p=getCount2( , , )”,那就没必要注意return了,还有一点的就是被调函数传入的值通过形参,实参的传递,已经传到主函数中去了,不会随着被调函数的析构而消失,num经过被调函数前后,值也发生了变化。

那么顺着这个思路,还可以再进行提高,比如,我不要求统计字符串的数量了,我想把不包含空格的字符给输出出来,该怎么做呢?可以这么做:

//那么在之前的基础上,再进行些优化,比如,如果想把字符串前面的空格
//和后面的空格都求出来,那该怎么做呢?

//去除字符串前后的空格,中间不管。
int trimSpace(char *str, char *newstr)
{

	char *p = str;
	int ncount = 0;
	int i, j = 0; //所有的定义都必须写在一块儿。

	if (str == NULL && newstr == NULL)
	{
		printf("func trimSpace() \n");
		return -1;
	}


	i = 0;
	j = strlen(p) - 1; //i作为指针指向头部;j作为指针要指向尾部,
	//而指向尾部的j是从0开始的,故须减1.

	while (isspace(p[i]) && p[i] != '\0')
	{
		i++;
	}

	while (isspace(p[j]) && p[j] != '\0')
	{
		j--;
	}

	ncount = j - i + 1;
	strcpy(newstr, str + i, ncount);

	newstr[ncount] = '\0';

	return 0;
}

void main93()
{
	char *p = "     abcdefg      ";
	char buf[1024] = { 0 };
	trimSpace(p, buf);
	printf("buf:%s\n", buf);
	system("pause");

}

通过这条语句:

	strcpy(newstr, str + i, ncount);

将不包含空格的字符部分拷贝到新的内存空间,并输出,就可以了,需要注意的是,定义新的内存空间的时候,必须保证新的内存空间是可以被修改的,所定义的空间位置也肯定不能是全局区了,而是,定义了一个数组,定义在了可修改区。

	char buf[1024] = { 0 };

那么,我还可以继续优化,不想占用新的内存空间,而是,想将新得到的字符串,还放到原来的位置,这个怎么办呢?

//在这个基础上还可以继续优化,我不拷贝到一个新的内存空间中去了,
//而是,拷贝到原本的内存空间中去。

int trimSpace02(char *str)
{

	char *p = str;
	int ncount = 0;
	int i, j = 0; //所有的定义都必须写在一块儿。

	if (str == NULL)
	{
		printf("func trimSpace() \n");
		return -1;
	}


	i = 0;
	j = strlen(p) - 1; //i作为指针指向头部;j作为指针要指向尾部,
	//而指向尾部的j是从0开始的,故须减1.

	while (isspace(p[i]) && p[i] != '\0')
	{
		i++;
	}

	while (isspace(p[j]) && p[j] != '\0')
	{
		j--;
	}

	ncount = j - i + 1;
	strcpy(str, str + i, ncount); //直接把原来的新开的内存空间,用原来的内存空间的前一个位置代替。
	//相当于把原来的空格给擦除,拷贝到自己原来的内存空间当中去。
	str[ncount] = '\0';

	return 0;
}

//但是,这样做的前提是指针指向的内存空间可以被修改才行!
//故需要显式的分配内存才行

void main()
{
	//char *p = "     abcdefg      ";  //分配在常量区(全局区)
	//trimSpace02(p);
	 
	char buf[1024] = "     abcdefg      ";  //分配在临时区
	trimSpace02(buf);

	printf("p:%s\n", buf);
	system("pause");

}

//所以,指针可不可以被修改,是设计者应该告诉使用者的迫切消息,
//故一般在定义的函数的声明里面用关键字“const”来告诉使用者,这个指针,
//这块儿指针可不可以被修改。

如上,就是实现方法,通过,

	strcpy(str, str + i, ncount); 
	str[ncount] = '\0';

就将新的不含空格的字符串,拷贝到原来的位置中去了,但是,千万注意:这样做的前提是指针指向的内存空间可以被修改才行!故需要显式的分配内存才行,初学者往往很容易在这犯错误,如果不可以被修改,那很容易就报错了。

	//char *p = "     abcdefg      ";  //分配在常量区(全局区)
	//trimSpace02(p);
	 
	char buf[1024] = "     abcdefg      ";  //分配在临时区
	trimSpace02(buf);

在主函数部分中,如果依旧沿用原来的通过定义常量的方式定义,肯定会报错,故还是定义成buf[1024],字符数组的方式才行。

 所以,指针可不可以被修改,是设计者应该告诉使用者的迫切消息,故一般在定义的函数的声明里面用关键字“const”来告诉使用者,这个指针,这块儿指针可不可以被修改。

总体代码

#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

void main91()
{
	//求非空格的字符串长度
	char *p = "     abcdefg      ";
	int ncount = 0;

	int i, j = 0;
	i = 0;
	j = strlen(p)-1; //i作为指针指向头部;j作为指针要指向尾部,
	//而指向尾部的j是从0开始的,故须减1.

	while (isspace(p[i]) && p[i] != '\0')
	{
		i++;
	}

	while (isspace(p[j]) && p[j] != '\0')
	{
		j--;
	}

	ncount = j - i + 1;
	printf("ncount:%d\n", ncount);


	printf("hello...\n");
	system("pause");
	return;
}


//求非空格的字符串长度
int getCount2(char *str, int *pCount)
{
	
	char *p = str;
	int ncount = 0;
	int i, j = 0; //所有的定义都必须写在一块儿。

	if (str == NULL || pCount == NULL)
	{
		return -1;
	}


	i = 0;
	j = strlen(p) - 1; //i作为指针指向头部;j作为指针要指向尾部,
	//而指向尾部的j是从0开始的,故须减1.

	while (isspace(p[i]) && p[i] != '\0')
	{
		i++;
	}

	while (isspace(p[j]) && p[j] != '\0')
	{
		j--;
	}

	ncount = j - i + 1;

	*pCount = ncount;
	return 0;
}

void main92()
{
	char *p = "     abcdefg      ";
	int num = 0;
	getCount2(p, &num);
	printf("num:%d\n", num);
	system("pause");

}


//那么在之前的基础上,再进行些优化,比如,如果想把字符串前面的空格
//和后面的空格都求出来,那该怎么做呢?

//去除字符串前后的空格,中间不管。
int trimSpace(char *str, char *newstr)
{

	char *p = str;
	int ncount = 0;
	int i, j = 0; //所有的定义都必须写在一块儿。

	if (str == NULL && newstr == NULL)
	{
		printf("func trimSpace() \n");
		return -1;
	}


	i = 0;
	j = strlen(p) - 1; //i作为指针指向头部;j作为指针要指向尾部,
	//而指向尾部的j是从0开始的,故须减1.

	while (isspace(p[i]) && p[i] != '\0')
	{
		i++;
	}

	while (isspace(p[j]) && p[j] != '\0')
	{
		j--;
	}

	ncount = j - i + 1;
	strcpy(newstr, str + i, ncount);

	newstr[ncount] = '\0';

	return 0;
}

void main93()
{
	char *p = "     abcdefg      ";
	char buf[1024] = { 0 };
	trimSpace(p, buf);
	printf("buf:%s\n", buf);
	system("pause");

}


//在这个基础上还可以继续优化,我不拷贝到一个新的内存空间中去了,
//而是,拷贝到原本的内存空间中去。

int trimSpace02(char *str)
{

	char *p = str;
	int ncount = 0;
	int i, j = 0; //所有的定义都必须写在一块儿。

	if (str == NULL)
	{
		printf("func trimSpace() \n");
		return -1;
	}


	i = 0;
	j = strlen(p) - 1; //i作为指针指向头部;j作为指针要指向尾部,
	//而指向尾部的j是从0开始的,故须减1.

	while (isspace(p[i]) && p[i] != '\0')
	{
		i++;
	}

	while (isspace(p[j]) && p[j] != '\0')
	{
		j--;
	}

	ncount = j - i + 1;
	strcpy(str, str + i, ncount); //直接把原来的新开的内存空间,用原来的内存空间的前一个位置代替。
	//相当于把原来的空格给擦除,拷贝到自己原来的内存空间当中去。
	str[ncount] = '\0';

	return 0;
}

//但是,这样做的前提是指针指向的内存空间可以被修改才行!
//故需要显式的分配内存才行

void main()
{
	//char *p = "     abcdefg      ";  //分配在常量区(全局区)
	//trimSpace02(p);
	 
	char buf[1024] = "     abcdefg      ";  //分配在临时区
	trimSpace02(buf);

	printf("p:%s\n", buf);
	system("pause");

}

//所以,指针可不可以被修改,是设计者应该告诉使用者的迫切消息,
//故一般在定义的函数的声明里面用关键字“const”来告诉使用者,这个指针,
//这块儿指针可不可以被修改。
发布了140 篇原创文章 · 获赞 6 · 访问量 4871

猜你喜欢

转载自blog.csdn.net/qq_17846375/article/details/103693512