#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
int inverse(char *str1)
{
int length = 0;
char *p1 = NULL;
char *p2 = NULL;
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;
}
return 0;
}
int main(void)
{
char buf[] = "abcdefg"; //buf[] 会在张栈上对全局区的字符串拷贝。
inverse(buf);
printf("buf:%s\n", buf);
system("pause");
return 0;
}
这种模型是两个指针做分别指向字符串的开始和结尾,因为我们的buf是在栈上有内存,buf作为形参传入inverse函数的实参,我们可以在inverse函数内部,通过指针去修改buf的内存数据。
如果我们将main函数改变内存模型就会改变.
int main(void)
{
char *p = "abcdefg"; //p只有在栈上拥有指针的内存,而没有字符串的内存。
inverse(p);
printf("buf:%s\n", p);
system("pause");
return 0;
}
由内存模型可知由于是在全局区修改的字符串,因此会报错,程序荡机。
掌握递归需要掌握两点:函数参数的入栈模型和函数调用的压栈模型。我们对下面代码的参数压栈模型个函数调用模型进行分析。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
int inverse_stack(char *str1)
{
if (str1 == NULL) //递归结束的异常条件
{
return;
}
if (*str1 == '\0') //递归结束的正常条件
{
return;
}
inverse_stack(str1 + 1);
printf("%c", *str1);
}
int main(void)
{
char buf[] = "abcg"; //buf[] 会在栈上对全局区的字符串拷贝。
inverse_stack(buf);
system("pause");
return 0;
}
这个是函数实参str1指向字符g时的参数压栈模型。根据函数压栈模型来讲,当最后str1指向了字符'\0'时,最后一个压栈的函数会在if(str1 == '\0') {return;}语句块中结束函数,释放函数在栈上申请的内存,进入到倒数第二次压栈的函数(即图上的栈顶的函数),此时函数输出printf("%c",*str1) (str1指向了‘g’),然后依次执行,直到栈上的内存被释放的只有main函数。
函数的调用模型。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
char g_buf[1024];
int inverse_stack(char *str1)
{
if (str1 == NULL) //递归结束的异常条件
{
return;
}
if (*str1 == '\0') //递归结束的正常条件
{
return;
}
inverse_stack(str1 + 1);
strncat(g_buf, str1, 1);
}
int main(void)
{
char buf[] = "abcg"; //buf[] 会在张栈上对全局区的字符串拷贝。
memset(g_buf, 0, strlen(g_buf));
inverse_stack(buf);
printf("%s", g_buf);
system("pause");
return 0;
}
在项目开发里面,如果这函数被多个线程所调用,因为这个函数使用了全局变量,所以会出现加锁与解锁的问题,也有可能会使多个程序相同一块内存空间拷贝数据,出现乱序的问题。
我们需要避免这个问题。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
int inverse_stack(char *str1,char *buf)
{
if (str1 == NULL || buf == NULL) //递归结束的异常条件
{
return;
}
if (*str1 == '\0') //递归结束的正常条件
{
return;
}
inverse_stack(str1 + 1,buf);
strncat(buf, str1, 1);
}
int main(void)
{
char buf[] = "abcg"; //buf[] 会在张栈上对全局区的字符串拷贝。
char g_buf[1024] = {0};
inverse_stack(buf,g_buf);
printf("%s", g_buf);
system("pause");
return 0;
}
局部变量做函数参数,因为函数的压栈模型的原因,我们的g_buf不会再inverse函数调用结束前被释放。