目录
字符串反转模型
和两头堵模型类似,解决问题分两种方法,一种是直接用指针进行反转;另一种借助栈模型的特性进行反转。
方法一:直接用指针进行反转
定义两个指向头和尾的指针,然后让他们依次交换指向的内容,就可以完成反转,
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");
}