#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//方法一:将第一个字符和最后一个互换,第二个和倒数第二个互换,如此依次循环下去
char *strrev1(const char *str)
{
int len = strlen(str);
char *tmp = (char*)malloc(len + 1);
strcpy(tmp,str);
int i = 0;
for (i = 0; i < len/2; ++i)
{
char c = tmp[i];
tmp[i] = tmp[len-i-1];
tmp[len-i-1] = c;
}
return tmp;
free(tmp);
}
//方法二:用指针实现
char *strrev2(const char *str)
{
char *tmp = (char*)malloc(strlen(str)+1);
strcpy(tmp,str);
char *ret = tmp;
char *p = tmp + strlen(str) - 1;
while(p > tmp)
{
char t = *tmp;
*tmp = *p;
*p = t;
--p;
++tmp;
}
return ret;
free(tmp);
}
//方法三:
char *strrev3(const char *str)
{
char *tmp = (char*)malloc(strlen(str)+1);
strcpy(tmp,str);
char *ret = tmp;
char *p = tmp + strlen(str) - 1;
while(p > tmp)
{
*p ^= *tmp;
*tmp ^= *p;
*p ^= *tmp;
--p;
++tmp;
}
return ret;
free(tmp);
}
/*
显然上面的两个解法中没有考虑时间和空间的优化,一个典型的优化策略就是两个字符交换的算法优化,我们可以完全不使用任何外部变量即完成两个字符(或者整数)的交换,这也是一个很经典的面试题目。特别是一些嵌入式硬件相关编程中经常要考虑寄存器的使用,因此经常有不使用任何第三个寄存器即完成两个寄存器数据的交换的题目。一般有两个解法,对应这里的解法三和解法四。*/
char *strrev4(const char *str)
{
char *tmp = (char*)malloc(strlen(str)+1);
strcpy(tmp,str);
char *ret = tmp;
char *p = tmp + strlen(str) - 1;
while(p > tmp)
{
*p = *p + *tmp;
*tmp = *p - *tmp;
*p = *p - *tmp;
--p;
++tmp;
}
return ret;
free(tmp);
}
/*还可以通过递归的思想来解决这个问题,思想很简单:每次交换首尾两个字符,中间部分则又变为和原来字符串同样的问题,因此可以通过递归的思想来解决这个问题,对应解法五的实现代码为:*/
char *strrev5(char *str,int len)
{
if(len <= 1)
{
return str;
}
char t = *str;
*str = *(str + len - 1);
*(str + len - 1) = t;
return (strrev5(str + 1,len - 2) - 1);
}
int main(int argc,char *argv[])
{
char *str = "ABCD1234efgh";
printf("%s/n",str);
char *str1 = strrev1(str);
printf("%s/n",str1);
char *str2 = strrev2(str1);
printf("%s/n",str2);
char *str3 = strrev3(str2);
printf("%s/n",str3);
char *str4 = strrev4(str3);
printf("%s/n",str4);
char *str5 = strrev5(str4,strlen(str));
printf("%s/n",str5);
return 0;
}
你就可以看到字符串"ABCD1234efgh"和"hgfe4321DCBA"交替输出了。
说明:1)这里解法中没有认真考虑输入字符串的合法性和特殊长度(如NULL、一个字符等)字符串的处理;2)前4个算法不改变输入字符串的值,解法五修改了输入字符串