Record16—项目开发中的字符串模型:字符串反转(逆序)模型

目录

字符串反转模型

方法一:直接用指针进行反转

方法二:借助堆栈特性进行反转

总体代码


字符串反转模型

和两头堵模型类似,解决问题分两种方法,一种是直接用指针进行反转;另一种借助栈模型的特性进行反转。

方法一:直接用指针进行反转

定义两个指向头和尾的指针,然后让他们依次交换指向的内容,就可以完成反转,

void main101()
{
	char buf[] = "abcdefg";
	int length = strlen(buf);


	char *p1 = buf;
	char *p2 = buf + length - 1;

	while (p1 < p2)
	{
		char c = *p1;
		*p1 = *p2;
		*p2 = c;
		++p1;
		--p2;
	}

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

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

 将其写成标准的封装函数,即为:

int inverse(char *str1)
{
	int length;
	char *p1;
	char *p2;

	if (str1 == NULL)
	{
		return -1;
	}

	length = strlen(str1);
	p1 = str1;
	p2 = str1 + length - 1;

	while (p1 < p2)
	{
		char c = *p1;
		*p1 = *p2;
		*p2 = c;
		++p1;
		--p2;
	}

}

void main()
{
	char buf[] = "abcdefg";
	int length = strlen(buf);
	inverse(buf);
	printf("buf:%s\n", buf);

	system("pause");
	return;
}

方法二:借助堆栈特性进行反转

 用递归的方法来反转字符串 ,借助函数参数,让字符串中的每个字符,依次入栈,然后,再依次出栈。代码如下:

void inverse02(char *p)
{
	if (p == NULL) // 递归结束的异常条件
	{
		return;
	}
	if (*p == '\0') // 递归结束的条件
	{
		return;
	}

	inverse02(p + 1); //注意,此时没有执行打印,而是执行了函数调用,让字符串的每一个地址入栈。
	printf("%c\n", *p);
}

void main102()
{
	char buf[] = "abcdefg";
	inverse02(buf);
	system("pause");
}

掌握递归,要牢牢把握两点:  

1.参数的入栈模型

 

2.  函数的调用模型

当存的时候,是按黑色线的方式进行,不断的存入,一旦触发递归结束条件,开始按红色线方向进行,开始返回。 放在上面代码中理解就是:

void inverse02(char *p)
{
	if (p == NULL) // 黑色斜线
	{
		return;
	}
	if (*p == '\0') // 黑色斜线
	{
		return;
	}

	inverse02(p + 1); //这行代码的是图中的黑色竖线
	printf("%c", *p); // 红色线
}

 

那么在以上基础上,再进行优化:我想把逆序的结果,给保存下来,该如何编写呢?初学者一般最容易想到的一个方法,就是定义一个全局变量:

char g_buf[1000];

void inverse03(char *p)
{
	if (p == NULL) // 递归结束的异常条件
	{
		return;
	}
	if (*p == '\0') // 递归结束的条件
	{
		return;
	}

	inverse03(p + 1); //注意,此时没有执行打印,而是执行了函数调用,让字符串的每一个地址入栈。
	//printf("%c\n", *p);

	//strcat(g_buf, p);
	//strcpy(g_buf, p, 1);//每次将结果都拷贝到g_buf中去。拷贝的时候拷贝被一个元素
	strncat(g_buf, p, 1);
}

void main103()
{
	char buf[] = "abcdefg";
	//inverse02(buf);

	memset(g_buf, 0, sizeof(g_buf));
	inverse03(buf);
	printf("g_buf:%s\n", g_buf);


	system("pause");
}

而在项目开发中,如果一个函数被多个进程同时执行的时候,如果这个函数使用了一个全局变量,那就存在一个加锁解锁的问题,以上面的定义全局变量那种方式来论,如果是在多个进程中进行,很可能出现,多个进程同时往g_buf里面拷贝数据,这样就会很糟糕了,所以,定义全局变量是一种有巨大风险的方式,应该避免掉。那么改为定义局部变量来进行:

void inverse04(char *p, char *bufresult)
{
	if (p == NULL || bufresult == NULL) // 递归结束的异常条件
	{
		return;
	}
	if (*p == '\0') // 递归结束的条件
	{
		return;
	}

	inverse04(p + 1, bufresult); //注意,此时没有执行打印,而是执行了函数调用,让字符串的每一个地址入栈。
	//printf("%c\n", *p);

	strncat(bufresult, p, 1);
}

void main104()
{
	char buf[] = "abcdefg";

	{
		char mybuf[1024] = {0};
		inverse04(buf, mybuf);
		printf("mybuf:%s\n", mybuf);
	}

	system("pause");
}

 

总体代码

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




//方法一:在同一个内存空间里面
void main101()
{
	char buf[] = "abcdefg";
	int length = strlen(buf);


	char *p1 = buf;
	char *p2 = buf + length - 1;

	while (p1 < p2)
	{
		char c = *p1;
		*p1 = *p2;
		*p2 = c;
		++p1;
		--p2;
	}

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

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


//当然,也可以将以上代码写成一个函数,这里就不演示了。

int inverse(char *str1)
{
	int length;
	char *p1;
	char *p2;

	if (str1 == NULL)
	{
		return -1;
	}

	length = strlen(str1);
	p1 = str1;
	p2 = str1 + length - 1;

	while (p1 < p2)
	{
		char c = *p1;
		*p1 = *p2;
		*p2 = c;
		++p1;
		--p2;
	}

}

void main102()
{
	char buf[] = "abcdefg";
	int length = strlen(buf);
	inverse(buf);
	printf("buf:%s\n", buf);

	system("pause");
	return;
}

//方法二,须掌握的三点:
//1.通过递归的方式逆序打印。
//2.递归和全局变量(把逆序打印的结果存入全局变量)
//3.递归和非全局变量,即递归做函数参数
void inverse02(char *p)
{
	if (p == NULL) // 递归结束的异常条件
	{
		return;
	}
	if (*p == '\0') // 递归结束的条件
	{
		return;
	}

	inverse02(p + 1); //注意,此时没有执行打印,而是执行了函数调用,让字符串的每一个地址入栈。
	printf("%c\n", *p);
}

void main103()
{
	char buf[] = "abcdefg";
	inverse02(buf);
	system("pause");
}

//改进,将递归结果保存,下面是用全局变量和递归进行的
char g_buf[1000];

void inverse03(char *p)
{
	if (p == NULL) // 递归结束的异常条件
	{
		return;
	}
	if (*p == '\0') // 递归结束的条件
	{
		return;
	}

	inverse03(p + 1); //注意,此时没有执行打印,而是执行了函数调用,让字符串的每一个地址入栈。
	//printf("%c\n", *p);

	//strcat(g_buf, p);
	//strcpy(g_buf, p, 1);//每次将结果都拷贝到g_buf中去。拷贝的时候拷贝被一个元素
	strncat(g_buf, p, 1);
}

void main104()
{
	char buf[] = "abcdefg";
	//inverse02(buf);

	memset(g_buf, 0, sizeof(g_buf));
	inverse03(buf);
	printf("g_buf:%s\n", g_buf);


	system("pause");
}

// 而在项目开发中,如果一个函数被多个进程同时执行的时候,
//如果这个函数使用了一个全局变量,那就存在一个加锁解锁的问题,
//以上面的定义全局变量那种方式来论,如果是在多个进程中进行,很可能出现,
//同时往g_buf里面拷贝数据,这样就会很糟糕了,所以,定义全局变量是一种有
//巨大风险的方式,应该避免掉。


void inverse04(char *p, char *bufresult)
{
	if (p == NULL || bufresult == NULL) // 递归结束的异常条件
	{
		return;
	}
	if (*p == '\0') // 递归结束的条件
	{
		return;
	}

	inverse04(p + 1, bufresult); //注意,此时没有执行打印,而是执行了函数调用,让字符串的每一个地址入栈。
	//printf("%c\n", *p);

	strncat(bufresult, p, 1);
}

void main()
{
	char buf[] = "abcdefg";

	{
		char mybuf[1024] = {0};
		inverse04(buf, mybuf);
		printf("mybuf:%s\n", mybuf);
	}

	system("pause");
}
发布了140 篇原创文章 · 获赞 6 · 访问量 4870

猜你喜欢

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